@orbinum/sdk 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +51 -49
- package/dist/index.mjs +51 -49
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -4515,9 +4515,9 @@ declare function windowSizeForCounter(counter: number): number;
|
|
|
4515
4515
|
*
|
|
4516
4516
|
* The expensive part (one ECDH per memo) runs in the injected decrypt pool —
|
|
4517
4517
|
* Web Workers when the host provides a factory, a yielded loop otherwise — while
|
|
4518
|
-
* the cheap bookkeeping (cursor, on-chain set, counters) stays here.
|
|
4519
|
-
*
|
|
4520
|
-
* and CPU.
|
|
4518
|
+
* the cheap bookkeeping (cursor, on-chain set, counters) stays here. Both
|
|
4519
|
+
* transports download through the same PREFETCH-deep sliding window
|
|
4520
|
+
* (`runPrefetched`), overlapping network and CPU.
|
|
4521
4521
|
*/
|
|
4522
4522
|
|
|
4523
4523
|
/**
|
|
@@ -4552,8 +4552,11 @@ interface ScanOutcome {
|
|
|
4552
4552
|
onChainHexes: Set<string>;
|
|
4553
4553
|
/** Highest leafIndex seen — the next incremental scan resumes after it. */
|
|
4554
4554
|
maxLeafIndex: number | undefined;
|
|
4555
|
+
/** Hints walked this call, across both transports. */
|
|
4555
4556
|
scanned: number;
|
|
4557
|
+
/** Notes recovered that the vault did not hold yet. */
|
|
4556
4558
|
found: number;
|
|
4559
|
+
/** Hints carrying no memo or ephemeral key — nothing to decrypt. */
|
|
4557
4560
|
noMemo: number;
|
|
4558
4561
|
/**
|
|
4559
4562
|
* Hints whose memo did not open with this wallet's keys.
|
|
@@ -4564,6 +4567,7 @@ interface ScanOutcome {
|
|
|
4564
4567
|
* recovers nothing while this equals the whole pool has a key problem.
|
|
4565
4568
|
*/
|
|
4566
4569
|
decryptFailed: number;
|
|
4570
|
+
/** Notes recovered that the vault already held. */
|
|
4567
4571
|
alreadyPresent: number;
|
|
4568
4572
|
/** Hints discarded by the view-tag fast filter (no AEAD decrypt attempted). */
|
|
4569
4573
|
tagFiltered: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -4515,9 +4515,9 @@ declare function windowSizeForCounter(counter: number): number;
|
|
|
4515
4515
|
*
|
|
4516
4516
|
* The expensive part (one ECDH per memo) runs in the injected decrypt pool —
|
|
4517
4517
|
* Web Workers when the host provides a factory, a yielded loop otherwise — while
|
|
4518
|
-
* the cheap bookkeeping (cursor, on-chain set, counters) stays here.
|
|
4519
|
-
*
|
|
4520
|
-
* and CPU.
|
|
4518
|
+
* the cheap bookkeeping (cursor, on-chain set, counters) stays here. Both
|
|
4519
|
+
* transports download through the same PREFETCH-deep sliding window
|
|
4520
|
+
* (`runPrefetched`), overlapping network and CPU.
|
|
4521
4521
|
*/
|
|
4522
4522
|
|
|
4523
4523
|
/**
|
|
@@ -4552,8 +4552,11 @@ interface ScanOutcome {
|
|
|
4552
4552
|
onChainHexes: Set<string>;
|
|
4553
4553
|
/** Highest leafIndex seen — the next incremental scan resumes after it. */
|
|
4554
4554
|
maxLeafIndex: number | undefined;
|
|
4555
|
+
/** Hints walked this call, across both transports. */
|
|
4555
4556
|
scanned: number;
|
|
4557
|
+
/** Notes recovered that the vault did not hold yet. */
|
|
4556
4558
|
found: number;
|
|
4559
|
+
/** Hints carrying no memo or ephemeral key — nothing to decrypt. */
|
|
4557
4560
|
noMemo: number;
|
|
4558
4561
|
/**
|
|
4559
4562
|
* Hints whose memo did not open with this wallet's keys.
|
|
@@ -4564,6 +4567,7 @@ interface ScanOutcome {
|
|
|
4564
4567
|
* recovers nothing while this equals the whole pool has a key problem.
|
|
4565
4568
|
*/
|
|
4566
4569
|
decryptFailed: number;
|
|
4570
|
+
/** Notes recovered that the vault already held. */
|
|
4567
4571
|
alreadyPresent: number;
|
|
4568
4572
|
/** Hints discarded by the view-tag fast filter (no AEAD decrypt attempted). */
|
|
4569
4573
|
tagFiltered: number;
|
package/dist/index.js
CHANGED
|
@@ -5880,6 +5880,7 @@ var VaultStore = class {
|
|
|
5880
5880
|
|
|
5881
5881
|
// src/wallet/scanner/phases/collect.ts
|
|
5882
5882
|
var PAGE_SIZE = 2500;
|
|
5883
|
+
var PREFETCH = 3;
|
|
5883
5884
|
async function processHints(ctx, hints, total) {
|
|
5884
5885
|
const { outcome } = ctx;
|
|
5885
5886
|
const toDecrypt = [];
|
|
@@ -5927,6 +5928,24 @@ async function processHints(ctx, hints, total) {
|
|
|
5927
5928
|
await ctx.onBatchDone?.(outcome.maxLeafIndex);
|
|
5928
5929
|
ctx.onProgress?.({ scanned: outcome.scanned, total, found: outcome.found });
|
|
5929
5930
|
}
|
|
5931
|
+
async function runPrefetched(count, fetchItem, signal, handle) {
|
|
5932
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
5933
|
+
const ensureFetching = (i) => {
|
|
5934
|
+
if (i < count && !inFlight.has(i)) inFlight.set(i, fetchItem(i));
|
|
5935
|
+
};
|
|
5936
|
+
try {
|
|
5937
|
+
for (let i = 0; i < count; i++) {
|
|
5938
|
+
if (signal?.aborted) throw scanAbortError();
|
|
5939
|
+
for (let n = i; n < i + PREFETCH; n++) ensureFetching(n);
|
|
5940
|
+
const item = await inFlight.get(i);
|
|
5941
|
+
inFlight.delete(i);
|
|
5942
|
+
await handle(item);
|
|
5943
|
+
}
|
|
5944
|
+
} finally {
|
|
5945
|
+
for (const pending of inFlight.values()) pending.catch(() => {
|
|
5946
|
+
});
|
|
5947
|
+
}
|
|
5948
|
+
}
|
|
5930
5949
|
async function processSealedChunks(ctx, source, sinceLeafIndex) {
|
|
5931
5950
|
if (!source.chunks) return null;
|
|
5932
5951
|
const manifest = await source.chunks.manifest().catch(() => null);
|
|
@@ -5939,27 +5958,36 @@ async function processSealedChunks(ctx, source, sinceLeafIndex) {
|
|
|
5939
5958
|
if (pending.length === 0) return null;
|
|
5940
5959
|
const total = Math.max(manifest.total - startLeaf, 0);
|
|
5941
5960
|
const fetchChunk = (i) => source.chunks.chunk(pending[i].idx, pending[i].digest);
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5961
|
+
await runPrefetched(
|
|
5962
|
+
pending.length,
|
|
5963
|
+
fetchChunk,
|
|
5964
|
+
ctx.signal,
|
|
5965
|
+
(hints) => (
|
|
5966
|
+
// The first chunk may straddle the cursor — drop already-scanned leaves.
|
|
5967
|
+
processHints(
|
|
5949
5968
|
ctx,
|
|
5950
5969
|
hints.filter((h) => (h.leafIndex ?? 0) >= startLeaf),
|
|
5951
5970
|
total
|
|
5952
|
-
)
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
nextChunk?.catch(() => {
|
|
5956
|
-
});
|
|
5957
|
-
}
|
|
5971
|
+
)
|
|
5972
|
+
)
|
|
5973
|
+
);
|
|
5958
5974
|
return manifest.lastSealedLeaf + 1;
|
|
5959
5975
|
}
|
|
5976
|
+
async function processPaginatedTail(ctx, source, sinceLeafIndex) {
|
|
5977
|
+
const fetchPage = (page) => source.listHints({ page, limit: PAGE_SIZE, sinceLeafIndex });
|
|
5978
|
+
const firstPage = await fetchPage(1);
|
|
5979
|
+
const total = ctx.outcome.scanned + firstPage.pagination.total;
|
|
5980
|
+
const effectiveLimit = firstPage.pagination.limit || PAGE_SIZE;
|
|
5981
|
+
const totalPages = Math.max(Math.ceil(firstPage.pagination.total / effectiveLimit), 1);
|
|
5982
|
+
await runPrefetched(
|
|
5983
|
+
totalPages,
|
|
5984
|
+
(i) => i === 0 ? Promise.resolve(firstPage) : fetchPage(i + 1),
|
|
5985
|
+
ctx.signal,
|
|
5986
|
+
(page) => processHints(ctx, page.data, total)
|
|
5987
|
+
);
|
|
5988
|
+
}
|
|
5960
5989
|
async function collectScanEntries(params) {
|
|
5961
|
-
const { source,
|
|
5962
|
-
const { onBatchDone } = params;
|
|
5990
|
+
const { source, sinceLeafIndex, signal } = params;
|
|
5963
5991
|
if (signal?.aborted) throw scanAbortError();
|
|
5964
5992
|
const outcome = {
|
|
5965
5993
|
scanEntries: [],
|
|
@@ -5977,14 +6005,14 @@ async function collectScanEntries(params) {
|
|
|
5977
6005
|
};
|
|
5978
6006
|
const ctx = {
|
|
5979
6007
|
outcome,
|
|
5980
|
-
pool,
|
|
5981
|
-
keys,
|
|
5982
|
-
existingHexes,
|
|
5983
|
-
vaultHexes: params.vaultHexes ?? existingHexes,
|
|
5984
|
-
onProgress,
|
|
6008
|
+
pool: params.pool,
|
|
6009
|
+
keys: params.keys,
|
|
6010
|
+
existingHexes: params.existingHexes,
|
|
6011
|
+
vaultHexes: params.vaultHexes ?? params.existingHexes,
|
|
6012
|
+
onProgress: params.onProgress,
|
|
5985
6013
|
signal,
|
|
5986
|
-
onPage,
|
|
5987
|
-
onBatchDone
|
|
6014
|
+
onPage: params.onPage,
|
|
6015
|
+
onBatchDone: params.onBatchDone
|
|
5988
6016
|
};
|
|
5989
6017
|
let tailSince = sinceLeafIndex;
|
|
5990
6018
|
try {
|
|
@@ -5995,33 +6023,7 @@ async function collectScanEntries(params) {
|
|
|
5995
6023
|
params.onWarning?.("sealed-chunk path failed; falling back to paginated hints", err);
|
|
5996
6024
|
if (outcome.maxLeafIndex !== void 0) tailSince = outcome.maxLeafIndex + 1;
|
|
5997
6025
|
}
|
|
5998
|
-
|
|
5999
|
-
const firstPage = await fetchPage(1);
|
|
6000
|
-
const total = outcome.scanned + firstPage.pagination.total;
|
|
6001
|
-
const effectiveLimit = firstPage.pagination.limit || PAGE_SIZE;
|
|
6002
|
-
const totalPages = Math.ceil(firstPage.pagination.total / effectiveLimit);
|
|
6003
|
-
const PREFETCH = 3;
|
|
6004
|
-
const inFlight = /* @__PURE__ */ new Map();
|
|
6005
|
-
const ensureFetching = (page) => {
|
|
6006
|
-
if (page >= 2 && page <= totalPages && !inFlight.has(page)) {
|
|
6007
|
-
inFlight.set(page, fetchPage(page));
|
|
6008
|
-
}
|
|
6009
|
-
};
|
|
6010
|
-
try {
|
|
6011
|
-
for (let p = 2; p < 2 + PREFETCH; p++) ensureFetching(p);
|
|
6012
|
-
await processHints(ctx, firstPage.data, total);
|
|
6013
|
-
for (let page = 2; page <= totalPages; page++) {
|
|
6014
|
-
if (signal?.aborted) throw scanAbortError();
|
|
6015
|
-
ensureFetching(page);
|
|
6016
|
-
const current = await inFlight.get(page);
|
|
6017
|
-
inFlight.delete(page);
|
|
6018
|
-
for (let p = page + 1; p <= page + PREFETCH; p++) ensureFetching(p);
|
|
6019
|
-
await processHints(ctx, current.data, total);
|
|
6020
|
-
}
|
|
6021
|
-
} finally {
|
|
6022
|
-
for (const pending of inFlight.values()) pending.catch(() => {
|
|
6023
|
-
});
|
|
6024
|
-
}
|
|
6026
|
+
await processPaginatedTail(ctx, source, tailSince);
|
|
6025
6027
|
return outcome;
|
|
6026
6028
|
}
|
|
6027
6029
|
|
package/dist/index.mjs
CHANGED
|
@@ -4654,6 +4654,7 @@ var VaultStore = class {
|
|
|
4654
4654
|
|
|
4655
4655
|
// src/wallet/scanner/phases/collect.ts
|
|
4656
4656
|
var PAGE_SIZE = 2500;
|
|
4657
|
+
var PREFETCH = 3;
|
|
4657
4658
|
async function processHints(ctx, hints, total) {
|
|
4658
4659
|
const { outcome } = ctx;
|
|
4659
4660
|
const toDecrypt = [];
|
|
@@ -4701,6 +4702,24 @@ async function processHints(ctx, hints, total) {
|
|
|
4701
4702
|
await ctx.onBatchDone?.(outcome.maxLeafIndex);
|
|
4702
4703
|
ctx.onProgress?.({ scanned: outcome.scanned, total, found: outcome.found });
|
|
4703
4704
|
}
|
|
4705
|
+
async function runPrefetched(count, fetchItem, signal, handle) {
|
|
4706
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
4707
|
+
const ensureFetching = (i) => {
|
|
4708
|
+
if (i < count && !inFlight.has(i)) inFlight.set(i, fetchItem(i));
|
|
4709
|
+
};
|
|
4710
|
+
try {
|
|
4711
|
+
for (let i = 0; i < count; i++) {
|
|
4712
|
+
if (signal?.aborted) throw scanAbortError();
|
|
4713
|
+
for (let n = i; n < i + PREFETCH; n++) ensureFetching(n);
|
|
4714
|
+
const item = await inFlight.get(i);
|
|
4715
|
+
inFlight.delete(i);
|
|
4716
|
+
await handle(item);
|
|
4717
|
+
}
|
|
4718
|
+
} finally {
|
|
4719
|
+
for (const pending of inFlight.values()) pending.catch(() => {
|
|
4720
|
+
});
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4704
4723
|
async function processSealedChunks(ctx, source, sinceLeafIndex) {
|
|
4705
4724
|
if (!source.chunks) return null;
|
|
4706
4725
|
const manifest = await source.chunks.manifest().catch(() => null);
|
|
@@ -4713,27 +4732,36 @@ async function processSealedChunks(ctx, source, sinceLeafIndex) {
|
|
|
4713
4732
|
if (pending.length === 0) return null;
|
|
4714
4733
|
const total = Math.max(manifest.total - startLeaf, 0);
|
|
4715
4734
|
const fetchChunk = (i) => source.chunks.chunk(pending[i].idx, pending[i].digest);
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4735
|
+
await runPrefetched(
|
|
4736
|
+
pending.length,
|
|
4737
|
+
fetchChunk,
|
|
4738
|
+
ctx.signal,
|
|
4739
|
+
(hints) => (
|
|
4740
|
+
// The first chunk may straddle the cursor — drop already-scanned leaves.
|
|
4741
|
+
processHints(
|
|
4723
4742
|
ctx,
|
|
4724
4743
|
hints.filter((h) => (h.leafIndex ?? 0) >= startLeaf),
|
|
4725
4744
|
total
|
|
4726
|
-
)
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
nextChunk?.catch(() => {
|
|
4730
|
-
});
|
|
4731
|
-
}
|
|
4745
|
+
)
|
|
4746
|
+
)
|
|
4747
|
+
);
|
|
4732
4748
|
return manifest.lastSealedLeaf + 1;
|
|
4733
4749
|
}
|
|
4750
|
+
async function processPaginatedTail(ctx, source, sinceLeafIndex) {
|
|
4751
|
+
const fetchPage = (page) => source.listHints({ page, limit: PAGE_SIZE, sinceLeafIndex });
|
|
4752
|
+
const firstPage = await fetchPage(1);
|
|
4753
|
+
const total = ctx.outcome.scanned + firstPage.pagination.total;
|
|
4754
|
+
const effectiveLimit = firstPage.pagination.limit || PAGE_SIZE;
|
|
4755
|
+
const totalPages = Math.max(Math.ceil(firstPage.pagination.total / effectiveLimit), 1);
|
|
4756
|
+
await runPrefetched(
|
|
4757
|
+
totalPages,
|
|
4758
|
+
(i) => i === 0 ? Promise.resolve(firstPage) : fetchPage(i + 1),
|
|
4759
|
+
ctx.signal,
|
|
4760
|
+
(page) => processHints(ctx, page.data, total)
|
|
4761
|
+
);
|
|
4762
|
+
}
|
|
4734
4763
|
async function collectScanEntries(params) {
|
|
4735
|
-
const { source,
|
|
4736
|
-
const { onBatchDone } = params;
|
|
4764
|
+
const { source, sinceLeafIndex, signal } = params;
|
|
4737
4765
|
if (signal?.aborted) throw scanAbortError();
|
|
4738
4766
|
const outcome = {
|
|
4739
4767
|
scanEntries: [],
|
|
@@ -4751,14 +4779,14 @@ async function collectScanEntries(params) {
|
|
|
4751
4779
|
};
|
|
4752
4780
|
const ctx = {
|
|
4753
4781
|
outcome,
|
|
4754
|
-
pool,
|
|
4755
|
-
keys,
|
|
4756
|
-
existingHexes,
|
|
4757
|
-
vaultHexes: params.vaultHexes ?? existingHexes,
|
|
4758
|
-
onProgress,
|
|
4782
|
+
pool: params.pool,
|
|
4783
|
+
keys: params.keys,
|
|
4784
|
+
existingHexes: params.existingHexes,
|
|
4785
|
+
vaultHexes: params.vaultHexes ?? params.existingHexes,
|
|
4786
|
+
onProgress: params.onProgress,
|
|
4759
4787
|
signal,
|
|
4760
|
-
onPage,
|
|
4761
|
-
onBatchDone
|
|
4788
|
+
onPage: params.onPage,
|
|
4789
|
+
onBatchDone: params.onBatchDone
|
|
4762
4790
|
};
|
|
4763
4791
|
let tailSince = sinceLeafIndex;
|
|
4764
4792
|
try {
|
|
@@ -4769,33 +4797,7 @@ async function collectScanEntries(params) {
|
|
|
4769
4797
|
params.onWarning?.("sealed-chunk path failed; falling back to paginated hints", err);
|
|
4770
4798
|
if (outcome.maxLeafIndex !== void 0) tailSince = outcome.maxLeafIndex + 1;
|
|
4771
4799
|
}
|
|
4772
|
-
|
|
4773
|
-
const firstPage = await fetchPage(1);
|
|
4774
|
-
const total = outcome.scanned + firstPage.pagination.total;
|
|
4775
|
-
const effectiveLimit = firstPage.pagination.limit || PAGE_SIZE;
|
|
4776
|
-
const totalPages = Math.ceil(firstPage.pagination.total / effectiveLimit);
|
|
4777
|
-
const PREFETCH = 3;
|
|
4778
|
-
const inFlight = /* @__PURE__ */ new Map();
|
|
4779
|
-
const ensureFetching = (page) => {
|
|
4780
|
-
if (page >= 2 && page <= totalPages && !inFlight.has(page)) {
|
|
4781
|
-
inFlight.set(page, fetchPage(page));
|
|
4782
|
-
}
|
|
4783
|
-
};
|
|
4784
|
-
try {
|
|
4785
|
-
for (let p = 2; p < 2 + PREFETCH; p++) ensureFetching(p);
|
|
4786
|
-
await processHints(ctx, firstPage.data, total);
|
|
4787
|
-
for (let page = 2; page <= totalPages; page++) {
|
|
4788
|
-
if (signal?.aborted) throw scanAbortError();
|
|
4789
|
-
ensureFetching(page);
|
|
4790
|
-
const current = await inFlight.get(page);
|
|
4791
|
-
inFlight.delete(page);
|
|
4792
|
-
for (let p = page + 1; p <= page + PREFETCH; p++) ensureFetching(p);
|
|
4793
|
-
await processHints(ctx, current.data, total);
|
|
4794
|
-
}
|
|
4795
|
-
} finally {
|
|
4796
|
-
for (const pending of inFlight.values()) pending.catch(() => {
|
|
4797
|
-
});
|
|
4798
|
-
}
|
|
4800
|
+
await processPaginatedTail(ctx, source, tailSince);
|
|
4799
4801
|
return outcome;
|
|
4800
4802
|
}
|
|
4801
4803
|
|