@arkade-os/sdk 0.4.48 → 0.4.49-rc.0
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/adapters/expo.cjs +5 -5
- package/dist/adapters/expo.d.cts +2 -2
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +3 -3
- package/dist/adapters/indexedDB.cjs +5 -5
- package/dist/adapters/indexedDB.js +4 -4
- package/dist/{ark-CjE0KkGp.d.cts → ark-Bz4VxTY7.d.cts} +85 -23
- package/dist/{ark-CjE0KkGp.d.ts → ark-Bz4VxTY7.d.ts} +85 -23
- package/dist/{asyncStorageTaskQueue-CeLZhZFU.d.cts → asyncStorageTaskQueue-BgQaK3El.d.cts} +2 -2
- package/dist/{asyncStorageTaskQueue-D9SOPMPC.d.ts → asyncStorageTaskQueue-UIyDWZ_d.d.ts} +2 -2
- package/dist/{chunk-G6J6AEMH.js → chunk-27DACHF6.js} +4 -4
- package/dist/{chunk-G6J6AEMH.js.map → chunk-27DACHF6.js.map} +1 -1
- package/dist/{chunk-XFMGIFBL.js → chunk-COB6VP4M.js} +4 -4
- package/dist/{chunk-XFMGIFBL.js.map → chunk-COB6VP4M.js.map} +1 -1
- package/dist/{chunk-7TXSPRN5.cjs → chunk-E7HB3GKK.cjs} +31 -2
- package/dist/chunk-E7HB3GKK.cjs.map +1 -0
- package/dist/{chunk-ENDNQPZA.cjs → chunk-EEYMJVF6.cjs} +17 -17
- package/dist/{chunk-ENDNQPZA.cjs.map → chunk-EEYMJVF6.cjs.map} +1 -1
- package/dist/{chunk-ZDDBTFVO.js → chunk-EFNLTS6Q.js} +29 -3
- package/dist/chunk-EFNLTS6Q.js.map +1 -0
- package/dist/{chunk-BHHLRZCS.js → chunk-ITT2S4O3.js} +4 -4
- package/dist/chunk-ITT2S4O3.js.map +1 -0
- package/dist/{chunk-5XMVTK5S.cjs → chunk-LJQ2VQBE.cjs} +211 -230
- package/dist/chunk-LJQ2VQBE.cjs.map +1 -0
- package/dist/{chunk-4VVTRPH3.js → chunk-MBSYQ3WX.js} +183 -201
- package/dist/chunk-MBSYQ3WX.js.map +1 -0
- package/dist/{chunk-ENZ4YPR2.cjs → chunk-R3LGVLKP.cjs} +491 -418
- package/dist/chunk-R3LGVLKP.cjs.map +1 -0
- package/dist/{chunk-EB3ALGTM.cjs → chunk-RNNCQHAI.cjs} +13 -13
- package/dist/chunk-RNNCQHAI.cjs.map +1 -0
- package/dist/{chunk-NYR5H6GR.js → chunk-T2IVKSZP.js} +154 -81
- package/dist/chunk-T2IVKSZP.js.map +1 -0
- package/dist/{chunk-SYDANBJI.cjs → chunk-XWZY6NHJ.cjs} +9 -9
- package/dist/{chunk-SYDANBJI.cjs.map → chunk-XWZY6NHJ.cjs.map} +1 -1
- package/dist/contracts/handlers/index.cjs +8 -8
- package/dist/contracts/handlers/index.d.cts +3 -3
- package/dist/contracts/handlers/index.d.ts +3 -3
- package/dist/contracts/handlers/index.js +2 -2
- package/dist/{delegate-DhGZk1r2.d.ts → delegate-BoIZ4Sjj.d.ts} +1 -1
- package/dist/{delegate-D3dY-2vS.d.cts → delegate-D_7Gh5H4.d.cts} +1 -1
- package/dist/{index-DK4_iWYy.d.ts → index-Cu6QYjYT.d.ts} +2 -2
- package/dist/{index-D6RQROds.d.cts → index-jAMA6NXc.d.cts} +2 -2
- package/dist/index.cjs +181 -181
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +4 -4
- package/dist/repositories/realm/index.cjs +19 -19
- package/dist/repositories/realm/index.d.cts +2 -2
- package/dist/repositories/realm/index.d.ts +2 -2
- package/dist/repositories/realm/index.js +5 -5
- package/dist/repositories/sqlite/index.cjs +18 -18
- package/dist/repositories/sqlite/index.d.cts +2 -2
- package/dist/repositories/sqlite/index.d.ts +2 -2
- package/dist/repositories/sqlite/index.js +5 -5
- package/dist/{taskRunner-Brnak0Rc.d.cts → taskRunner-Ck0AouQU.d.cts} +2 -2
- package/dist/{taskRunner-B-2MHCYG.d.ts → taskRunner-bs1AE_BL.d.ts} +2 -2
- package/dist/wallet/expo/background.cjs +14 -14
- package/dist/wallet/expo/background.d.cts +3 -3
- package/dist/wallet/expo/background.d.ts +3 -3
- package/dist/wallet/expo/background.js +6 -6
- package/dist/wallet/expo/index.cjs +14 -14
- package/dist/wallet/expo/index.d.cts +4 -4
- package/dist/wallet/expo/index.d.ts +4 -4
- package/dist/wallet/expo/index.js +5 -5
- package/dist/{wallet-B5bwixQa.d.ts → wallet-CJ_8yiIz.d.ts} +2 -2
- package/dist/{wallet-DiOrtYic.d.cts → wallet-CkTb2epm.d.cts} +2 -2
- package/dist/worker/expo/index.cjs +9 -9
- package/dist/worker/expo/index.d.cts +4 -4
- package/dist/worker/expo/index.d.ts +4 -4
- package/dist/worker/expo/index.js +5 -5
- package/package.json +1 -1
- package/dist/chunk-4VVTRPH3.js.map +0 -1
- package/dist/chunk-5XMVTK5S.cjs.map +0 -1
- package/dist/chunk-7TXSPRN5.cjs.map +0 -1
- package/dist/chunk-BHHLRZCS.js.map +0 -1
- package/dist/chunk-EB3ALGTM.cjs.map +0 -1
- package/dist/chunk-ENZ4YPR2.cjs.map +0 -1
- package/dist/chunk-NYR5H6GR.js.map +0 -1
- package/dist/chunk-ZDDBTFVO.js.map +0 -1
package/dist/adapters/expo.cjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
3
|
+
var chunkEEYMJVF6_cjs = require('../chunk-EEYMJVF6.cjs');
|
|
4
|
+
require('../chunk-RNNCQHAI.cjs');
|
|
5
|
+
require('../chunk-E7HB3GKK.cjs');
|
|
6
6
|
require('../chunk-5BLDMQED.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "ExpoArkProvider", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkEEYMJVF6_cjs.ExpoArkProvider; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "ExpoIndexerProvider", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkEEYMJVF6_cjs.ExpoIndexerProvider; }
|
|
17
17
|
});
|
|
18
18
|
//# sourceMappingURL=expo.cjs.map
|
|
19
19
|
//# sourceMappingURL=expo.cjs.map
|
package/dist/adapters/expo.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { k as RestArkProvider, i as SettlementEvent, T as TxNotification, l as RestIndexerProvider, m as SubscriptionResponse } from '../ark-
|
|
2
|
-
export { n as ArkProvider, o as IndexerProvider } from '../ark-
|
|
1
|
+
import { k as RestArkProvider, i as SettlementEvent, T as TxNotification, l as RestIndexerProvider, m as SubscriptionResponse } from '../ark-Bz4VxTY7.cjs';
|
|
2
|
+
export { n as ArkProvider, o as IndexerProvider } from '../ark-Bz4VxTY7.cjs';
|
|
3
3
|
import '@scure/btc-signer/transaction.js';
|
|
4
4
|
import '@scure/btc-signer/utils.js';
|
|
5
5
|
import '@scure/btc-signer/psbt.js';
|
package/dist/adapters/expo.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { k as RestArkProvider, i as SettlementEvent, T as TxNotification, l as RestIndexerProvider, m as SubscriptionResponse } from '../ark-
|
|
2
|
-
export { n as ArkProvider, o as IndexerProvider } from '../ark-
|
|
1
|
+
import { k as RestArkProvider, i as SettlementEvent, T as TxNotification, l as RestIndexerProvider, m as SubscriptionResponse } from '../ark-Bz4VxTY7.js';
|
|
2
|
+
export { n as ArkProvider, o as IndexerProvider } from '../ark-Bz4VxTY7.js';
|
|
3
3
|
import '@scure/btc-signer/transaction.js';
|
|
4
4
|
import '@scure/btc-signer/utils.js';
|
|
5
5
|
import '@scure/btc-signer/psbt.js';
|
package/dist/adapters/expo.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { ExpoArkProvider, ExpoIndexerProvider } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { ExpoArkProvider, ExpoIndexerProvider } from '../chunk-COB6VP4M.js';
|
|
2
|
+
import '../chunk-ITT2S4O3.js';
|
|
3
|
+
import '../chunk-EFNLTS6Q.js';
|
|
4
4
|
import '../chunk-NSBPE2FW.js';
|
|
5
5
|
//# sourceMappingURL=expo.js.map
|
|
6
6
|
//# sourceMappingURL=expo.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
6
|
-
require('../chunk-
|
|
3
|
+
var chunkR3LGVLKP_cjs = require('../chunk-R3LGVLKP.cjs');
|
|
4
|
+
require('../chunk-RNNCQHAI.cjs');
|
|
5
|
+
require('../chunk-LJQ2VQBE.cjs');
|
|
6
|
+
require('../chunk-E7HB3GKK.cjs');
|
|
7
7
|
require('../chunk-5BLDMQED.cjs');
|
|
8
8
|
|
|
9
9
|
// src/storage/indexedDB.ts
|
|
@@ -11,7 +11,7 @@ var IndexedDBStorageAdapter = class {
|
|
|
11
11
|
dbName;
|
|
12
12
|
version;
|
|
13
13
|
db = null;
|
|
14
|
-
constructor(dbName, version =
|
|
14
|
+
constructor(dbName, version = chunkR3LGVLKP_cjs.DB_VERSION) {
|
|
15
15
|
this.dbName = dbName;
|
|
16
16
|
this.version = version;
|
|
17
17
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DB_VERSION } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import '../chunk-
|
|
1
|
+
import { DB_VERSION } from '../chunk-T2IVKSZP.js';
|
|
2
|
+
import '../chunk-ITT2S4O3.js';
|
|
3
|
+
import '../chunk-MBSYQ3WX.js';
|
|
4
|
+
import '../chunk-EFNLTS6Q.js';
|
|
5
5
|
import '../chunk-NSBPE2FW.js';
|
|
6
6
|
|
|
7
7
|
// src/storage/indexedDB.ts
|
|
@@ -1912,12 +1912,19 @@ type RefreshVtxosOptions = {
|
|
|
1912
1912
|
includeInactive?: boolean;
|
|
1913
1913
|
};
|
|
1914
1914
|
/**
|
|
1915
|
-
* A single `Discoverable` handler's
|
|
1916
|
-
*
|
|
1915
|
+
* A single `Discoverable` handler's discovery failure, captured during a
|
|
1916
|
+
* {@link IContractManager.scanContracts} run instead of aborting the loop.
|
|
1917
|
+
*
|
|
1918
|
+
* TODO(next major): rename `index` → `fromIndex` so the pair reads
|
|
1919
|
+
* `fromIndex`/`toIndex`. It stays `index` here only to keep this exported
|
|
1920
|
+
* shape backward-compatible.
|
|
1917
1921
|
*/
|
|
1918
1922
|
interface HandlerError {
|
|
1919
1923
|
handler: string;
|
|
1924
|
+
/** The failed index, or the first index of a failed `discoverRange` window. */
|
|
1920
1925
|
index: number;
|
|
1926
|
+
/** Inclusive end of a failed `discoverRange` window; absent for a single index. */
|
|
1927
|
+
toIndex?: number;
|
|
1921
1928
|
error: unknown;
|
|
1922
1929
|
}
|
|
1923
1930
|
/**
|
|
@@ -1941,7 +1948,7 @@ interface ScanResult {
|
|
|
1941
1948
|
* when the scan closed a genuine gap.
|
|
1942
1949
|
*/
|
|
1943
1950
|
truncatedAt?: number;
|
|
1944
|
-
/** Per-handler
|
|
1951
|
+
/** Per-handler discovery failures. Non-empty implies `truncatedAt` is set. */
|
|
1945
1952
|
handlerErrors: HandlerError[];
|
|
1946
1953
|
}
|
|
1947
1954
|
/**
|
|
@@ -1951,11 +1958,13 @@ interface ScanContractsOptions {
|
|
|
1951
1958
|
/** Default 20. A non-positive / non-integer value throws. */
|
|
1952
1959
|
gapLimit?: number;
|
|
1953
1960
|
/**
|
|
1954
|
-
* Number of HD indices probed
|
|
1955
|
-
* {@link DEFAULT_SCAN_BATCH}).
|
|
1956
|
-
*
|
|
1957
|
-
*
|
|
1958
|
-
*
|
|
1961
|
+
* Number of HD indices probed per window (default
|
|
1962
|
+
* {@link DEFAULT_SCAN_BATCH}). The gap loop stays gap-limit bounded and
|
|
1963
|
+
* the discovered set is identical regardless of batch size; the window is
|
|
1964
|
+
* also the unit a batching handler ({@link Discoverable.discoverRange})
|
|
1965
|
+
* collapses into one request, so it doubles as the batch width. A
|
|
1966
|
+
* non-positive / non-integer value throws. Ignored when `hd` is false (the
|
|
1967
|
+
* static pass probes only index 0).
|
|
1959
1968
|
*/
|
|
1960
1969
|
batchSize?: number;
|
|
1961
1970
|
/** HD mode → unbounded gap loop guided by the gap counter; false → probe only index 0 (single static pass). */
|
|
@@ -2092,11 +2101,12 @@ interface IContractManager extends Disposable {
|
|
|
2092
2101
|
* resets the gap counter, so swap discovery keeps the HD window open.
|
|
2093
2102
|
*
|
|
2094
2103
|
* Error contract (safety-critical — see spec §4):
|
|
2095
|
-
* - A handler's
|
|
2096
|
-
*
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
*
|
|
2104
|
+
* - A handler's discovery rejecting is **collected** into `handlerErrors`
|
|
2105
|
+
* and makes its index *indeterminate*: it never advances the gap
|
|
2106
|
+
* counter, and the scan **stops verifying** there rather than closing a
|
|
2107
|
+
* window it never observed close. A batched
|
|
2108
|
+
* {@link Discoverable.discoverRange} failure makes its whole requested
|
|
2109
|
+
* range indeterminate. It still never throws.
|
|
2100
2110
|
* - A fatal operational error — `materialize()` throwing, or
|
|
2101
2111
|
* `createContract` rejecting — **propagates** out of `scanContracts`
|
|
2102
2112
|
* (it invalidates the gap-window signal, so a silent truncation
|
|
@@ -2316,21 +2326,27 @@ declare class ContractManager implements IContractManager {
|
|
|
2316
2326
|
* Safety-critical invariants (spec §2.C / §4):
|
|
2317
2327
|
* - `opts.materialize(i)` throwing is structural/fatal: it is NOT
|
|
2318
2328
|
* wrapped — it propagates and aborts the scan.
|
|
2319
|
-
* - A
|
|
2320
|
-
*
|
|
2321
|
-
*
|
|
2329
|
+
* - A discovery rejection is collected into `handlerErrors` and makes its
|
|
2330
|
+
* index *indeterminate*: it does NOT advance the gap counter, and the
|
|
2331
|
+
* scan stops verifying there, reporting `truncatedAt`. Only an index
|
|
2322
2332
|
* every handler answered for can be a confirmed miss.
|
|
2323
2333
|
* - `persistAndWatchContract` rejecting is operational/fatal and
|
|
2324
|
-
* propagates (only
|
|
2325
|
-
* -
|
|
2326
|
-
*
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2329
|
-
*
|
|
2334
|
+
* propagates (only the handler calls are guarded).
|
|
2335
|
+
* - A handler exposing {@link Discoverable.discoverRange} is asked for the
|
|
2336
|
+
* whole window in ONE call instead of one per index — the batching that
|
|
2337
|
+
* keeps a large restore from bursting into an operator's rate limiter.
|
|
2338
|
+
* Its failures are therefore range-wide: every index in the window goes
|
|
2339
|
+
* indeterminate and truncation lands on the window's first index. Its
|
|
2340
|
+
* answer must cover every requested index; an incomplete map is treated
|
|
2341
|
+
* as a rejection (see `Discoverable.discoverRange`).
|
|
2342
|
+
* - Handlers are probed concurrently (independent network reads); their
|
|
2343
|
+
* hits are persisted sequentially in `discoverables` order to preserve
|
|
2344
|
+
* the first-wins collision tie-break.
|
|
2345
|
+
* - Indices are probed `batchSize` at a time, but each window is CAPPED to
|
|
2330
2346
|
* `gapLimit - unused` indices — the most a serial scan could still reach
|
|
2331
2347
|
* before the gap window is guaranteed to close. So every index probed in
|
|
2332
2348
|
* a window is one a one-index-at-a-time scan would also reach: nothing is
|
|
2333
|
-
* over-scanned, nothing is discarded, and `materialize
|
|
2349
|
+
* over-scanned, nothing is discarded, and `materialize`/discovery are
|
|
2334
2350
|
* invoked on exactly the same index set. The window's hits are still
|
|
2335
2351
|
* processed strictly in ascending index order, so the discovered set,
|
|
2336
2352
|
* persisted rows, `highestConfirmedUsedIndex`, and `handlerErrors` are
|
|
@@ -2339,8 +2355,12 @@ declare class ContractManager implements IContractManager {
|
|
|
2339
2355
|
* can surface hits above the failed index that a serial scan would never
|
|
2340
2356
|
* have reached, so a truncated batched scan discovers a superset — never
|
|
2341
2357
|
* a subset — of the serial one.
|
|
2358
|
+
* - The whole scan runs inside one coalesced subscription scope, so N
|
|
2359
|
+
* discovered contracts cost ONE `subscribeForScripts` instead of N
|
|
2360
|
+
* growing ones (see {@link ContractWatcher.withCoalescedSubscription}).
|
|
2342
2361
|
*/
|
|
2343
2362
|
scanContracts(opts: ScanContractsOptions): Promise<ScanResult>;
|
|
2363
|
+
private runScan;
|
|
2344
2364
|
/**
|
|
2345
2365
|
* Get contracts with optional filters.
|
|
2346
2366
|
*
|
|
@@ -2770,6 +2790,27 @@ interface DiscoveryDeps {
|
|
|
2770
2790
|
*/
|
|
2771
2791
|
interface Discoverable {
|
|
2772
2792
|
discoverAt(index: number, descriptor: string, deps: DiscoveryDeps): Promise<DiscoveredContract[]>;
|
|
2793
|
+
/**
|
|
2794
|
+
* Optional: answer for a whole scan window in one batched round-trip.
|
|
2795
|
+
* The scanner prefers it over per-index `discoverAt` calls when present,
|
|
2796
|
+
* which is what keeps a 10-index window to 1-2 indexer requests instead
|
|
2797
|
+
* of one per index. Handlers whose source is inherently per-address (e.g.
|
|
2798
|
+
* boarding, on Esplora) implement only `discoverAt`.
|
|
2799
|
+
*
|
|
2800
|
+
* **All-or-nothing per call.** Either resolve with a map covering *every*
|
|
2801
|
+
* requested index (empty array = confirmed miss), or reject — a handler
|
|
2802
|
+
* whose inner chunk fails partway must discard the partial results and
|
|
2803
|
+
* reject, because a missing index would otherwise read as "no funds here"
|
|
2804
|
+
* and let restore close its gap window on a failed request. The scanner
|
|
2805
|
+
* enforces this rather than trusting it: an incomplete map is treated as a
|
|
2806
|
+
* rejection, making the whole requested range indeterminate (hits present
|
|
2807
|
+
* in it are still persisted) and truncating the scan at the range's first
|
|
2808
|
+
* index. Indices that were not requested are ignored.
|
|
2809
|
+
*/
|
|
2810
|
+
discoverRange?(entries: readonly {
|
|
2811
|
+
index: number;
|
|
2812
|
+
descriptor: string;
|
|
2813
|
+
}[], deps: DiscoveryDeps): Promise<Map<number, DiscoveredContract[]>>;
|
|
2773
2814
|
}
|
|
2774
2815
|
/** Duck-typed guard (mirrors `hasReceiveRotatorFactory`). */
|
|
2775
2816
|
declare function isDiscoverable(handler: ContractHandler<unknown> | undefined): handler is ContractHandler<unknown> & Discoverable;
|
|
@@ -2931,6 +2972,9 @@ declare class ContractWatcher {
|
|
|
2931
2972
|
private reconnectAttempts;
|
|
2932
2973
|
private reconnectTimeoutId?;
|
|
2933
2974
|
private failsafePollIntervalId?;
|
|
2975
|
+
/** See {@link withCoalescedSubscription}. */
|
|
2976
|
+
private subscriptionBatchDepth;
|
|
2977
|
+
private subscriptionUpdateDeferred;
|
|
2934
2978
|
/**
|
|
2935
2979
|
* Create a contract watcher with the given providers and polling settings.
|
|
2936
2980
|
*
|
|
@@ -3025,6 +3069,24 @@ declare class ContractWatcher {
|
|
|
3025
3069
|
* Poll specific contracts and emit events for changes.
|
|
3026
3070
|
*/
|
|
3027
3071
|
private pollContracts;
|
|
3072
|
+
/**
|
|
3073
|
+
* Run `fn` with subscription updates coalesced into a single
|
|
3074
|
+
* `subscribeForScripts` on the way out.
|
|
3075
|
+
*
|
|
3076
|
+
* {@link addContract} re-subscribes eagerly (the watcher may already be
|
|
3077
|
+
* running), and every subscribe posts the *whole* accumulated script list —
|
|
3078
|
+
* so a restore scan that discovers N contracts sends N growing POSTs,
|
|
3079
|
+
* quadratic in script-slots. Inside this scope those updates are only
|
|
3080
|
+
* marked dirty, flushed once on the way out (success and error path alike).
|
|
3081
|
+
*
|
|
3082
|
+
* A contract added inside the scope is therefore not streaming until the
|
|
3083
|
+
* flush. Nothing in the watcher closes that window — the failsafe poll
|
|
3084
|
+
* replays repository state and cannot see VTXOs no one has fetched yet. The
|
|
3085
|
+
* one caller, `scanContracts`, is covered because `Wallet.restore` follows
|
|
3086
|
+
* it with a bulk `refreshVtxos`. A new caller must provide its own
|
|
3087
|
+
* equivalent catch-up, or keep the scope short enough not to need one.
|
|
3088
|
+
*/
|
|
3089
|
+
withCoalescedSubscription<T>(fn: () => Promise<T>): Promise<T>;
|
|
3028
3090
|
private tryUpdateSubscription;
|
|
3029
3091
|
/**
|
|
3030
3092
|
* Update the subscription with scripts that should be watched.
|
|
@@ -1912,12 +1912,19 @@ type RefreshVtxosOptions = {
|
|
|
1912
1912
|
includeInactive?: boolean;
|
|
1913
1913
|
};
|
|
1914
1914
|
/**
|
|
1915
|
-
* A single `Discoverable` handler's
|
|
1916
|
-
*
|
|
1915
|
+
* A single `Discoverable` handler's discovery failure, captured during a
|
|
1916
|
+
* {@link IContractManager.scanContracts} run instead of aborting the loop.
|
|
1917
|
+
*
|
|
1918
|
+
* TODO(next major): rename `index` → `fromIndex` so the pair reads
|
|
1919
|
+
* `fromIndex`/`toIndex`. It stays `index` here only to keep this exported
|
|
1920
|
+
* shape backward-compatible.
|
|
1917
1921
|
*/
|
|
1918
1922
|
interface HandlerError {
|
|
1919
1923
|
handler: string;
|
|
1924
|
+
/** The failed index, or the first index of a failed `discoverRange` window. */
|
|
1920
1925
|
index: number;
|
|
1926
|
+
/** Inclusive end of a failed `discoverRange` window; absent for a single index. */
|
|
1927
|
+
toIndex?: number;
|
|
1921
1928
|
error: unknown;
|
|
1922
1929
|
}
|
|
1923
1930
|
/**
|
|
@@ -1941,7 +1948,7 @@ interface ScanResult {
|
|
|
1941
1948
|
* when the scan closed a genuine gap.
|
|
1942
1949
|
*/
|
|
1943
1950
|
truncatedAt?: number;
|
|
1944
|
-
/** Per-handler
|
|
1951
|
+
/** Per-handler discovery failures. Non-empty implies `truncatedAt` is set. */
|
|
1945
1952
|
handlerErrors: HandlerError[];
|
|
1946
1953
|
}
|
|
1947
1954
|
/**
|
|
@@ -1951,11 +1958,13 @@ interface ScanContractsOptions {
|
|
|
1951
1958
|
/** Default 20. A non-positive / non-integer value throws. */
|
|
1952
1959
|
gapLimit?: number;
|
|
1953
1960
|
/**
|
|
1954
|
-
* Number of HD indices probed
|
|
1955
|
-
* {@link DEFAULT_SCAN_BATCH}).
|
|
1956
|
-
*
|
|
1957
|
-
*
|
|
1958
|
-
*
|
|
1961
|
+
* Number of HD indices probed per window (default
|
|
1962
|
+
* {@link DEFAULT_SCAN_BATCH}). The gap loop stays gap-limit bounded and
|
|
1963
|
+
* the discovered set is identical regardless of batch size; the window is
|
|
1964
|
+
* also the unit a batching handler ({@link Discoverable.discoverRange})
|
|
1965
|
+
* collapses into one request, so it doubles as the batch width. A
|
|
1966
|
+
* non-positive / non-integer value throws. Ignored when `hd` is false (the
|
|
1967
|
+
* static pass probes only index 0).
|
|
1959
1968
|
*/
|
|
1960
1969
|
batchSize?: number;
|
|
1961
1970
|
/** HD mode → unbounded gap loop guided by the gap counter; false → probe only index 0 (single static pass). */
|
|
@@ -2092,11 +2101,12 @@ interface IContractManager extends Disposable {
|
|
|
2092
2101
|
* resets the gap counter, so swap discovery keeps the HD window open.
|
|
2093
2102
|
*
|
|
2094
2103
|
* Error contract (safety-critical — see spec §4):
|
|
2095
|
-
* - A handler's
|
|
2096
|
-
*
|
|
2097
|
-
*
|
|
2098
|
-
*
|
|
2099
|
-
*
|
|
2104
|
+
* - A handler's discovery rejecting is **collected** into `handlerErrors`
|
|
2105
|
+
* and makes its index *indeterminate*: it never advances the gap
|
|
2106
|
+
* counter, and the scan **stops verifying** there rather than closing a
|
|
2107
|
+
* window it never observed close. A batched
|
|
2108
|
+
* {@link Discoverable.discoverRange} failure makes its whole requested
|
|
2109
|
+
* range indeterminate. It still never throws.
|
|
2100
2110
|
* - A fatal operational error — `materialize()` throwing, or
|
|
2101
2111
|
* `createContract` rejecting — **propagates** out of `scanContracts`
|
|
2102
2112
|
* (it invalidates the gap-window signal, so a silent truncation
|
|
@@ -2316,21 +2326,27 @@ declare class ContractManager implements IContractManager {
|
|
|
2316
2326
|
* Safety-critical invariants (spec §2.C / §4):
|
|
2317
2327
|
* - `opts.materialize(i)` throwing is structural/fatal: it is NOT
|
|
2318
2328
|
* wrapped — it propagates and aborts the scan.
|
|
2319
|
-
* - A
|
|
2320
|
-
*
|
|
2321
|
-
*
|
|
2329
|
+
* - A discovery rejection is collected into `handlerErrors` and makes its
|
|
2330
|
+
* index *indeterminate*: it does NOT advance the gap counter, and the
|
|
2331
|
+
* scan stops verifying there, reporting `truncatedAt`. Only an index
|
|
2322
2332
|
* every handler answered for can be a confirmed miss.
|
|
2323
2333
|
* - `persistAndWatchContract` rejecting is operational/fatal and
|
|
2324
|
-
* propagates (only
|
|
2325
|
-
* -
|
|
2326
|
-
*
|
|
2327
|
-
*
|
|
2328
|
-
*
|
|
2329
|
-
*
|
|
2334
|
+
* propagates (only the handler calls are guarded).
|
|
2335
|
+
* - A handler exposing {@link Discoverable.discoverRange} is asked for the
|
|
2336
|
+
* whole window in ONE call instead of one per index — the batching that
|
|
2337
|
+
* keeps a large restore from bursting into an operator's rate limiter.
|
|
2338
|
+
* Its failures are therefore range-wide: every index in the window goes
|
|
2339
|
+
* indeterminate and truncation lands on the window's first index. Its
|
|
2340
|
+
* answer must cover every requested index; an incomplete map is treated
|
|
2341
|
+
* as a rejection (see `Discoverable.discoverRange`).
|
|
2342
|
+
* - Handlers are probed concurrently (independent network reads); their
|
|
2343
|
+
* hits are persisted sequentially in `discoverables` order to preserve
|
|
2344
|
+
* the first-wins collision tie-break.
|
|
2345
|
+
* - Indices are probed `batchSize` at a time, but each window is CAPPED to
|
|
2330
2346
|
* `gapLimit - unused` indices — the most a serial scan could still reach
|
|
2331
2347
|
* before the gap window is guaranteed to close. So every index probed in
|
|
2332
2348
|
* a window is one a one-index-at-a-time scan would also reach: nothing is
|
|
2333
|
-
* over-scanned, nothing is discarded, and `materialize
|
|
2349
|
+
* over-scanned, nothing is discarded, and `materialize`/discovery are
|
|
2334
2350
|
* invoked on exactly the same index set. The window's hits are still
|
|
2335
2351
|
* processed strictly in ascending index order, so the discovered set,
|
|
2336
2352
|
* persisted rows, `highestConfirmedUsedIndex`, and `handlerErrors` are
|
|
@@ -2339,8 +2355,12 @@ declare class ContractManager implements IContractManager {
|
|
|
2339
2355
|
* can surface hits above the failed index that a serial scan would never
|
|
2340
2356
|
* have reached, so a truncated batched scan discovers a superset — never
|
|
2341
2357
|
* a subset — of the serial one.
|
|
2358
|
+
* - The whole scan runs inside one coalesced subscription scope, so N
|
|
2359
|
+
* discovered contracts cost ONE `subscribeForScripts` instead of N
|
|
2360
|
+
* growing ones (see {@link ContractWatcher.withCoalescedSubscription}).
|
|
2342
2361
|
*/
|
|
2343
2362
|
scanContracts(opts: ScanContractsOptions): Promise<ScanResult>;
|
|
2363
|
+
private runScan;
|
|
2344
2364
|
/**
|
|
2345
2365
|
* Get contracts with optional filters.
|
|
2346
2366
|
*
|
|
@@ -2770,6 +2790,27 @@ interface DiscoveryDeps {
|
|
|
2770
2790
|
*/
|
|
2771
2791
|
interface Discoverable {
|
|
2772
2792
|
discoverAt(index: number, descriptor: string, deps: DiscoveryDeps): Promise<DiscoveredContract[]>;
|
|
2793
|
+
/**
|
|
2794
|
+
* Optional: answer for a whole scan window in one batched round-trip.
|
|
2795
|
+
* The scanner prefers it over per-index `discoverAt` calls when present,
|
|
2796
|
+
* which is what keeps a 10-index window to 1-2 indexer requests instead
|
|
2797
|
+
* of one per index. Handlers whose source is inherently per-address (e.g.
|
|
2798
|
+
* boarding, on Esplora) implement only `discoverAt`.
|
|
2799
|
+
*
|
|
2800
|
+
* **All-or-nothing per call.** Either resolve with a map covering *every*
|
|
2801
|
+
* requested index (empty array = confirmed miss), or reject — a handler
|
|
2802
|
+
* whose inner chunk fails partway must discard the partial results and
|
|
2803
|
+
* reject, because a missing index would otherwise read as "no funds here"
|
|
2804
|
+
* and let restore close its gap window on a failed request. The scanner
|
|
2805
|
+
* enforces this rather than trusting it: an incomplete map is treated as a
|
|
2806
|
+
* rejection, making the whole requested range indeterminate (hits present
|
|
2807
|
+
* in it are still persisted) and truncating the scan at the range's first
|
|
2808
|
+
* index. Indices that were not requested are ignored.
|
|
2809
|
+
*/
|
|
2810
|
+
discoverRange?(entries: readonly {
|
|
2811
|
+
index: number;
|
|
2812
|
+
descriptor: string;
|
|
2813
|
+
}[], deps: DiscoveryDeps): Promise<Map<number, DiscoveredContract[]>>;
|
|
2773
2814
|
}
|
|
2774
2815
|
/** Duck-typed guard (mirrors `hasReceiveRotatorFactory`). */
|
|
2775
2816
|
declare function isDiscoverable(handler: ContractHandler<unknown> | undefined): handler is ContractHandler<unknown> & Discoverable;
|
|
@@ -2931,6 +2972,9 @@ declare class ContractWatcher {
|
|
|
2931
2972
|
private reconnectAttempts;
|
|
2932
2973
|
private reconnectTimeoutId?;
|
|
2933
2974
|
private failsafePollIntervalId?;
|
|
2975
|
+
/** See {@link withCoalescedSubscription}. */
|
|
2976
|
+
private subscriptionBatchDepth;
|
|
2977
|
+
private subscriptionUpdateDeferred;
|
|
2934
2978
|
/**
|
|
2935
2979
|
* Create a contract watcher with the given providers and polling settings.
|
|
2936
2980
|
*
|
|
@@ -3025,6 +3069,24 @@ declare class ContractWatcher {
|
|
|
3025
3069
|
* Poll specific contracts and emit events for changes.
|
|
3026
3070
|
*/
|
|
3027
3071
|
private pollContracts;
|
|
3072
|
+
/**
|
|
3073
|
+
* Run `fn` with subscription updates coalesced into a single
|
|
3074
|
+
* `subscribeForScripts` on the way out.
|
|
3075
|
+
*
|
|
3076
|
+
* {@link addContract} re-subscribes eagerly (the watcher may already be
|
|
3077
|
+
* running), and every subscribe posts the *whole* accumulated script list —
|
|
3078
|
+
* so a restore scan that discovers N contracts sends N growing POSTs,
|
|
3079
|
+
* quadratic in script-slots. Inside this scope those updates are only
|
|
3080
|
+
* marked dirty, flushed once on the way out (success and error path alike).
|
|
3081
|
+
*
|
|
3082
|
+
* A contract added inside the scope is therefore not streaming until the
|
|
3083
|
+
* flush. Nothing in the watcher closes that window — the failsafe poll
|
|
3084
|
+
* replays repository state and cannot see VTXOs no one has fetched yet. The
|
|
3085
|
+
* one caller, `scanContracts`, is covered because `Wallet.restore` follows
|
|
3086
|
+
* it with a bulk `refreshVtxos`. A new caller must provide its own
|
|
3087
|
+
* equivalent catch-up, or keep the scope short enough not to need one.
|
|
3088
|
+
*/
|
|
3089
|
+
withCoalescedSubscription<T>(fn: () => Promise<T>): Promise<T>;
|
|
3028
3090
|
private tryUpdateSubscription;
|
|
3029
3091
|
/**
|
|
3030
3092
|
* Update the subscription with scripts that should be watched.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as TaskQueue, b as TaskItem, d as TaskResult } from './taskRunner-Ck0AouQU.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Minimal async key-value storage interface.
|
|
@@ -46,4 +46,4 @@ declare class AsyncStorageTaskQueue implements TaskQueue {
|
|
|
46
46
|
private writeList;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export {
|
|
49
|
+
export { type AsyncStorageLike as A, AsyncStorageTaskQueue as a };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as TaskQueue, b as TaskItem, d as TaskResult } from './taskRunner-bs1AE_BL.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Minimal async key-value storage interface.
|
|
@@ -46,4 +46,4 @@ declare class AsyncStorageTaskQueue implements TaskQueue {
|
|
|
46
46
|
private writeList;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export {
|
|
49
|
+
export { type AsyncStorageLike as A, AsyncStorageTaskQueue as a };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getRandomId, extendVirtualCoinForContract, warnAndFilterVtxosForScript, saveVtxosForContract } from './chunk-
|
|
2
|
-
import { getNormalizedVtxos } from './chunk-
|
|
1
|
+
import { getRandomId, extendVirtualCoinForContract, warnAndFilterVtxosForScript, saveVtxosForContract } from './chunk-T2IVKSZP.js';
|
|
2
|
+
import { getNormalizedVtxos } from './chunk-EFNLTS6Q.js';
|
|
3
3
|
|
|
4
4
|
// src/worker/expo/taskRunner.ts
|
|
5
5
|
async function runTasks(queue, processors, deps) {
|
|
@@ -92,5 +92,5 @@ var contractPollProcessor = {
|
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
export { CONTRACT_POLL_TASK_TYPE, contractPollProcessor, createTaskDependencies, runTasks };
|
|
95
|
-
//# sourceMappingURL=chunk-
|
|
96
|
-
//# sourceMappingURL=chunk-
|
|
95
|
+
//# sourceMappingURL=chunk-27DACHF6.js.map
|
|
96
|
+
//# sourceMappingURL=chunk-27DACHF6.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/worker/expo/taskRunner.ts","../src/worker/expo/processors/contractPollProcessor.ts"],"names":[],"mappings":"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","file":"chunk-G6J6AEMH.js","sourcesContent":["import type { TaskItem, TaskResult, TaskQueue } from \"./taskQueue\";\nimport type { WalletRepository } from \"../../repositories/walletRepository\";\nimport type { ContractRepository } from \"../../repositories/contractRepository\";\nimport type { IndexerProvider } from \"../../providers/indexer\";\nimport type { ArkProvider } from \"../../providers/ark\";\nimport type { ExtendedVirtualCoin, VirtualCoin } from \"../../wallet\";\nimport type { Contract } from \"../../contracts/types\";\nimport { getRandomId, extendVirtualCoinForContract } from \"../../wallet/utils\";\n\n/**\n * Shared dependencies injected into every processor at runtime.\n *\n * `extendVtxo` requires the owning contract — processors must resolve each\n * vtxo's `script` to a known contract (via the contract repository) before\n * calling this. The strict signature prevents the footgun where a missing\n * contract silently falls back to the wallet's default tapscript.\n */\nexport interface TaskDependencies {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) => ExtendedVirtualCoin;\n}\n\n/**\n * A stateless unit that handles one type of task item.\n *\n * Processors must not keep in-memory state across invocations —\n * all coordination lives in the @see TaskQueue and repositories.\n *\n * The `TDeps` parameter defaults to @see TaskDependencies but\n * can be overridden for domain-specific processors (e.g. swap processing).\n */\nexport interface TaskProcessor<TDeps = TaskDependencies> {\n readonly taskType: string;\n execute(item: TaskItem, deps: TDeps): Promise<Omit<TaskResult, \"id\" | \"executedAt\">>;\n}\n\n/**\n * Run all pending tasks from the queue through matching processors.\n *\n * For each task in the inbox:\n * 1. Find the processor whose `taskType` matches `task.type`.\n * 2. Execute it, producing a @see TaskResult.\n * 3. Push the result to the outbox and remove the task from the inbox.\n *\n * Tasks with no matching processor produce a `\"noop\"` result.\n * Processor errors produce a `\"failed\"` result with the error message.\n */\nexport async function runTasks<TDeps = TaskDependencies>(\n queue: TaskQueue,\n processors: TaskProcessor<TDeps>[],\n deps: TDeps,\n): Promise<TaskResult[]> {\n const tasks = await queue.getTasks();\n const processorMap = new Map(processors.map((p) => [p.taskType, p]));\n const results: TaskResult[] = [];\n\n for (const task of tasks) {\n const processor = processorMap.get(task.type);\n\n let partial: Omit<TaskResult, \"id\" | \"executedAt\">;\n\n if (!processor) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"noop\",\n };\n } else {\n try {\n partial = await processor.execute(task, deps);\n } catch (error) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"failed\",\n data: {\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n\n const result: TaskResult = {\n ...partial,\n id: getRandomId(),\n executedAt: Date.now(),\n };\n\n await queue.pushResult(result);\n await queue.removeTask(task.id);\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Options for @see createTaskDependencies.\n */\nexport interface CreateTaskDependenciesOptions {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n}\n\n/**\n * Build the @see TaskDependencies needed by task processors\n * (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)\n *\n * This is the same construction that `defineExpoBackgroundTask` does\n * internally, extracted so that consumers with custom schedulers\n * (e.g. bare React Native with `react-native-background-fetch`)\n * can build deps without depending on Expo.\n */\nexport function createTaskDependencies(options: CreateTaskDependenciesOptions): TaskDependencies {\n return {\n ...options,\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) =>\n extendVirtualCoinForContract(vtxo, contract),\n };\n}\n","import type { TaskItem, TaskResult } from \"../taskQueue\";\nimport type { TaskProcessor, TaskDependencies } from \"../taskRunner\";\nimport type { ExtendedVirtualCoin } from \"../../../wallet\";\nimport { getNormalizedVtxos } from \"../../../wallet/vtxo\";\nimport {\n warnAndFilterVtxosForScript,\n saveVtxosForContract,\n} from \"../../../contracts/vtxoOwnership\";\n\nexport const CONTRACT_POLL_TASK_TYPE = \"contract-poll\";\n\n/**\n * Polls the indexer for the latest VTXO state of every contract and\n * persists the results to the wallet repository.\n *\n * Replicates the polling subset of @see ContractManager.initialize:\n * 1. Load all contracts from the contract repository.\n * 2. Paginated fetch of every VTXO (including spent) from the indexer.\n * 3. Extend each VTXO with tapscript data.\n * 4. Save to the wallet repository.\n *\n * NOTE: the indexer query deliberately omits `spendableOnly`. Every\n * repository implements `saveVtxos` as an upsert with no batch delete,\n * so filtering to spendable-only would leave VTXOs that became spent\n * between polls marked as spendable forever. Fetching the full set lets\n * the upsert overwrite stale records with their latest state.\n */\nexport const contractPollProcessor: TaskProcessor = {\n taskType: CONTRACT_POLL_TASK_TYPE,\n\n async execute(\n item: TaskItem,\n deps: TaskDependencies,\n ): Promise<Omit<TaskResult, \"id\" | \"executedAt\">> {\n const { contractRepository, walletRepository, indexerProvider, extendVtxo } = deps;\n\n const contracts = await contractRepository.getContracts();\n let contractsProcessed = 0;\n let vtxosSaved = 0;\n\n for (const contract of contracts) {\n // Paginated fetch of spendable virtual outputs\n const pageSize = 100;\n let pageIndex = 0;\n let hasMore = true;\n const allVtxos: ExtendedVirtualCoin[] = [];\n\n while (hasMore) {\n const { vtxos, page } = await getNormalizedVtxos(indexerProvider, {\n scripts: [contract.script],\n pageIndex,\n pageSize,\n });\n\n for (const vtxo of vtxos) {\n allVtxos.push(extendVtxo(vtxo, contract));\n }\n\n hasMore = page ? vtxos.length === pageSize : false;\n pageIndex++;\n }\n\n // Skip wrong-script rows (legacy duplicates or indexer drift)\n // before persisting; the loop must keep going for the remaining\n // contracts even when one row is rejected.\n const filtered = warnAndFilterVtxosForScript(\n allVtxos,\n contract.script,\n \"contractPollProcessor\",\n );\n await saveVtxosForContract(walletRepository, contract, filtered);\n vtxosSaved += filtered.length;\n contractsProcessed++;\n }\n\n return {\n taskItemId: item.id,\n type: CONTRACT_POLL_TASK_TYPE,\n status: \"success\",\n data: { contractsProcessed, vtxosSaved },\n };\n },\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/worker/expo/taskRunner.ts","../src/worker/expo/processors/contractPollProcessor.ts"],"names":[],"mappings":"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","file":"chunk-27DACHF6.js","sourcesContent":["import type { TaskItem, TaskResult, TaskQueue } from \"./taskQueue\";\nimport type { WalletRepository } from \"../../repositories/walletRepository\";\nimport type { ContractRepository } from \"../../repositories/contractRepository\";\nimport type { IndexerProvider } from \"../../providers/indexer\";\nimport type { ArkProvider } from \"../../providers/ark\";\nimport type { ExtendedVirtualCoin, VirtualCoin } from \"../../wallet\";\nimport type { Contract } from \"../../contracts/types\";\nimport { getRandomId, extendVirtualCoinForContract } from \"../../wallet/utils\";\n\n/**\n * Shared dependencies injected into every processor at runtime.\n *\n * `extendVtxo` requires the owning contract — processors must resolve each\n * vtxo's `script` to a known contract (via the contract repository) before\n * calling this. The strict signature prevents the footgun where a missing\n * contract silently falls back to the wallet's default tapscript.\n */\nexport interface TaskDependencies {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) => ExtendedVirtualCoin;\n}\n\n/**\n * A stateless unit that handles one type of task item.\n *\n * Processors must not keep in-memory state across invocations —\n * all coordination lives in the @see TaskQueue and repositories.\n *\n * The `TDeps` parameter defaults to @see TaskDependencies but\n * can be overridden for domain-specific processors (e.g. swap processing).\n */\nexport interface TaskProcessor<TDeps = TaskDependencies> {\n readonly taskType: string;\n execute(item: TaskItem, deps: TDeps): Promise<Omit<TaskResult, \"id\" | \"executedAt\">>;\n}\n\n/**\n * Run all pending tasks from the queue through matching processors.\n *\n * For each task in the inbox:\n * 1. Find the processor whose `taskType` matches `task.type`.\n * 2. Execute it, producing a @see TaskResult.\n * 3. Push the result to the outbox and remove the task from the inbox.\n *\n * Tasks with no matching processor produce a `\"noop\"` result.\n * Processor errors produce a `\"failed\"` result with the error message.\n */\nexport async function runTasks<TDeps = TaskDependencies>(\n queue: TaskQueue,\n processors: TaskProcessor<TDeps>[],\n deps: TDeps,\n): Promise<TaskResult[]> {\n const tasks = await queue.getTasks();\n const processorMap = new Map(processors.map((p) => [p.taskType, p]));\n const results: TaskResult[] = [];\n\n for (const task of tasks) {\n const processor = processorMap.get(task.type);\n\n let partial: Omit<TaskResult, \"id\" | \"executedAt\">;\n\n if (!processor) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"noop\",\n };\n } else {\n try {\n partial = await processor.execute(task, deps);\n } catch (error) {\n partial = {\n taskItemId: task.id,\n type: task.type,\n status: \"failed\",\n data: {\n error: error instanceof Error ? error.message : String(error),\n },\n };\n }\n }\n\n const result: TaskResult = {\n ...partial,\n id: getRandomId(),\n executedAt: Date.now(),\n };\n\n await queue.pushResult(result);\n await queue.removeTask(task.id);\n results.push(result);\n }\n\n return results;\n}\n\n/**\n * Options for @see createTaskDependencies.\n */\nexport interface CreateTaskDependenciesOptions {\n walletRepository: WalletRepository;\n contractRepository: ContractRepository;\n indexerProvider: IndexerProvider;\n arkProvider: ArkProvider;\n}\n\n/**\n * Build the @see TaskDependencies needed by task processors\n * (e.g. `src/worker/expo/processors/contractPollProcessor.ts`)\n *\n * This is the same construction that `defineExpoBackgroundTask` does\n * internally, extracted so that consumers with custom schedulers\n * (e.g. bare React Native with `react-native-background-fetch`)\n * can build deps without depending on Expo.\n */\nexport function createTaskDependencies(options: CreateTaskDependenciesOptions): TaskDependencies {\n return {\n ...options,\n extendVtxo: (vtxo: VirtualCoin, contract: Contract) =>\n extendVirtualCoinForContract(vtxo, contract),\n };\n}\n","import type { TaskItem, TaskResult } from \"../taskQueue\";\nimport type { TaskProcessor, TaskDependencies } from \"../taskRunner\";\nimport type { ExtendedVirtualCoin } from \"../../../wallet\";\nimport { getNormalizedVtxos } from \"../../../wallet/vtxo\";\nimport {\n warnAndFilterVtxosForScript,\n saveVtxosForContract,\n} from \"../../../contracts/vtxoOwnership\";\n\nexport const CONTRACT_POLL_TASK_TYPE = \"contract-poll\";\n\n/**\n * Polls the indexer for the latest VTXO state of every contract and\n * persists the results to the wallet repository.\n *\n * Replicates the polling subset of @see ContractManager.initialize:\n * 1. Load all contracts from the contract repository.\n * 2. Paginated fetch of every VTXO (including spent) from the indexer.\n * 3. Extend each VTXO with tapscript data.\n * 4. Save to the wallet repository.\n *\n * NOTE: the indexer query deliberately omits `spendableOnly`. Every\n * repository implements `saveVtxos` as an upsert with no batch delete,\n * so filtering to spendable-only would leave VTXOs that became spent\n * between polls marked as spendable forever. Fetching the full set lets\n * the upsert overwrite stale records with their latest state.\n */\nexport const contractPollProcessor: TaskProcessor = {\n taskType: CONTRACT_POLL_TASK_TYPE,\n\n async execute(\n item: TaskItem,\n deps: TaskDependencies,\n ): Promise<Omit<TaskResult, \"id\" | \"executedAt\">> {\n const { contractRepository, walletRepository, indexerProvider, extendVtxo } = deps;\n\n const contracts = await contractRepository.getContracts();\n let contractsProcessed = 0;\n let vtxosSaved = 0;\n\n for (const contract of contracts) {\n // Paginated fetch of spendable virtual outputs\n const pageSize = 100;\n let pageIndex = 0;\n let hasMore = true;\n const allVtxos: ExtendedVirtualCoin[] = [];\n\n while (hasMore) {\n const { vtxos, page } = await getNormalizedVtxos(indexerProvider, {\n scripts: [contract.script],\n pageIndex,\n pageSize,\n });\n\n for (const vtxo of vtxos) {\n allVtxos.push(extendVtxo(vtxo, contract));\n }\n\n hasMore = page ? vtxos.length === pageSize : false;\n pageIndex++;\n }\n\n // Skip wrong-script rows (legacy duplicates or indexer drift)\n // before persisting; the loop must keep going for the remaining\n // contracts even when one row is rejected.\n const filtered = warnAndFilterVtxosForScript(\n allVtxos,\n contract.script,\n \"contractPollProcessor\",\n );\n await saveVtxosForContract(walletRepository, contract, filtered);\n vtxosSaved += filtered.length;\n contractsProcessed++;\n }\n\n return {\n taskItemId: item.id,\n type: CONTRACT_POLL_TASK_TYPE,\n status: \"success\",\n data: { contractsProcessed, vtxosSaved },\n };\n },\n};\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RestArkProvider, isFetchTimeoutError, RestIndexerProvider, buildVersion, sdkVersion, fetch } from './chunk-
|
|
2
|
-
import { DEFAULT_ARKADE_SERVER_URL, convertVtxo } from './chunk-
|
|
1
|
+
import { RestArkProvider, isFetchTimeoutError, RestIndexerProvider, buildVersion, sdkVersion, fetch } from './chunk-ITT2S4O3.js';
|
|
2
|
+
import { DEFAULT_ARKADE_SERVER_URL, convertVtxo } from './chunk-EFNLTS6Q.js';
|
|
3
3
|
|
|
4
4
|
// src/providers/expoUtils.ts
|
|
5
5
|
async function getExpoFetch(options) {
|
|
@@ -185,5 +185,5 @@ var ExpoIndexerProvider = class extends RestIndexerProvider {
|
|
|
185
185
|
};
|
|
186
186
|
|
|
187
187
|
export { ExpoArkProvider, ExpoIndexerProvider };
|
|
188
|
-
//# sourceMappingURL=chunk-
|
|
189
|
-
//# sourceMappingURL=chunk-
|
|
188
|
+
//# sourceMappingURL=chunk-COB6VP4M.js.map
|
|
189
|
+
//# sourceMappingURL=chunk-COB6VP4M.js.map
|