diff --git a/Cargo.lock b/Cargo.lock
index b4b50c9d1..36bb8b2e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -152,9 +152,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "async-compression"
-version = "0.4.22"
+version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59a194f9d963d8099596278594b3107448656ba73831c9d8c783e613ce86da64"
+checksum = "b37fc50485c4f3f736a4fb14199f6d5f5ba008d7f28fe710306c92780f004c07"
dependencies = [
"brotli",
"flate2",
@@ -566,9 +566,9 @@ dependencies = [
[[package]]
name = "brotli"
-version = "7.0.0"
+version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd"
+checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -577,9 +577,9 @@ dependencies = [
[[package]]
name = "brotli-decompressor"
-version = "4.0.3"
+version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd"
+checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -1478,9 +1478,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
-version = "0.2.9"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59ec30f7142be6fe14e1b021f50b85db8df2d4324ea6e91ec3e5dcde092021d0"
+checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
@@ -1493,9 +1493,9 @@ dependencies = [
[[package]]
name = "jiff-static"
-version = "0.2.9"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "526b834d727fd59d37b076b0c3236d9adde1b1729a4361e20b2026f738cc1dbe"
+checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
dependencies = [
"proc-macro2",
"quote",
@@ -1791,9 +1791,9 @@ checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
[[package]]
name = "oxc"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "548086420c5c78546c7417384689af59ed11dbe9462e8bfef42636be0f545b96"
+checksum = "339134dd7e4bb36c2d0e97601fe4193b37649f729e94e7c26667feecd439b27e"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1834,9 +1834,9 @@ dependencies = [
[[package]]
name = "oxc_allocator"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acaf33eacde1fca8fdb26655d7486842a8106916bc3855265607db2b4a4eaec4"
+checksum = "56c3dd872f5f819775c28163977399a1dd4f2177f3745dcb1bfd4214bae27e43"
dependencies = [
"allocator-api2",
"bumpalo",
@@ -1848,9 +1848,9 @@ dependencies = [
[[package]]
name = "oxc_ast"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3044daf0f6b02f27330954141d799f9206e04b9175a3f4fa199f78c5ef46b2b4"
+checksum = "a1bebb401e36d73f35400ee9609ab6372b457543ce7bb1ef17c922235f24ba7b"
dependencies = [
"bitflags",
"cow-utils",
@@ -1865,9 +1865,9 @@ dependencies = [
[[package]]
name = "oxc_ast_macros"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ee5d1546ecb309530b30b48f1aefefad7e6d53b8502e7b91b20d6a523af270e"
+checksum = "3b997c2a787321814d6e92f212486b4d590af4dbfff5c2265d3b0386e016eafe"
dependencies = [
"proc-macro2",
"quote",
@@ -1876,9 +1876,9 @@ dependencies = [
[[package]]
name = "oxc_ast_visit"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b29d0e9e05d2638317c39470b5a528e268fc088ae1e3fda26b049661f2de25ad"
+checksum = "e1ee363bd1ff2000ae2a1052bb4d68e827e62f76e0139449ad1301ad9adc6ac4"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1888,9 +1888,9 @@ dependencies = [
[[package]]
name = "oxc_cfg"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b3740da43d597136474fa738bafb697c8469b8ecd9c256819ae443ec91a67aa"
+checksum = "77cb606168f768c747885ae48272287a028de5374db865c29d6d307d3b601a97"
dependencies = [
"bitflags",
"itertools",
@@ -1903,9 +1903,9 @@ dependencies = [
[[package]]
name = "oxc_codegen"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee5e197f8bed070bcc6e9744a7a5f91bc4ff250543f07849567e6e602383c7db"
+checksum = "4afef88d94fe9eee073332e3f908bd429baa989300d83152dab10dad99bd2a66"
dependencies = [
"bitflags",
"cow-utils",
@@ -1924,15 +1924,15 @@ dependencies = [
[[package]]
name = "oxc_data_structures"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ca20f4fc9af4f462bfc6bbca60e3f4c2ca9c4f09e99363c0c85d90bb936641c"
+checksum = "235fe6251a3f06813e77b45f3cd9c7ec5d0a23741c33f6c308b5af393d5d2409"
[[package]]
name = "oxc_diagnostics"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50e5ef1106d01ade76eec600e5b0da38932f555d1cb661f0d5ec7f3d717da22d"
+checksum = "2cd0f62519773d942baf1a17474e53b535182182f2cb41319ad1c2782e34310d"
dependencies = [
"cow-utils",
"oxc-miette",
@@ -1940,9 +1940,9 @@ dependencies = [
[[package]]
name = "oxc_ecmascript"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76b1ea0ef90fda6b68127181b3b136b21041a595e8c2028c4e08fcf85f99a10c"
+checksum = "5d073fdd2a3e1adb63731faab3c3861d0f9244cc15e88453d78460a4b2a604ca"
dependencies = [
"cow-utils",
"num-bigint",
@@ -1954,9 +1954,9 @@ dependencies = [
[[package]]
name = "oxc_estree"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b9ce9584683d43622ef4b66bd605ce9878f3bf7468b9b59ad041f33af13c34d"
+checksum = "59df015cfd58d084b27d049281835094556a4469db3e2ac45b0676336e0aeed8"
[[package]]
name = "oxc_index"
@@ -1966,9 +1966,9 @@ checksum = "2fa07b0cfa997730afed43705766ef27792873fdf5215b1391949fec678d2392"
[[package]]
name = "oxc_mangler"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20c80a552dc097088d466679bcaba2576bbe88a430ca9c5b0cb67e23787aaa7a"
+checksum = "7dfc3363726f4ade77ba4d9e56cc38cc306436feee7b72e1c69436fb30c02b9b"
dependencies = [
"fixedbitset",
"itertools",
@@ -1983,9 +1983,9 @@ dependencies = [
[[package]]
name = "oxc_minifier"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5e504ac83f23ff755eae4ebd6291258b44e05cf58379e1fe1c00b1007e41f29"
+checksum = "f095580f12a6277d4cb532310ba95cc6d1f719b6c59341fb392b71e37d1207e6"
dependencies = [
"cow-utils",
"oxc_allocator",
@@ -2005,9 +2005,9 @@ dependencies = [
[[package]]
name = "oxc_parser"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "688491b2dfe8049a6410bc6b92f71e75bebfe9a1f352a64084a62069cd644e7f"
+checksum = "8d54fd003e5347dcb5ccdcc96cb283bf32a648ff291912b5a6e5e718b3359935"
dependencies = [
"bitflags",
"cow-utils",
@@ -2028,9 +2028,9 @@ dependencies = [
[[package]]
name = "oxc_regular_expression"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be6231edf43b8ca0fa8edad93b0b8e9067a3991ea2d8aa9f22a4c8fa464f267"
+checksum = "5e6e8058355e43a2388112eddf73031d8749b40255ad6f3a824e35fe0c6addec"
dependencies = [
"oxc_allocator",
"oxc_ast_macros",
@@ -2044,9 +2044,9 @@ dependencies = [
[[package]]
name = "oxc_semantic"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f5c80c996fafc27a8444732bbba06f1de3eb488c585d65293a4b40b089ff564"
+checksum = "3f9f297db174c99b43e1b268b0960dcc588767093575cc39bb5517196a7a21d3"
dependencies = [
"itertools",
"oxc_allocator",
@@ -2080,9 +2080,9 @@ dependencies = [
[[package]]
name = "oxc_span"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bce0a945765d00dd9ee0bfdc38fa265008e66f919157894c0383c525d026511f"
+checksum = "69575b94d8fdac097784abf48a5e43ee38375aa377f8e9bb8bc80f2ef3d2269c"
dependencies = [
"compact_str",
"oxc-miette",
@@ -2093,9 +2093,9 @@ dependencies = [
[[package]]
name = "oxc_syntax"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12b876a00908cb1fc6648823d7d8579a69af1c5a5c6d4cf6135040e09f41d116"
+checksum = "32c4940ed3e38ce51fb6bc3e880edb815182bdcdc19c6dc110857625aac9c9a7"
dependencies = [
"bitflags",
"cow-utils",
@@ -2114,9 +2114,9 @@ dependencies = [
[[package]]
name = "oxc_traverse"
-version = "0.64.0"
+version = "0.65.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c25f3da54211abd4b6ff1390a0f28d42b2128cb33f4b38edbdc5cb71bc3d3c"
+checksum = "5f8868dcb4ac2cd1e08dadbf34cd4fd9bbf36b70ef64dfa3376e1042a9f705a3"
dependencies = [
"compact_str",
"itoa",
@@ -2718,9 +2718,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
-version = "1.4.4"
+version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1ee1aca2bc74ef9589efa7ccaa0f3752751399940356209b3fd80c078149b5e"
+checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
dependencies = [
"libc",
]
diff --git a/Cargo.toml b/Cargo.toml
index ff71cc8c5..1e0211f4b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,7 +35,7 @@ clap = { version = "4.5.37", features = ["derive", "string"] }
color-eyre = "0.6.3"
derive_deref = "1.1.1"
fjall = "2.9.0"
-jiff = "0.2.9"
+jiff = "0.2.10"
log = { version = "0.4.27" }
minreq = { version = "2.13.4", features = ["https", "serde_json"] }
rayon = "1.10.0"
diff --git a/crates/brk_server/Cargo.toml b/crates/brk_server/Cargo.toml
index 78d9706ee..dda8db847 100644
--- a/crates/brk_server/Cargo.toml
+++ b/crates/brk_server/Cargo.toml
@@ -21,7 +21,7 @@ color-eyre = { workspace = true }
jiff = { workspace = true }
log = { workspace = true }
minreq = { workspace = true }
-oxc = { version = "0.64.0", features = ["codegen", "minifier"] }
+oxc = { version = "0.65.0", features = ["codegen", "minifier"] }
serde = { workspace = true }
tokio = { version = "1.44.2", features = ["full"] }
tower-http = { version = "0.6.2", features = ["compression-full", "trace"] }
diff --git a/websites/kibo.money/index.html b/websites/kibo.money/index.html
index ed6630a2b..f23778541 100644
--- a/websites/kibo.money/index.html
+++ b/websites/kibo.money/index.html
@@ -1607,7 +1607,7 @@
diff --git a/websites/kibo.money/packages/solid-signals/wrapper.js b/websites/kibo.money/packages/solid-signals/wrapper.js
index 1ab5f67bd..ca6375409 100644
--- a/websites/kibo.money/packages/solid-signals/wrapper.js
+++ b/websites/kibo.money/packages/solid-signals/wrapper.js
@@ -21,11 +21,11 @@ const importSignals = import("./v0.2.4-treeshaked/script.js").then(
(compute, effect) => {
let dispose = /** @type {VoidFunction | null} */ (null);
// @ts-ignore
- _signals.createEffect(compute, (v) => {
+ _signals.createEffect(compute, (v, oldV) => {
dispose?.();
signals.createRoot((_dispose) => {
dispose = _dispose;
- effect(v);
+ return effect(v, oldV);
});
signals.onCleanup(() => dispose?.());
});
diff --git a/websites/kibo.money/scripts/main.js b/websites/kibo.money/scripts/main.js
index 3361e0cd1..0b72d49df 100644
--- a/websites/kibo.money/scripts/main.js
+++ b/websites/kibo.money/scripts/main.js
@@ -223,7 +223,7 @@ function createUtils() {
* @param {Object} arg
* @param {string | HTMLElement} arg.inside
* @param {string} arg.title
- * @param {VoidFunction} arg.onClick
+ * @param {(event: MouseEvent) => void} arg.onClick
*/
createButtonElement({ inside: text, onClick, title }) {
const button = window.document.createElement("button");
@@ -438,47 +438,62 @@ function createUtils() {
};
},
/**
- * @param {Object} param0
- * @param {string} param0.name
- * @param {string} param0.value
+ * @template {string} Name
+ * @template {string} Value
+ * @template {Value | {name: Name; value: Value}} T
+ * @param {T} arg
*/
- createOption({ name, value }) {
+ createOption(arg) {
const option = window.document.createElement("option");
- option.value = value;
- option.innerText = name;
+ if (typeof arg === "object") {
+ option.value = arg.value;
+ option.innerText = arg.name;
+ } else {
+ option.value = arg;
+ option.innerText = arg;
+ }
return option;
},
/**
* @template {string} Name
* @template {string} Value
- * @template {{name: Name; value: Value}} T
+ * @template {Value | {name: Name; value: Value}} T
* @param {Object} args
- * @param {string} args.id
+ * @param {string} [args.id]
* @param {boolean} [args.deep]
- * @param {(({name: Name; value: Value} & T) | {name: string; list: ({name: Name; value: Value} & T)[]})[]} args.list
+ * @param {readonly ((T) | {name: string; list: T[]})[]} args.list
* @param {Signal
} args.signal
*/
createSelect({ id, list, signal, deep = false }) {
const select = window.document.createElement("select");
- select.name = id;
- select.id = id;
+
+ if (id) {
+ select.name = id;
+ select.id = id;
+ }
/** @type {Record} */
const setters = {};
list.forEach((anyOption, index) => {
- if ("list" in anyOption) {
+ if (typeof anyOption === "object" && "list" in anyOption) {
const { name, list } = anyOption;
const optGroup = window.document.createElement("optgroup");
optGroup.label = name;
select.append(optGroup);
list.forEach((option) => {
optGroup.append(this.createOption(option));
- setters[option.value] = () => signal.set(() => option);
+ const key = /** @type {string} */ (
+ typeof option === "object" ? option.value : option
+ );
+ setters[key] = () => signal.set(() => option);
});
} else {
select.append(this.createOption(anyOption));
- setters[anyOption.value] = () => signal.set(() => anyOption);
+ const key = /** @type {string} */ (
+ typeof anyOption === "object" ? anyOption.value : anyOption
+ );
+ setters[key] = () => signal.set(() => anyOption);
}
if (deep && index !== list.length - 1) {
select.append(window.document.createElement("hr"));
@@ -493,7 +508,10 @@ function createUtils() {
}
});
- select.value = signal().value;
+ const initialSignal = signal();
+ const initialValue =
+ typeof initialSignal === "object" ? initialSignal.value : initialSignal;
+ select.value = String(initialValue);
return { select, signal };
},
@@ -706,7 +724,7 @@ function createUtils() {
id.includes("ohlc")
) {
unit = "USD";
- } else if (id.includes("count")) {
+ } else if (id.includes("count") || id.match(/v[1-3]/g)) {
unit = "Count";
} else if (id.includes("date")) {
unit = "Date";
@@ -720,7 +738,7 @@ function createUtils() {
unit = "WU";
} else if (id.includes("vbytes") || id.includes("vsize")) {
unit = "vB";
- } else if (id.includes("version") || id.match(/v[1-3]/g)) {
+ } else if (id.includes("version")) {
unit = "Version";
} else if (id === "value") {
unit = "Sats";
@@ -839,6 +857,20 @@ function createUtils() {
return v;
},
},
+ vecIds: {
+ /**
+ * @param {VecId[]} v
+ */
+ serialize(v) {
+ return v.join(",");
+ },
+ /**
+ * @param {string} v
+ */
+ deserialize(v) {
+ return /** @type {VecId[]} */ (v.split(","));
+ },
+ },
number: {
/**
* @param {number} v
@@ -1273,7 +1305,16 @@ function createVecsResources(signals, utils) {
return {
url: utils.api.genUrl(index, id, from),
fetched,
- async fetch() {
+ /**
+ * Defaults
+ * - from: -10_000
+ * - to: undefined
+ *
+ * @param {Object} [args]
+ * @param {number} [args.from]
+ * @param {number} [args.to]
+ */
+ async fetch(args) {
if (loading) return fetched();
if (at) {
const diff = new Date().getTime() - at.getTime();
@@ -1288,7 +1329,8 @@ function createVecsResources(signals, utils) {
},
index,
id,
- from,
+ args?.from ?? from,
+ args?.to,
)
);
at = new Date();
@@ -1381,7 +1423,7 @@ function getElements() {
selectors: getElementById("frame-selectors"),
style: getComputedStyle(window.document.documentElement),
charts: getElementById("charts"),
- database: getElementById("database"),
+ table: getElementById("table"),
simulation: getElementById("simulation"),
};
}
@@ -1956,7 +1998,7 @@ function main() {
undefined
);
let firstTimeLoadingChart = true;
- let firstTimeLoadingDatabase = true;
+ let firstTimeLoadingTable = true;
let firstTimeLoadingSimulation = true;
signals.createEffect(options.selected, (option) => {
@@ -2008,13 +2050,13 @@ function main() {
break;
}
- case "database": {
- element = elements.database;
+ case "table": {
+ element = elements.table;
- if (firstTimeLoadingDatabase) {
- const databaseScript = import("./database.js");
- utils.dom.importStyleAndThen("/styles/database.css", () =>
- databaseScript.then(({ init }) =>
+ if (firstTimeLoadingTable) {
+ const tableScript = import("./table.js");
+ utils.dom.importStyleAndThen("/styles/table.css", () =>
+ tableScript.then(({ init }) =>
signals.runWithOwner(owner, () =>
init({
colors,
@@ -2022,13 +2064,14 @@ function main() {
signals,
utils,
vecsResources,
+ option,
vecIdToIndexes,
}),
),
),
);
}
- firstTimeLoadingDatabase = false;
+ firstTimeLoadingTable = false;
break;
}
diff --git a/websites/kibo.money/scripts/options.js b/websites/kibo.money/scripts/options.js
index 41a93a9fe..66be3f0f7 100644
--- a/websites/kibo.money/scripts/options.js
+++ b/websites/kibo.money/scripts/options.js
@@ -63,13 +63,13 @@
*
* @typedef {Required> & ProcessedChartOptionAddons & ProcessedOptionAddons} ChartOption
*
- * @typedef {Object} PartialDatabaseOptionSpecific
- * @property {"database"} kind
+ * @typedef {Object} PartialTableOptionSpecific
+ * @property {"table"} kind
* @property {string} title
*
- * @typedef {PartialOption & PartialDatabaseOptionSpecific} PartialDatabaseOption
+ * @typedef {PartialOption & PartialTableOptionSpecific} PartialTableOption
*
- * @typedef {Required & ProcessedOptionAddons} DatabaseOption
+ * @typedef {Required & ProcessedOptionAddons} TableOption
*
* @typedef {Object} PartialSimulationOptionSpecific
* @property {"simulation"} kind
@@ -88,9 +88,9 @@
*
* @typedef {Required & ProcessedOptionAddons} UrlOption
*
- * @typedef {PartialChartOption | PartialDatabaseOption | PartialSimulationOption | PartialUrlOption} AnyPartialOption
+ * @typedef {PartialChartOption | PartialTableOption | PartialSimulationOption | PartialUrlOption} AnyPartialOption
*
- * @typedef {ChartOption | DatabaseOption | SimulationOption | UrlOption} Option
+ * @typedef {ChartOption | TableOption | SimulationOption | UrlOption} Option
*
* @typedef {Object} PartialOptionsGroup
* @property {string} name
@@ -187,17 +187,18 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {VecIdSumBase & TotalVecIdBase} args.concat
+ * @param {string} [args.name]
*/
- function createSumTotalSeries({ concat }) {
+ function createSumTotalSeries({ concat, name }) {
return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([
{
key: `${concat}-sum`,
- title: "Sum",
+ title: name ? `${name} Sum` : "Sum",
color: colors.bitcoin,
},
{
key: `total-${concat}`,
- title: "Total",
+ title: name ? `Total ${name}` : "Total",
color: colors.offBitcoin,
defaultActive: false,
},
@@ -439,41 +440,42 @@ function createPartialOptions(colors) {
],
},
{
- name: "Version",
- tree: [
- {
- name: "1",
- title: "Transaction V1 Count",
- bottom: [
- createBaseSeries({
- key: "tx-v1",
- name: "Count",
- }),
- ...createSumTotalSeries({ concat: "tx-v1" }),
- ],
- },
- {
- name: "2",
- title: "Transaction V2 Count",
- bottom: [
- createBaseSeries({
- key: "tx-v2",
- name: "Count",
- }),
- ...createSumTotalSeries({ concat: "tx-v2" }),
- ],
- },
- {
- name: "3",
- title: "Transaction V3 Count",
- bottom: [
- createBaseSeries({
- key: "tx-v3",
- name: "Count",
- }),
- ...createSumTotalSeries({ concat: "tx-v3" }),
- ],
- },
+ name: "Versions",
+ title: "Transaction Versions",
+ bottom: [
+ // {
+ // name: "1",
+ // title: "Transaction V1 Count",
+ // bottom: [
+ createBaseSeries({
+ key: "tx-v1",
+ name: "v1 Count",
+ }),
+ ...createSumTotalSeries({ concat: "tx-v1", name: "v1" }),
+ // ],
+ // },
+ // {
+ // name: "2",
+ // title: "Transaction V2 Count",
+ // bottom: [
+ createBaseSeries({
+ key: "tx-v2",
+ name: "v2 Count",
+ }),
+ ...createSumTotalSeries({ concat: "tx-v2", name: "v2" }),
+ // ],
+ // },
+ // {
+ // name: "3",
+ // title: "Transaction V3 Count",
+ // bottom: [
+ createBaseSeries({
+ key: "tx-v3",
+ name: "v3 Count",
+ }),
+ ...createSumTotalSeries({ concat: "tx-v3", name: "v3" }),
+ // ],
+ // },
],
},
],
@@ -529,9 +531,9 @@ function createPartialOptions(colors) {
],
},
{
- kind: "database",
- title: "Database",
- name: "Database",
+ kind: "table",
+ title: "Table",
+ name: "Table",
},
{
name: "Simulations",
@@ -875,8 +877,8 @@ export function initOptions({
/** @type {Option} */
let option;
- if ("kind" in anyPartial && anyPartial.kind === "database") {
- option = /** @satisfies {DatabaseOption} */ ({
+ if ("kind" in anyPartial && anyPartial.kind === "table") {
+ option = /** @satisfies {TableOption} */ ({
kind: anyPartial.kind,
id: anyPartial.kind,
name: anyPartial.name,
diff --git a/websites/kibo.money/scripts/database.js b/websites/kibo.money/scripts/table.js
similarity index 52%
rename from websites/kibo.money/scripts/database.js
rename to websites/kibo.money/scripts/table.js
index 9c740097f..3b30474a7 100644
--- a/websites/kibo.money/scripts/database.js
+++ b/websites/kibo.money/scripts/table.js
@@ -3,22 +3,36 @@
/**
* @param {Object} args
* @param {VecIdToIndexes} args.vecIdToIndexes
+ * @param {Option} args.option
* @param {Utilities} args.utils
* @param {Signals} args.signals
* @param {VecsResources} args.vecsResources
*/
-function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
+function createTable({
+ utils,
+ vecIdToIndexes,
+ signals,
+ option,
+ vecsResources,
+}) {
const indexToVecIds = createIndexToVecIds(vecIdToIndexes);
const serializedIndexes = createSerializedIndexes();
/** @type {SerializedIndex} */
const defaultSerializedIndex = "height";
- const serializedIndex = signals.createSignal({
- name: /** @type {SerializedIndex} */ (defaultSerializedIndex),
- value: String(serializedIndexToIndex(defaultSerializedIndex)),
- });
+ /** @type {Signal} */
+ const serializedIndex = signals.createSignal(
+ /** @type {SerializedIndex} */ (defaultSerializedIndex),
+ {
+ save: {
+ ...utils.serde.string,
+ keyPrefix: "table",
+ key: "index",
+ },
+ },
+ );
const index = signals.createMemo(() =>
- serializedIndexToIndex(serializedIndex().name),
+ serializedIndexToIndex(serializedIndex()),
);
const table = window.document.createElement("table");
@@ -28,21 +42,35 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
addRandomCol: undefined,
};
- signals.createEffect(index, (index) => {
- table.innerHTML = "";
+ signals.createEffect(index, (index, prevIndex) => {
+ if (prevIndex !== undefined) {
+ utils.url.resetParams(option);
+ }
+ const possibleVecIds = indexToVecIds[index];
+
+ const columns = signals.createSignal(/** @type {VecId[]} */ ([]), {
+ equals: false,
+ save: {
+ ...utils.serde.vecIds,
+ keyPrefix: `table-${serializedIndex()}`,
+ key: `columns`,
+ },
+ });
+ columns.set((l) => l.filter((id) => possibleVecIds.includes(id)));
+
+ signals.createEffect(columns, (columns) => {
+ console.log(columns);
+ });
+
+ table.innerHTML = "";
const thead = window.document.createElement("thead");
table.append(thead);
const trHead = window.document.createElement("tr");
- const selects = signals.createSignal(
- /** @type {HTMLSelectElement[]} */ ([]),
- {
- equals: false,
- },
- );
thead.append(trHead);
const tbody = window.document.createElement("tbody");
table.append(tbody);
+
const rowElements = signals.createSignal(
/** @type {HTMLTableRowElement[]} */ ([]),
);
@@ -50,11 +78,12 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
/**
* @param {Object} args
* @param {HTMLSelectElement} args.select
- * @param {VoidFunction} [args.onLeft]
- * @param {VoidFunction} [args.onRight]
- * @param {VoidFunction} [args.onRemove]
+ * @param {Unit} [args.unit]
+ * @param {(event: MouseEvent) => void} [args.onLeft]
+ * @param {(event: MouseEvent) => void} [args.onRight]
+ * @param {(event: MouseEvent) => void} [args.onRemove]
*/
- function addThCol({ select, onLeft, onRight, onRemove }) {
+ function addThCol({ select, onLeft, onRight, onRemove, unit: _unit }) {
const th = window.document.createElement("th");
th.scope = "col";
trHead.append(th);
@@ -62,6 +91,9 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
div.append(select);
const strip = window.document.createElement("div");
const unit = window.document.createElement("span");
+ if (_unit) {
+ unit.innerHTML = _unit;
+ }
const moveLeft = utils.dom.createButtonElement({
inside: "←",
title: "Move column to the left",
@@ -94,22 +126,24 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
};
}
- const { select } = utils.dom.createSelect({
- id: "col-index",
- list: serializedIndexes.map((serializedIndex) => ({
- name: serializedIndex,
- value: String(serializedIndexToIndex(serializedIndex)),
- })),
- signal: serializedIndex,
+ addThCol({
+ ...utils.dom.createSelect({
+ list: serializedIndexes,
+ signal: serializedIndex,
+ }),
+ unit: "Index",
});
- const th = addThCol({ select });
- th.setUnit("Index");
+
+ let from = 0;
+ let to = 0;
vecsResources
- .getOrCreate(index, serializedIndex().name)
+ .getOrCreate(index, serializedIndex())
.fetch()
.then((vec) => {
if (!vec) return;
+ from = /** @type {number} */ (vec[0]);
+ to = /** @type {number} */ (vec.at(-1)) + 1;
const trs = /** @type {HTMLTableRowElement[]} */ ([]);
for (let i = vec.length - 1; i >= 0; i--) {
const value = vec[i];
@@ -117,184 +151,182 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
trs.push(tr);
tbody.append(tr);
const th = window.document.createElement("th");
- th.innerHTML = String(value);
+ th.innerHTML = serializeValue({
+ value,
+ unit: "Index",
+ });
th.scope = "row";
tr.append(th);
}
rowElements.set(() => trs);
});
- const columnIds = signals.createSignal(/** @type {VecId[]} */ ([]), {
- equals: false,
- });
-
const owner = signals.getOwner();
- const possibleVecids = indexToVecIds[index];
-
- obj.addRandomCol = function () {
+ /**
+ * @param {VecId} vecId
+ * @param {number} [_colIndex]
+ */
+ function addCol(vecId, _colIndex = columns().length) {
signals.runWithOwner(owner, () => {
- const vecId =
- possibleVecids[Math.round(Math.random() * possibleVecids.length)];
- const colIndex = signals.createSignal(columnIds().length);
+ /** @type {VoidFunction | undefined} */
+ let dispose;
+ signals.createRoot((_dispose) => {
+ dispose = _dispose;
- const vecIdOption = signals.createSignal({
- name: vecId,
- value: vecId,
- });
- const { select } = utils.dom.createSelect({
- id: `col-${colIndex() + 1}`,
- list: possibleVecids.map((vecId) => ({
+ const vecIdOption = signals.createSignal({
name: vecId,
value: vecId,
- })),
- signal: vecIdOption,
- });
- selects.set((l) => {
- l.push(select);
- return l;
- });
- /**
- * @param {boolean} right
- */
- function createMoveColumnFunction(right) {
- return () =>
- colIndex.set((oldI) => {
- const newI = oldI + (right ? 1 : -1);
- const currentSelect = selects()[oldI];
- const currentSelectSibling = currentSelect.nextSibling;
- const newSelect = selects()[newI];
- [selects()[oldI], selects()[newI]] = [
- selects()[newI],
- selects()[oldI],
- ];
- console.log(oldI, newI, selects());
- const newSelectSibling = newSelect.nextSibling;
- newSelectSibling?.before(currentSelect);
- currentSelectSibling?.before(newSelect);
- return newI;
- });
- }
- const th = addThCol({
- select,
- onLeft: createMoveColumnFunction(false),
- onRight: createMoveColumnFunction(true),
- });
+ });
+ const { select } = utils.dom.createSelect({
+ list: possibleVecIds.map((vecId) => ({
+ name: vecId,
+ value: vecId,
+ })),
+ signal: vecIdOption,
+ });
- signals.createEffect(rowElements, (rowElements) => {
- if (!rowElements.length) return;
- for (let i = 0; i < rowElements.length; i++) {
- const td = window.document.createElement("td");
- rowElements[i].append(td);
- }
-
- signals.createEffect(vecIdOption, ({ name: vecId }) => {
- const unit = utils.vecidToUnit(vecId);
- th.setUnit(unit);
-
- const valuesPromise = vecsResources
- .getOrCreate(index, vecId)
- .fetch();
-
- columnIds.set((l) => {
- if (columnIds().length === colIndex()) {
- l.push(vecId);
- } else {
- l[colIndex()] = vecId;
- }
- console.log(l);
+ if (_colIndex === columns().length) {
+ columns.set((l) => {
+ l.push(vecId);
return l;
});
+ }
- valuesPromise.then((vec) => {
- if (!vec) return;
- // const diff = vec.length - rowElements.length;
- for (let i = 0; i < rowElements.length; i++) {
- const iRev = vec.length - 1 - i;
- const value = vec[iRev];
+ const colIndex = signals.createSignal(_colIndex);
- /** @type {string | number | undefined} */
- let serialized;
+ /**
+ * @param {boolean} right
+ * @returns {(event: MouseEvent) => void}
+ */
+ function createMoveColumnFunction(right) {
+ return () => {
+ const oldColIndex = colIndex();
+ const newColIndex = oldColIndex + (right ? 1 : -1);
- if (typeof value !== "number") {
- serialized = value;
- } else if (value !== 18446744073709552000) {
- if (
- unit === "USD" ||
- unit === "Difficulty" ||
- unit === "sat/vB"
- ) {
- serialized = value.toLocaleString("en-us", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
- } else if (unit === "BTC") {
- serialized = value.toLocaleString("en-us", {
- minimumFractionDigits: 8,
- maximumFractionDigits: 8,
- });
- } else {
- serialized = value.toLocaleString("en-us");
- }
- }
+ const currentTh = /** @type {HTMLTableCellElement} */ (
+ trHead.childNodes[oldColIndex + 1]
+ );
+ const oterTh = /** @type {HTMLTableCellElement} */ (
+ trHead.childNodes[newColIndex + 1]
+ );
- signals.runWithOwner(owner, () => {
- signals.createEffect(colIndex, (colIndex) => {
- // @ts-ignore
- rowElements[i].childNodes[colIndex + 1].innerHTML =
- serialized;
- });
- });
+ if (right) {
+ oterTh.after(currentTh);
+ } else {
+ oterTh.before(currentTh);
}
- });
+
+ columns.set((l) => {
+ [l[oldColIndex], l[newColIndex]] = [
+ l[newColIndex],
+ l[oldColIndex],
+ ];
+ return l;
+ });
+
+ const rows = rowElements();
+ for (let i = 0; i < rows.length; i++) {
+ const element = rows[i].childNodes[oldColIndex + 1];
+ const sibling = rows[i].childNodes[newColIndex + 1];
+ const temp = element.textContent;
+ element.textContent = sibling.textContent;
+ sibling.textContent = temp;
+ }
+ };
+ }
+
+ const th = addThCol({
+ select,
+ unit: utils.vecidToUnit(vecId),
+ onLeft: createMoveColumnFunction(false),
+ onRight: createMoveColumnFunction(true),
+ onRemove: () => {
+ const ci = colIndex();
+ trHead.childNodes[ci + 1].remove();
+ columns.set((l) => {
+ l.splice(ci, 1);
+ return l;
+ });
+ const rows = rowElements();
+ for (let i = 0; i < rows.length; i++) {
+ rows[i].childNodes[ci + 1].remove();
+ }
+ dispose?.();
+ },
+ });
+
+ signals.createEffect(columns, () => {
+ colIndex.set(Array.from(trHead.children).indexOf(th.element) - 1);
+ });
+
+ console.log(colIndex());
+
+ signals.createEffect(rowElements, (rowElements) => {
+ if (!rowElements.length) return;
+ for (let i = 0; i < rowElements.length; i++) {
+ const td = window.document.createElement("td");
+ rowElements[i].append(td);
+ }
+
+ signals.createEffect(
+ () => vecIdOption().name,
+ (vecId, prevVecId) => {
+ const unit = utils.vecidToUnit(vecId);
+ th.setUnit(unit);
+
+ const vec = vecsResources.getOrCreate(index, vecId);
+
+ vec.fetch({ from, to });
+
+ columns.set((l) => {
+ const i = l.indexOf(prevVecId ?? vecId);
+ if (i === -1) {
+ l.push(vecId);
+ } else {
+ l[i] = vecId;
+ }
+ return l;
+ });
+
+ signals.createEffect(vec.fetched, (vec) => {
+ if (!vec) return;
+
+ const thIndex = colIndex() + 1;
+
+ for (let i = 0; i < rowElements.length; i++) {
+ const iRev = vec.length - 1 - i;
+ const value = vec[iRev];
+ // @ts-ignore
+ rowElements[i].childNodes[thIndex].innerHTML =
+ serializeValue({
+ value,
+ unit,
+ });
+ }
+ });
+
+ return () => vecId;
+ },
+ );
});
});
- });
- // signals.runWithOwner(owner, () => {
- // const thIndex = thHead.length;
- // const possibleVecids = indexToVecIds[index()];
- // const i = Math.round(Math.random() * possibleVecids.length);
- // const vecId = signals.createSignal({
- // name: possibleVecids[i],
- // value: possibleVecids[i],
- // });
- // const th = addThCol();
- // const { select } = utils.dom.createSelect({
- // id: `col-${vecId}`,
- // list: possibleVecids.map((vecId) => ({
- // name: vecId,
- // value: vecId,
- // })),
- // signal: vecId,
- // });
- // th.append(select);
- // signals.createEffect(
- // () => /** @type {const} */ ([index(), vecId(), rowElements()]),
- // ([index, vecId, trsBody]) => {
- // if (!trsBody.length) return;
- // vecsResources
- // .getOrCreate(index, vecId.name)
- // .fetch()
- // .then((vec) => {
- // if (!vec) return;
- // console.log({ vec, trsBody, index });
- // for (let i = 0; i < vec.length; i++) {
- // const iRev = vec.length - 1 - i;
- // const value = vec[iRev];
- // const td = window.document.createElement("td");
- // td.innerHTML = String(value);
- // trsBody[i].append(td);
- // }
- // });
- // },
- // );
- // });
+ signals.onCleanup(() => {
+ dispose?.();
+ });
+ });
+ }
+
+ columns().forEach((vecId, colIndex) => addCol(vecId, colIndex));
+
+ obj.addRandomCol = function () {
+ const vecId =
+ possibleVecIds[Math.floor(Math.random() * possibleVecIds.length)];
+ addCol(vecId);
};
- // setTimeout(addCol, 2000);
- // addRandomCol();
- // addRandomCol();
- // addRandomCol();
+
+ return () => index;
});
return obj;
@@ -305,6 +337,7 @@ function createTable({ utils, vecIdToIndexes, signals, vecsResources }) {
* @param {Colors} args.colors
* @param {Signals} args.signals
* @param {Utilities} args.utils
+ * @param {Option} args.option
* @param {Elements} args.elements
* @param {VecsResources} args.vecsResources
* @param {VecIdToIndexes} args.vecIdToIndexes
@@ -313,13 +346,14 @@ export function init({
colors,
elements,
signals,
+ option,
utils,
vecsResources,
vecIdToIndexes,
}) {
- const parent = elements.database;
+ const parent = elements.table;
const { headerElement } = utils.dom.createHeader({
- title: "Database",
+ title: "Table",
});
parent.append(headerElement);
@@ -331,6 +365,7 @@ export function init({
utils,
vecIdToIndexes,
vecsResources,
+ option,
});
div.append(table.element);
@@ -458,3 +493,30 @@ function createIndexToVecIds(vecIdToIndexes) {
});
return indexToVecIds;
}
+
+/**
+ * @param {Object} args
+ * @param {number | OHLCTuple} args.value
+ * @param {Unit} args.unit
+ */
+function serializeValue({ value, unit }) {
+ if (typeof value !== "number") {
+ return String(value);
+ } else if (value !== 18446744073709552000) {
+ if (unit === "USD" || unit === "Difficulty" || unit === "sat/vB") {
+ return value.toLocaleString("en-us", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+ } else if (unit === "BTC") {
+ return value.toLocaleString("en-us", {
+ minimumFractionDigits: 8,
+ maximumFractionDigits: 8,
+ });
+ } else {
+ return value.toLocaleString("en-us");
+ }
+ } else {
+ return "";
+ }
+}
diff --git a/websites/kibo.money/styles/database.css b/websites/kibo.money/styles/table.css
similarity index 97%
rename from websites/kibo.money/styles/database.css
rename to websites/kibo.money/styles/table.css
index c3e1af25a..fde7553c7 100644
--- a/websites/kibo.money/styles/database.css
+++ b/websites/kibo.money/styles/table.css
@@ -1,4 +1,4 @@
-#database {
+#table {
width: 100%;
display: flex;
flex-direction: column;
@@ -39,6 +39,10 @@
padding: 0.25rem 1rem;
}
+ td {
+ text-transform: lowercase;
+ }
+
th:first-child {
padding-left: var(--main-padding);
}