@arkade-os/sdk 0.4.59 → 0.4.60

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.
Files changed (88) hide show
  1. package/README.md +34 -6
  2. package/dist/adapters/expo.cjs +5 -5
  3. package/dist/adapters/expo.d.cts +2 -2
  4. package/dist/adapters/expo.d.ts +2 -2
  5. package/dist/adapters/expo.js +3 -3
  6. package/dist/adapters/indexedDB.cjs +5 -5
  7. package/dist/adapters/indexedDB.js +4 -4
  8. package/dist/{ark-C9DsPSm8.d.cts → ark-D2_yNhfz.d.cts} +1009 -523
  9. package/dist/{ark-C9DsPSm8.d.ts → ark-D2_yNhfz.d.ts} +1009 -523
  10. package/dist/{asyncStorageTaskQueue-CYHXFfvn.d.cts → asyncStorageTaskQueue-CqijAAPG.d.cts} +1 -1
  11. package/dist/{asyncStorageTaskQueue-BwuWQ1Qc.d.ts → asyncStorageTaskQueue-Vsp6uk8e.d.ts} +1 -1
  12. package/dist/{chunk-PN5RD7ZI.js → chunk-2DINXHGQ.js} +1665 -1149
  13. package/dist/chunk-2DINXHGQ.js.map +1 -0
  14. package/dist/{chunk-IPFGYVF3.cjs → chunk-2XLNQHG4.cjs} +10 -10
  15. package/dist/chunk-2XLNQHG4.cjs.map +1 -0
  16. package/dist/{chunk-VSHY5TBY.js → chunk-3Q7BBUWO.js} +4 -4
  17. package/dist/{chunk-VSHY5TBY.js.map → chunk-3Q7BBUWO.js.map} +1 -1
  18. package/dist/{chunk-DSTYXT2D.cjs → chunk-4A4GRSTB.cjs} +44 -6
  19. package/dist/chunk-4A4GRSTB.cjs.map +1 -0
  20. package/dist/{chunk-H342JPPZ.js → chunk-B66RYHTB.js} +5 -5
  21. package/dist/chunk-B66RYHTB.js.map +1 -0
  22. package/dist/{chunk-YEHGCHIL.js → chunk-FSKANUV4.js} +12 -5
  23. package/dist/chunk-FSKANUV4.js.map +1 -0
  24. package/dist/{chunk-7FA36NOA.cjs → chunk-H7JCHFM6.cjs} +17 -17
  25. package/dist/{chunk-7FA36NOA.cjs.map → chunk-H7JCHFM6.cjs.map} +1 -1
  26. package/dist/{chunk-FIMOVH25.js → chunk-JBULXTCC.js} +40 -7
  27. package/dist/chunk-JBULXTCC.js.map +1 -0
  28. package/dist/{chunk-DYNB6POO.cjs → chunk-KNS5MTTI.cjs} +3820 -2915
  29. package/dist/chunk-KNS5MTTI.cjs.map +1 -0
  30. package/dist/{chunk-2XO43UHI.cjs → chunk-MZNLCMUP.cjs} +1686 -1169
  31. package/dist/chunk-MZNLCMUP.cjs.map +1 -0
  32. package/dist/{chunk-V2KENVN6.cjs → chunk-PRFL62ID.cjs} +22 -15
  33. package/dist/chunk-PRFL62ID.cjs.map +1 -0
  34. package/dist/{chunk-OVSNY3HC.js → chunk-Y54MUBT7.js} +3476 -2584
  35. package/dist/chunk-Y54MUBT7.js.map +1 -0
  36. package/dist/contracts/handlers/index.cjs +12 -8
  37. package/dist/contracts/handlers/index.d.cts +3 -3
  38. package/dist/contracts/handlers/index.d.ts +3 -3
  39. package/dist/contracts/handlers/index.js +2 -2
  40. package/dist/{delegate-D0eGaz3J.d.cts → delegate-DNEuM_nK.d.cts} +1 -1
  41. package/dist/{delegate-B_oKWm1k.d.ts → delegate-DidNTsKm.d.ts} +1 -1
  42. package/dist/{index-BmK6tEqf.d.ts → index-BP8-zniX.d.cts} +182 -26
  43. package/dist/{index-BG2AL2Ie.d.cts → index-DzQbNQUG.d.ts} +182 -26
  44. package/dist/index.cjs +302 -230
  45. package/dist/index.d.cts +286 -48
  46. package/dist/index.d.ts +286 -48
  47. package/dist/index.js +4 -4
  48. package/dist/repositories/realm/index.cjs +43 -23
  49. package/dist/repositories/realm/index.cjs.map +1 -1
  50. package/dist/repositories/realm/index.d.cts +21 -9
  51. package/dist/repositories/realm/index.d.ts +21 -9
  52. package/dist/repositories/realm/index.js +29 -9
  53. package/dist/repositories/realm/index.js.map +1 -1
  54. package/dist/repositories/sqlite/index.cjs +48 -23
  55. package/dist/repositories/sqlite/index.cjs.map +1 -1
  56. package/dist/repositories/sqlite/index.d.cts +9 -3
  57. package/dist/repositories/sqlite/index.d.ts +9 -3
  58. package/dist/repositories/sqlite/index.js +35 -10
  59. package/dist/repositories/sqlite/index.js.map +1 -1
  60. package/dist/{taskRunner-Cy4Gh8n7.d.ts → taskRunner-9gnlYEpb.d.ts} +1 -1
  61. package/dist/{taskRunner-CBvKIttE.d.cts → taskRunner-BEQNFEa4.d.cts} +1 -1
  62. package/dist/wallet/expo/background.cjs +14 -14
  63. package/dist/wallet/expo/background.d.cts +3 -3
  64. package/dist/wallet/expo/background.d.ts +3 -3
  65. package/dist/wallet/expo/background.js +6 -6
  66. package/dist/wallet/expo/index.cjs +17 -14
  67. package/dist/wallet/expo/index.cjs.map +1 -1
  68. package/dist/wallet/expo/index.d.cts +5 -4
  69. package/dist/wallet/expo/index.d.ts +5 -4
  70. package/dist/wallet/expo/index.js +8 -5
  71. package/dist/wallet/expo/index.js.map +1 -1
  72. package/dist/{wallet-EyVDhqzP.d.ts → wallet-C_MYHyOj.d.ts} +155 -17
  73. package/dist/{wallet-DlXemAzP.d.cts → wallet-ipUA1XCp.d.cts} +155 -17
  74. package/dist/worker/expo/index.cjs +9 -9
  75. package/dist/worker/expo/index.d.cts +5 -5
  76. package/dist/worker/expo/index.d.ts +5 -5
  77. package/dist/worker/expo/index.js +5 -5
  78. package/package.json +4 -2
  79. package/dist/chunk-2XO43UHI.cjs.map +0 -1
  80. package/dist/chunk-DSTYXT2D.cjs.map +0 -1
  81. package/dist/chunk-DYNB6POO.cjs.map +0 -1
  82. package/dist/chunk-FIMOVH25.js.map +0 -1
  83. package/dist/chunk-H342JPPZ.js.map +0 -1
  84. package/dist/chunk-IPFGYVF3.cjs.map +0 -1
  85. package/dist/chunk-OVSNY3HC.js.map +0 -1
  86. package/dist/chunk-PN5RD7ZI.js.map +0 -1
  87. package/dist/chunk-V2KENVN6.cjs.map +0 -1
  88. package/dist/chunk-YEHGCHIL.js.map +0 -1
@@ -970,6 +970,27 @@ declare function classifyContractSigner(contractServerPubKeyHex: string, info: A
970
970
  */
971
971
  declare function isCooperativelyMigratable(status: SignerStatus): boolean;
972
972
 
973
+ /**
974
+ * Outpoints (`txid:vout`) of VTXOs that are NOT cooperatively spendable because
975
+ * their contract's signer is past its cutoff (`EXPIRED`) and the VTXO has not
976
+ * yet been swept by the server. Such funds are unspendable until they recover
977
+ * (the server sweeps the batch at expiry, then the swept output re-settles under
978
+ * the active signer), so `getBalance` buckets them under `pendingRecovery` and
979
+ * coin selection skips them — otherwise a send would pick a VTXO the operator
980
+ * will not co-sign and fail at submit.
981
+ *
982
+ * Pure + offline: classification uses a cached {@link SignerSet}, never a fresh
983
+ * GetInfo. `MIGRATABLE` / `DUE_NOW` (still cooperatively spendable), already-
984
+ * swept (recoverable), `CURRENT`, and `UNKNOWN_SIGNER` rows are all left alone.
985
+ */
986
+ declare function selectPendingRecoveryOutpoints(contractsWithVtxos: ReadonlyArray<{
987
+ contract: {
988
+ params: {
989
+ serverPubKey?: string;
990
+ };
991
+ };
992
+ vtxos: ReadonlyArray<VirtualCoin>;
993
+ }>, signerSet: SignerSet, nowSeconds?: number): Set<string>;
973
994
  /**
974
995
  * Configuration options for automatic virtual output renewal
975
996
  *
@@ -1836,9 +1857,19 @@ interface ContractFilter {
1836
1857
  state?: ContractState | ContractState[];
1837
1858
  /** Filter by contract type(s) */
1838
1859
  type?: string | string[];
1860
+ /**
1861
+ * Filter by watch state(s). Rows written before the field existed
1862
+ * have no stored value and match `"watched"`.
1863
+ * @see ContractWatchState
1864
+ */
1865
+ watch?: ContractWatchState | ContractWatchState[];
1839
1866
  }
1840
1867
  interface ContractRepository extends AsyncDisposable {
1841
- readonly version: 1;
1868
+ /**
1869
+ * 2 — {@link Contract.watch}. An implementation must persist and
1870
+ * round-trip it, and treat a row without one as `"watched"`.
1871
+ */
1872
+ readonly version: 2;
1842
1873
  /**
1843
1874
  * Clear all data from storage.
1844
1875
  */
@@ -1972,153 +2003,524 @@ interface VirtualTxRepository extends AsyncDisposable {
1972
2003
  pruneForSpentVtxo(vtxo: Outpoint): Promise<void>;
1973
2004
  }
1974
2005
 
1975
- type RefreshVtxosOptions = {
2006
+ /** One transaction's participation in one logical action. */
2007
+ interface GroupMembership {
1976
2008
  /**
1977
- * Narrow the refresh to these scripts. A subset query, so the
1978
- * cursor is not advanced: contracts outside the list may have data
1979
- * we'd skip.
2009
+ * Stable id of the action; txs sharing it group together. Third-party
2010
+ * resolvers should namespace it (`"vendor:thing"`) to avoid colliding with
2011
+ * other resolvers' groups. SDK built-ins use namespaced ids such as `boarding:`.
2012
+ * A membership with an empty groupId is dropped.
1980
2013
  */
1981
- scripts?: string[];
2014
+ groupId: string;
2015
+ /** Human label for the action, e.g. "Dice game". */
2016
+ label?: string;
2017
+ /** App category for icon/filtering, e.g. "game". */
2018
+ kind?: string;
1982
2019
  /**
1983
- * Time window overriding the cursor-derived one. The cursor never
1984
- * advances on a windowed query because the window may skip data
1985
- * outside its bounds.
2020
+ * Free-form row data. Same-group metadata is shallow-merged with
2021
+ * earlier-resolver keys winning.
1986
2022
  */
1987
- after?: number;
1988
- /** @see after */
1989
- before?: number;
2023
+ metadata?: Record<string, unknown>;
1990
2024
  /**
1991
- * When true and `scripts` is not set, refresh every contract in
1992
- * the repository rather than the watcher's watched set which
1993
- * differs only for rows the watcher never registered, since
1994
- * retirement doesn't narrow that set
1995
- * (see {@link ContractWatcher.getWatchedContracts}).
1996
- *
1997
- * Because this is a *superset* of the watched set, the cursor
1998
- * invariant still holds and the cursor advances normally (unless
1999
- * `after` / `before` is also supplied).
2000
- *
2001
- * @defaultValue `false`
2025
+ * This tx's unsigned sat contribution to this group. Defaults to the tx's
2026
+ * full amount; the builder applies direction. Use it to split a batched tx
2027
+ * across groups. Same-key receive rows paired with a sent row are treated
2028
+ * as change and excluded from `Activity.amount`. A membership with a
2029
+ * non-finite amount (NaN/Infinity) is dropped.
2002
2030
  */
2003
- includeInactive?: boolean;
2004
- };
2005
- /**
2006
- * A single `Discoverable` handler's discovery failure, captured during a
2007
- * {@link IContractManager.scanContracts} run instead of aborting the loop.
2008
- *
2009
- * TODO(next major): rename `index` → `fromIndex` so the pair reads
2010
- * `fromIndex`/`toIndex`. It stays `index` here only to keep this exported
2011
- * shape backward-compatible.
2012
- */
2013
- interface HandlerError {
2014
- handler: string;
2015
- /** The failed index, or the first index of a failed `discoverRange` window. */
2016
- index: number;
2017
- /** Inclusive end of a failed `discoverRange` window; absent for a single index. */
2018
- toIndex?: number;
2019
- error: unknown;
2031
+ amount?: number;
2020
2032
  }
2021
- /**
2022
- * Outcome of a {@link IContractManager.scanContracts} run.
2023
- */
2024
- interface ScanResult {
2025
- /** @deprecated Alias of {@link ScanResult.highestConfirmedUsedIndex}. */
2026
- lastIndexUsed: number;
2033
+ /** A pluggable resolver keyed by `id`. */
2034
+ interface ActivityResolver {
2027
2035
  /**
2028
- * Highest HD index at which any handler confirmed a contract (`-1` if none),
2029
- * including hits past {@link ScanResult.truncatedAt}. Safe to record
2030
- * unconditionally: the HD watermark it feeds is a monotonic max over a scan
2031
- * that always restarts at 0, so it cannot skip an index — while withholding
2032
- * it risks re-issuing a funded index as a fresh receive address.
2036
+ * Registry key override or remove by it. Namespace it (`"vendor:games"`)
2037
+ * so independent libraries don't clobber each other; `use()` overwrites
2038
+ * silently on a duplicate id.
2033
2039
  */
2034
- highestConfirmedUsedIndex: number;
2040
+ id: string;
2035
2041
  /**
2036
- * First index a handler failed at, making it *indeterminate* neither a hit
2037
- * nor a confirmed miss. The scan stops there, so indices `>= truncatedAt` are
2038
- * unverified and the caller must retry (scanning is idempotent). `undefined`
2039
- * when the scan closed a genuine gap.
2042
+ * Load correlation data before `resolve` runs. If it rejects, this resolver
2043
+ * contributes no memberships.
2040
2044
  */
2041
- truncatedAt?: number;
2042
- /** Per-handler discovery failures. Non-empty implies `truncatedAt` is set. */
2043
- handlerErrors: HandlerError[];
2045
+ prepare?(): Promise<void>;
2046
+ /** Pure and synchronous. The groups this tx belongs to, or undefined to leave it plain. */
2047
+ resolve(tx: ArkTransaction): GroupMembership[] | undefined;
2048
+ }
2049
+ /** The non-id, non-amount part of a {@link GroupMembership}. */
2050
+ interface ActivityIntent {
2051
+ /** Human label for the action, e.g. "Dice game". */
2052
+ label?: string;
2053
+ /** App category for icon/filtering, e.g. "game". */
2054
+ kind?: string;
2055
+ /** Free-form row data, shallow-merged across the group's resolvers (first-writer-wins). */
2056
+ metadata?: Record<string, unknown>;
2057
+ }
2058
+ /** One logical activity. */
2059
+ interface Activity {
2060
+ /** The groupId, or the natural tx key for untagged rows. */
2061
+ id: string;
2062
+ /** Merged intent for the group, if any resolver tagged it. */
2063
+ intent?: ActivityIntent;
2064
+ /** Member txs, oldest-first. */
2065
+ txs: ArkTransaction[];
2066
+ /** Signed net sats: positive received, negative sent; same-key change rows are excluded. */
2067
+ amount: number;
2068
+ /** Earliest member createdAt (ms since epoch). */
2069
+ createdAt: number;
2070
+ /** True once every member tx is settled. */
2071
+ settled: boolean;
2072
+ }
2073
+ /** Resolver registry keyed by id. */
2074
+ declare class ActivityRegistry {
2075
+ private readonly resolvers;
2076
+ /** Add a resolver, or override an existing one with the same id (kept in place). */
2077
+ use(resolver: ActivityResolver): void;
2078
+ /** Remove a resolver (built-in or custom) by id. */
2079
+ remove(id: string): void;
2080
+ /** The registered resolver ids, in registration order. */
2081
+ list(): string[];
2082
+ /** All registered resolvers, in registration (priority) order. */
2083
+ all(): ActivityResolver[];
2044
2084
  }
2085
+ /** Built-in resolver: labels on-chain boarding (deposit) transactions. */
2086
+ declare function boardingResolver(): ActivityResolver;
2087
+ /** Built-in resolver: labels collaborative exits (VTXOs forfeited to chain in a batch). */
2088
+ declare function collabExitResolver(): ActivityResolver;
2045
2089
  /**
2046
- * Options for {@link IContractManager.scanContracts}.
2090
+ * Built-in resolver: labels the genesis transaction of a minted asset — "Asset
2091
+ * mint" on the issuer's sent tx, "Asset receive" when the fresh supply arrives
2092
+ * in the genesis tx itself. An asset id encodes its genesis txid; reissues and
2093
+ * transfers carry the asset under a different `arkTxid`, so they are left plain.
2094
+ *
2095
+ * `metadata.amount` is the decimal string of the asset's `bigint` amount, kept
2096
+ * as a string so large supplies survive JSON round-trips without truncation.
2097
+ * Recover the value with `BigInt(metadata.amount as string)` — using it
2098
+ * directly in arithmetic coerces (`"10" + 1` is `"101"`, not `11`) and loses
2099
+ * precision past `Number.MAX_SAFE_INTEGER`.
2047
2100
  */
2048
- interface ScanContractsOptions {
2049
- /** Default 20. A non-positive / non-integer value throws. */
2050
- gapLimit?: number;
2051
- /**
2052
- * Number of HD indices probed per window (default
2053
- * {@link DEFAULT_SCAN_BATCH}). The gap loop stays gap-limit bounded and
2054
- * the discovered set is identical regardless of batch size; the window is
2055
- * also the unit a batching handler ({@link Discoverable.discoverRange})
2056
- * collapses into one request, so it doubles as the batch width. A
2057
- * non-positive / non-integer value throws. Ignored when `hd` is false (the
2058
- * static pass probes only index 0).
2059
- */
2060
- batchSize?: number;
2061
- /** HD mode → unbounded gap loop guided by the gap counter; false → probe only index 0 (single static pass). */
2062
- hd: boolean;
2063
- /**
2064
- * Materialize the descriptor at an HD index. Pure derivation; a throw
2065
- * here is structural/fatal and propagates out of `scanContracts`.
2066
- */
2067
- materialize: (index: number) => string;
2068
- /** Read-only context injected into every `discoverAt` call. */
2069
- deps: DiscoveryDeps;
2070
- }
2101
+ declare function assetMintResolver(): ActivityResolver;
2071
2102
  /**
2072
- * Freshness of the ContractManager's provider-backed sync. `degraded` means the
2073
- * most recent sync (boot, best-effort read, or contract hydration) hit a
2074
- * retryable indexer/operator failure and the manager is serving repository
2075
- * state; it returns to `online` on the next successful sync. This only
2076
- * describes sync freshness — never wallet data itself.
2103
+ * A registry pre-populated with the SDK's built-in resolvers: `boarding`,
2104
+ * `collab-exit`, and `asset-mint`.
2077
2105
  */
2078
- type ContractSyncState = {
2079
- mode: "online";
2080
- lastSyncedAt?: number;
2081
- } | {
2082
- mode: "degraded";
2083
- reason: string;
2084
- lastSyncedAt?: number;
2085
- };
2086
- interface IContractManager extends Disposable {
2106
+ declare function createDefaultActivityRegistry(): ActivityRegistry;
2107
+
2108
+ /**
2109
+ * Intent proof implementation for Bitcoin message signing.
2110
+ *
2111
+ * Intent proof defines a standard for signing Bitcoin messages as well as proving
2112
+ * ownership of outputs.
2113
+ *
2114
+ * This namespace provides utilities for creating and validating Intent proof.
2115
+ *
2116
+ * It is greatly inspired by BIP322.
2117
+ * @see https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki
2118
+ *
2119
+ * @example
2120
+ * ```typescript
2121
+ * // Create a Intent proof
2122
+ * const proof = Intent.create(
2123
+ * "Hello Bitcoin!",
2124
+ * [input],
2125
+ * [output]
2126
+ * );
2127
+ *
2128
+ * // Sign the proof
2129
+ * const signedProof = await identity.sign(proof);
2130
+ *
2131
+ */
2132
+ declare namespace Intent {
2133
+ type Proof = Transaction;
2087
2134
  /**
2088
- * Create and register a new contract.
2089
- *
2090
- * Implementations may validate that:
2091
- * - A handler exists for `params.type`
2092
- * - `params.script` matches the script derived from `params.params`
2135
+ * Creates a new Intent proof unsigned transaction.
2093
2136
  *
2094
- * The contract script is used as the unique identifier.
2095
- */
2096
- createContract(params: CreateContractParams): Promise<Contract>;
2097
- /**
2098
- * List contracts with optional filters.
2137
+ * This function constructs a special transaction that can be signed to prove
2138
+ * ownership of onchain and virtual outputs. The proof includes the message to be
2139
+ * signed and the inputs/outputs that demonstrate ownership.
2099
2140
  *
2100
- * @example
2101
- * ```typescript
2102
- * const vhtlcs = await manager.getContracts({ type: "vhtlc" });
2103
- * const active = await manager.getContracts({ state: "active" });
2104
- * ```
2141
+ * @param message - The Intent message to be signed, either raw string of Message object
2142
+ * @param ins - Array of transaction inputs to prove ownership of
2143
+ * @param outputs - Optional array of transaction outputs
2144
+ * @returns An unsigned Intent proof transaction
2105
2145
  */
2106
- getContracts(filter?: GetContractsFilter): Promise<Contract[]>;
2146
+ function create(message: string | Message, ins: (TransactionInput | ExtendedCoin)[], outputs?: TransactionOutput[]): Proof;
2107
2147
  /**
2108
- * List contracts and their current virtual outputs.
2148
+ * Compute the fee paid by an intent proof transaction.
2109
2149
  *
2110
- * If no filter is provided, returns all contracts with their virtual outputs.
2111
- */
2112
- getContractsWithVtxos(filter?: GetContractsFilter): Promise<ContractWithVtxos[]>;
2113
- /**
2114
- * Latest provider-sync health (online vs. degraded to repository data).
2115
- * See {@link ContractSyncState}.
2150
+ * @param proof - Intent proof transaction
2151
+ * @returns The fee in satoshis
2116
2152
  */
2117
- getSyncState(): ContractSyncState;
2118
- /**
2119
- * Stamp raw virtual outputs with the correct per-contract tapscripts
2120
- * (forfeit, intent, tap tree).
2121
- *
2153
+ function fee(proof: Proof): number;
2154
+ type RegisterMessage = {
2155
+ type: "register";
2156
+ onchain_output_indexes: number[];
2157
+ valid_at: number;
2158
+ expire_at: number;
2159
+ cosigners_public_keys: string[];
2160
+ };
2161
+ type DeleteMessage = {
2162
+ type: "delete";
2163
+ expire_at: number;
2164
+ };
2165
+ type GetPendingTxMessage = {
2166
+ type: "get-pending-tx";
2167
+ expire_at: number;
2168
+ };
2169
+ type Message = RegisterMessage | DeleteMessage | GetPendingTxMessage;
2170
+ /**
2171
+ * Serialize an intent message to the canonical JSON string used for signing.
2172
+ *
2173
+ * @param message - Intent message payload
2174
+ * @returns Canonical string form of the message
2175
+ */
2176
+ function encodeMessage(message: Message): string;
2177
+ }
2178
+
2179
+ /**
2180
+ * A source of unilateral-exit chain data for a set of VTXOs. Sources are tried
2181
+ * in order by the resolver; a source returns `null` (chain) or omits keys (psbts)
2182
+ * for data it cannot supply — a "miss" — and the resolver falls through.
2183
+ */
2184
+ interface ExitDataSource {
2185
+ readonly name: string;
2186
+ /** Full ancestry chain for a vtxo (all pages merged), or null on a miss. */
2187
+ getVtxoChain(vtxo: Outpoint): Promise<ChainTx[] | null>;
2188
+ /** Base64 PSBTs this source has, keyed by (unsigned) txid. Absent key = miss. */
2189
+ getVirtualTxs(txids: string[]): Promise<Map<string, string>>;
2190
+ }
2191
+ /** Reads exit chain data through an ordered chain of sources. */
2192
+ interface ExitChainResolver {
2193
+ getVtxoChain(vtxo: Outpoint): Promise<ChainTx[]>;
2194
+ getVirtualTxs(txids: string[]): Promise<string[]>;
2195
+ }
2196
+ /**
2197
+ * Assemble the standard exit-data resolver: local repo (if configured) → any
2198
+ * extra sources (e.g. a future provider) → indexer. Read-through persists to the
2199
+ * repository. With no repository this is exactly the indexer path (a no-op seam).
2200
+ */
2201
+ declare function createExitChainResolver(params: {
2202
+ indexer: IndexerProvider;
2203
+ repository?: VirtualTxRepository;
2204
+ extraSources?: ExitDataSource[];
2205
+ }): ExitChainResolver;
2206
+
2207
+ type ExitCaptureMode = "lite" | "full";
2208
+
2209
+ /**
2210
+ * Delegate identity and fee information returned by `getDelegateInfo`.
2211
+ */
2212
+ interface DelegateInfo {
2213
+ /** Delegate public key. */
2214
+ pubkey: string;
2215
+ /** Delegate fee amount or expression returned by the delegate. */
2216
+ fee: string;
2217
+ /** Address for delegate fee collection. Sourced from `delegatorAddress` in Fulmine response, for now. */
2218
+ delegateAddress: string;
2219
+ /** @deprecated alias for @see DelegateInfo.delegateAddress */
2220
+ delegatorAddress?: string;
2221
+ }
2222
+ /**
2223
+ * Optional delegate behavior flags.
2224
+ */
2225
+ interface DelegateOptions {
2226
+ /**
2227
+ * Instruct the delegate not to replace an existing delegation
2228
+ * (meaning a signed register intent and its forfeit transactions)
2229
+ * that already includes at least one virtual output from this request.
2230
+ *
2231
+ * @defaultValue `false`
2232
+ */
2233
+ rejectReplace?: boolean;
2234
+ }
2235
+ /**
2236
+ * Provider interface for remote delegation service.
2237
+ */
2238
+ interface DelegateProvider {
2239
+ /**
2240
+ * Request delegation for a signed register intent and its forfeit transactions.
2241
+ *
2242
+ * @param intent - Signed register intent to delegate
2243
+ * @param forfeitTxs - Forfeit transactions associated with the delegation request
2244
+ * @param options - Optional delegate behavior flags
2245
+ */
2246
+ delegate(intent: SignedIntent<Intent.RegisterMessage>, forfeitTxs: string[], options?: DelegateOptions): Promise<void>;
2247
+ /**
2248
+ * Fetch delegate metadata such as pubkey, fee, and delegate address.
2249
+ *
2250
+ * @returns Delegate identity and fee information
2251
+ */
2252
+ getDelegateInfo(): Promise<DelegateInfo>;
2253
+ }
2254
+ /** @deprecated alias for @see DelegateProvider */
2255
+ type DelegatorProvider = DelegateProvider;
2256
+ /**
2257
+ * REST-based delegate provider implementation.
2258
+ * @example
2259
+ * ```typescript
2260
+ * const provider = new RestDelegateProvider('https://delegate.example.com');
2261
+ * const info = await provider.getDelegateInfo();
2262
+ * await provider.delegate(intent, forfeitTxs);
2263
+ * ```
2264
+ */
2265
+ declare class RestDelegateProvider implements DelegateProvider {
2266
+ url: string;
2267
+ /**
2268
+ * Create a REST delegate provider targeting the given base URL.
2269
+ *
2270
+ * @param url - Base URL of the remote delegation service.
2271
+ */
2272
+ constructor(url: string);
2273
+ /**
2274
+ * Submit a delegation request to the remote delegation service.
2275
+ *
2276
+ * @param intent - Signed register intent to delegate
2277
+ * @param forfeitTxs - Forfeit transactions associated with the delegation request
2278
+ * @param options - Optional delegate behavior flags
2279
+ * @throws Error if the remote service rejects the request
2280
+ */
2281
+ delegate(intent: SignedIntent<Intent.RegisterMessage>, forfeitTxs: string[], options?: DelegateOptions): Promise<void>;
2282
+ /**
2283
+ * Fetch delegate metadata exposed by the remote delegation service.
2284
+ *
2285
+ * @returns Delegate identity and fee information
2286
+ * @throws Error if the remote service returns invalid data
2287
+ */
2288
+ getDelegateInfo(): Promise<DelegateInfo>;
2289
+ }
2290
+ /** @deprecated alias for @see RestDelegateProvider */
2291
+ declare const RestDelegatorProvider: typeof RestDelegateProvider;
2292
+ type RestDelegatorProvider = RestDelegateProvider;
2293
+
2294
+ interface IDelegateManager {
2295
+ /**
2296
+ * Delegate virtual outputs to the remote delegation service.
2297
+ *
2298
+ * Vtxos that are not locked to a delegate-type contract (no tap leaf
2299
+ * matches the delegate's pubkey) are filtered out silently, since they
2300
+ * cannot be co-signed by the delegate.
2301
+ *
2302
+ * @param vtxos - Virtual outputs to delegate
2303
+ * @param destination - Arkade address that should receive renewed funds
2304
+ * @param delegateAt - Optional timestamp to force a specific delegation time
2305
+ * @returns Successfully delegated and failed outpoint groups
2306
+ */
2307
+ delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
2308
+ delegated: Outpoint[];
2309
+ failed: {
2310
+ outpoints: Outpoint[];
2311
+ error: unknown;
2312
+ }[];
2313
+ }>;
2314
+ /** Fetch delegate metadata such as pubkey, fee, and delegate address. */
2315
+ getDelegateInfo(): Promise<DelegateInfo>;
2316
+ }
2317
+ /** @deprecated alias for @see IDelegateManager */
2318
+ type IDelegatorManager = IDelegateManager;
2319
+ declare class DelegateManagerImpl implements IDelegateManager {
2320
+ readonly delegateProvider: DelegateProvider;
2321
+ readonly arkInfoProvider: Pick<ArkProvider, "getInfo">;
2322
+ readonly identity: Identity;
2323
+ /** Create a delegate manager from the configured provider, Arkade info source, and wallet identity. */
2324
+ constructor(delegateProvider: DelegateProvider, arkInfoProvider: Pick<ArkProvider, "getInfo">, identity: Identity);
2325
+ getDelegateInfo(): Promise<DelegateInfo>;
2326
+ delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
2327
+ delegated: Outpoint[];
2328
+ failed: {
2329
+ outpoints: Outpoint[];
2330
+ error: unknown;
2331
+ }[];
2332
+ }>;
2333
+ }
2334
+ /** @deprecated alias for @see DelegateManagerImpl */
2335
+ declare const DelegatorManagerImpl: typeof DelegateManagerImpl;
2336
+ type DelegatorManagerImpl = DelegateManagerImpl;
2337
+
2338
+ /**
2339
+ * Tapscript fields derived purely from a contract's params. They are identical
2340
+ * for every VTXO locked to the same contract, so they can be memoized per
2341
+ * contract (see {@link ContractTapscriptCache}).
2342
+ */
2343
+ type ContractTapscripts = Pick<ExtendedVirtualCoin, "forfeitTapLeafScript" | "intentTapLeafScript" | "tapTree">;
2344
+ /**
2345
+ * Cache of per-contract tapscript data, keyed by `contract.script`. Building
2346
+ * the taproot tree via `handler.createScript(contract.params)` is the dominant
2347
+ * cost when annotating large VTXO sets; passing a shared cache across an
2348
+ * annotation batch rebuilds it once per distinct contract instead of once per
2349
+ * VTXO (see #521).
2350
+ */
2351
+ type ContractTapscriptCache = Map<string, ContractTapscripts>;
2352
+ declare function getRandomId(): string;
2353
+ /**
2354
+ * What a recipient Arkade address must match. An address failing either check
2355
+ * belongs to another network or operator, so this wallet's operator cannot
2356
+ * create the VTXO where the recipient's wallet expects it.
2357
+ */
2358
+ type RecipientAddressContext = {
2359
+ hrp: string;
2360
+ signerSet: SignerSet;
2361
+ };
2362
+
2363
+ /**
2364
+ * An input for {@link IContractManager.assertSpendableNow}.
2365
+ *
2366
+ * The outpoint and script are what identify the owning contract. A full
2367
+ * {@link VirtualCoin} is accepted and preferred: a relative (CSV) timelock is
2368
+ * measured from this coin's own confirmation, so `status.block_height` /
2369
+ * `status.block_time` are the only way to answer one. Pass the coin where you
2370
+ * have it; the bare shape still answers every absolute (CLTV) question.
2371
+ */
2372
+ type AssertSpendableInput = {
2373
+ txid: string;
2374
+ vout: number;
2375
+ script: string;
2376
+ };
2377
+ type RefreshVtxosOptions = {
2378
+ /**
2379
+ * Narrow the refresh to these scripts. A subset query, so the
2380
+ * cursor is not advanced: contracts outside the list may have data
2381
+ * we'd skip.
2382
+ */
2383
+ scripts?: string[];
2384
+ /**
2385
+ * Time window overriding the cursor-derived one. The cursor never
2386
+ * advances on a windowed query because the window may skip data
2387
+ * outside its bounds.
2388
+ */
2389
+ after?: number;
2390
+ /** @see after */
2391
+ before?: number;
2392
+ /**
2393
+ * When true and `scripts` is not set, refresh every contract in
2394
+ * the repository rather than the watcher's watched set — which
2395
+ * differs only for rows the watcher never registered, since
2396
+ * retirement doesn't narrow that set
2397
+ * (see {@link ContractWatcher.getWatchedContracts}).
2398
+ *
2399
+ * Because this is a *superset* of the watched set, the cursor
2400
+ * invariant still holds and the cursor advances normally (unless
2401
+ * `after` / `before` is also supplied).
2402
+ *
2403
+ * @defaultValue `false`
2404
+ */
2405
+ includeInactive?: boolean;
2406
+ };
2407
+ /**
2408
+ * A single `Discoverable` handler's discovery failure, captured during a
2409
+ * {@link IContractManager.scanContracts} run instead of aborting the loop.
2410
+ *
2411
+ * TODO(next major): rename `index` → `fromIndex` so the pair reads
2412
+ * `fromIndex`/`toIndex`. It stays `index` here only to keep this exported
2413
+ * shape backward-compatible.
2414
+ */
2415
+ interface HandlerError {
2416
+ handler: string;
2417
+ /** The failed index, or the first index of a failed `discoverRange` window. */
2418
+ index: number;
2419
+ /** Inclusive end of a failed `discoverRange` window; absent for a single index. */
2420
+ toIndex?: number;
2421
+ error: unknown;
2422
+ }
2423
+ /**
2424
+ * Outcome of a {@link IContractManager.scanContracts} run.
2425
+ */
2426
+ interface ScanResult {
2427
+ /** @deprecated Alias of {@link ScanResult.highestConfirmedUsedIndex}. */
2428
+ lastIndexUsed: number;
2429
+ /**
2430
+ * Highest HD index at which any handler confirmed a contract (`-1` if none),
2431
+ * including hits past {@link ScanResult.truncatedAt}. Safe to record
2432
+ * unconditionally: the HD watermark it feeds is a monotonic max over a scan
2433
+ * that always restarts at 0, so it cannot skip an index — while withholding
2434
+ * it risks re-issuing a funded index as a fresh receive address.
2435
+ */
2436
+ highestConfirmedUsedIndex: number;
2437
+ /**
2438
+ * First index a handler failed at, making it *indeterminate* — neither a hit
2439
+ * nor a confirmed miss. The scan stops there, so indices `>= truncatedAt` are
2440
+ * unverified and the caller must retry (scanning is idempotent). `undefined`
2441
+ * when the scan closed a genuine gap.
2442
+ */
2443
+ truncatedAt?: number;
2444
+ /** Per-handler discovery failures. Non-empty implies `truncatedAt` is set. */
2445
+ handlerErrors: HandlerError[];
2446
+ }
2447
+ /**
2448
+ * Options for {@link IContractManager.scanContracts}.
2449
+ */
2450
+ interface ScanContractsOptions {
2451
+ /** Default 20. A non-positive / non-integer value throws. */
2452
+ gapLimit?: number;
2453
+ /**
2454
+ * Number of HD indices probed per window (default
2455
+ * {@link DEFAULT_SCAN_BATCH}). The gap loop stays gap-limit bounded and
2456
+ * the discovered set is identical regardless of batch size; the window is
2457
+ * also the unit a batching handler ({@link Discoverable.discoverRange})
2458
+ * collapses into one request, so it doubles as the batch width. A
2459
+ * non-positive / non-integer value throws. Ignored when `hd` is false (the
2460
+ * static pass probes only index 0).
2461
+ */
2462
+ batchSize?: number;
2463
+ /** HD mode → unbounded gap loop guided by the gap counter; false → probe only index 0 (single static pass). */
2464
+ hd: boolean;
2465
+ /**
2466
+ * Materialize the descriptor at an HD index. Pure derivation; a throw
2467
+ * here is structural/fatal and propagates out of `scanContracts`.
2468
+ */
2469
+ materialize: (index: number) => string;
2470
+ /** Read-only context injected into every `discoverAt` call. */
2471
+ deps: DiscoveryDeps;
2472
+ }
2473
+ /**
2474
+ * Freshness of the ContractManager's provider-backed sync. `degraded` means the
2475
+ * most recent sync (boot, best-effort read, or contract hydration) hit a
2476
+ * retryable indexer/operator failure and the manager is serving repository
2477
+ * state; it returns to `online` on the next successful sync. This only
2478
+ * describes sync freshness — never wallet data itself.
2479
+ */
2480
+ type ContractSyncState = {
2481
+ mode: "online";
2482
+ lastSyncedAt?: number;
2483
+ } | {
2484
+ mode: "degraded";
2485
+ reason: string;
2486
+ lastSyncedAt?: number;
2487
+ };
2488
+ interface IContractManager extends Disposable {
2489
+ /**
2490
+ * Create and register a new contract.
2491
+ *
2492
+ * Implementations may validate that:
2493
+ * - A handler exists for `params.type`
2494
+ * - `params.script` matches the script derived from `params.params`
2495
+ *
2496
+ * The contract script is used as the unique identifier.
2497
+ */
2498
+ createContract(params: CreateContractParams): Promise<Contract>;
2499
+ /**
2500
+ * List contracts with optional filters.
2501
+ *
2502
+ * @example
2503
+ * ```typescript
2504
+ * const vhtlcs = await manager.getContracts({ type: "vhtlc" });
2505
+ * const active = await manager.getContracts({ state: "active" });
2506
+ * ```
2507
+ */
2508
+ getContracts(filter?: GetContractsFilter): Promise<Contract[]>;
2509
+ /**
2510
+ * List contracts and their current virtual outputs.
2511
+ *
2512
+ * If no filter is provided, returns all contracts with their virtual outputs.
2513
+ */
2514
+ getContractsWithVtxos(filter?: GetContractsFilter): Promise<ContractWithVtxos[]>;
2515
+ /**
2516
+ * Latest provider-sync health (online vs. degraded to repository data).
2517
+ * See {@link ContractSyncState}.
2518
+ */
2519
+ getSyncState(): ContractSyncState;
2520
+ /**
2521
+ * Stamp raw virtual outputs with the correct per-contract tapscripts
2522
+ * (forfeit, intent, tap tree).
2523
+ *
2122
2524
  * Resolves each vtxo's `script` to its owning contract via the contract
2123
2525
  * repository and attaches the matching tapscripts. Throws when any vtxo
2124
2526
  * references a script with no registered contract — callers are expected
@@ -2127,7 +2529,43 @@ interface IContractManager extends Disposable {
2127
2529
  * in wallet/handler code, and keeps the wallet from silently stamping the
2128
2530
  * default tapscript onto a non-default vtxo.
2129
2531
  */
2130
- annotateVtxos(vtxos: VirtualCoin[]): Promise<NormalizedExtendedVirtualCoin[]>;
2532
+ annotateVtxos(vtxos: VirtualCoin[], tapscripts?: ContractTapscriptCache): Promise<NormalizedExtendedVirtualCoin[]>;
2533
+ /**
2534
+ * Throw unless every one of `vtxos` still has an annotatable contract.
2535
+ *
2536
+ * Spending does not re-derive tapscripts — it uses the ones stored on the
2537
+ * coin — so a contract that stopped being annotatable (handler no longer
2538
+ * registered, or params its handler now rejects) still builds and submits a
2539
+ * transaction fine, and only fails afterwards, in the bookkeeping that
2540
+ * re-annotates the inputs. Calling this before submitting turns that into a
2541
+ * refusal to spend, naming the contract, rather than a broadcast whose local
2542
+ * state could not be recorded.
2543
+ */
2544
+ assertAnnotatable(vtxos: readonly {
2545
+ txid: string;
2546
+ vout: number;
2547
+ script: string;
2548
+ }[]): Promise<void>;
2549
+ /**
2550
+ * Throw when one of `vtxos` belongs to a contract that provably cannot be
2551
+ * spent right now, asking each owning handler's
2552
+ * {@link ContractHandler.assertSpendableNow}.
2553
+ *
2554
+ * The complement of {@link isContractGenericallySpendable}, which keeps
2555
+ * escrow out of generic selection and leaves explicit-input APIs open on
2556
+ * purpose. This does not close that door — it makes walking through it too
2557
+ * early report itself locally, naming the timelock, instead of coming back
2558
+ * as a protocol-level rejection after the round trip.
2559
+ *
2560
+ * Handlers answer only where they are certain, so contracts with no opinion
2561
+ * (which is all of them but VHTLC today) pass through untouched and cost
2562
+ * nothing — not even a chain-tip read.
2563
+ *
2564
+ * Optional so that adding it is not a breaking change for an embedder with
2565
+ * its own `IContractManager`. An implementation that omits it simply offers
2566
+ * no opinion, which is the same answer every non-VHTLC contract gives.
2567
+ */
2568
+ assertSpendableNow?(vtxos: readonly AssertSpendableInput[], walletPubKey?: () => Promise<string | undefined>): Promise<void>;
2131
2569
  /**
2132
2570
  * Update mutable contract fields.
2133
2571
  *
@@ -2136,13 +2574,29 @@ interface IContractManager extends Disposable {
2136
2574
  updateContract(script: string, updates: Partial<Omit<Contract, "script" | "createdAt">>): Promise<Contract>;
2137
2575
  /**
2138
2576
  * Convenience helper to update only the contract state. Note
2139
- * `inactive` does not stop watching; see {@link ContractState} and
2140
- * {@link deleteContract}.
2577
+ * `inactive` governs receive-address selection and does not stop
2578
+ * watching; see {@link ContractState} and
2579
+ * {@link setContractWatchState}.
2141
2580
  */
2142
2581
  setContractState(script: string, state: ContractState): Promise<void>;
2143
2582
  /**
2144
- * Delete a contract by script and stop watching it. This — not
2145
- * retiring via {@link setContractState} — is the stop-watching path.
2583
+ * Convenience helper to update only the contract's watch state.
2584
+ *
2585
+ * `retained` is how an owner says "this script is done": it leaves
2586
+ * the subscription and the sweep, while the row — and so history,
2587
+ * annotation and restore — is untouched. `awaiting-funds` asks for
2588
+ * coverage only until the script is funded, after which the manager
2589
+ * demotes it to `retained` itself.
2590
+ *
2591
+ * @see ContractWatchState
2592
+ */
2593
+ setContractWatchState(script: string, watch: ContractWatchState): Promise<void>;
2594
+ /**
2595
+ * Delete a contract by script, dropping both the row and the watch.
2596
+ * Destructive: the row is what keeps the contract's VTXOs
2597
+ * annotatable and its transactions readable in history, so to stop
2598
+ * watching a finished contract use
2599
+ * {@link setContractWatchState}(`"retained"`) instead.
2146
2600
  */
2147
2601
  deleteContract(script: string): Promise<void>;
2148
2602
  /**
@@ -2194,6 +2648,17 @@ interface IContractManager extends Disposable {
2194
2648
  * coalesce into a single drain.
2195
2649
  */
2196
2650
  refillLookAhead(): Promise<void>;
2651
+ /**
2652
+ * Allocate the next signing descriptor through the manager-owned HD
2653
+ * watermark path. Returns `undefined` when look-ahead/allocation is not
2654
+ * configured.
2655
+ */
2656
+ getNextSigningDescriptor(): Promise<string | undefined>;
2657
+ /**
2658
+ * Advance the HD signing descriptor watermark to `index` and refill the
2659
+ * watched look-ahead band. No-op when look-ahead/allocation is not configured.
2660
+ */
2661
+ advanceSigningDescriptorWatermark(index: number): Promise<void>;
2197
2662
  /**
2198
2663
  * Explicit, gap-limit contract discovery used by `wallet.restore()`.
2199
2664
  *
@@ -2290,6 +2755,33 @@ interface ContractManagerConfig {
2290
2755
  * {@link ContractManager.refillLookAhead}.
2291
2756
  */
2292
2757
  lookAhead?: LookAheadConfig;
2758
+ /**
2759
+ * Current chain tip height, for the `blockHeight` a {@link PathContext}
2760
+ * carries. Absent, or resolving `undefined`, leaves `blockHeight` unset.
2761
+ *
2762
+ * `isCltvSatisfied` answers `false` outright for a height-typed locktime
2763
+ * when `blockHeight` is missing, so every such path was reported
2764
+ * unspendable however mature it was. Nothing populated this before, which
2765
+ * made that the only behaviour available. Seconds-typed locktimes read
2766
+ * `currentTime` and are unaffected either way.
2767
+ *
2768
+ * Block-typed CSV is not fixed by this. `isCsvSpendable` also needs the
2769
+ * VTXO's confirmation height, and `status.block_height` is never populated
2770
+ * for a virtual coin, so it stays `false` regardless of the tip.
2771
+ *
2772
+ * Both fields matter. `height` answers height-typed timelocks; `time` (the
2773
+ * tip's timestamp, in SECONDS) is what seconds-typed ones should be judged
2774
+ * against, because the machine's clock is an estimate of chain time and a
2775
+ * drifting one reads the boundary wrong.
2776
+ *
2777
+ * Resolve `undefined` rather than rejecting when the tip cannot be read:
2778
+ * the callers treat it as "unknown", which is the pre-existing behaviour,
2779
+ * and a path query is not worth failing over a provider hiccup.
2780
+ */
2781
+ chainTip?: () => Promise<{
2782
+ height: number;
2783
+ time: number;
2784
+ } | undefined>;
2293
2785
  }
2294
2786
  /**
2295
2787
  * Wallet-injected surface backing the HD look-ahead window. Kept as a
@@ -2301,6 +2793,10 @@ interface LookAheadConfig {
2301
2793
  size: number;
2302
2794
  /** Current allocation watermark (`lastIndexUsed ?? -1`). */
2303
2795
  currentWatermark(): Promise<number>;
2796
+ /** Allocate the next signing descriptor, advancing the watermark. */
2797
+ allocate?(): Promise<string | undefined>;
2798
+ /** Advance the allocation watermark to a confirmed/restored index. */
2799
+ advanceWatermark?(index: number): Promise<void>;
2304
2800
  /** Signing descriptor at an HD index. Pure derivation. */
2305
2801
  materialize(index: number): string;
2306
2802
  /**
@@ -2309,7 +2805,10 @@ interface LookAheadConfig {
2309
2805
  * `rotateServerSigner` fans the new signer set.
2310
2806
  */
2311
2807
  candidateDeps(): CandidateDeps;
2312
- /** Fired after a speculative entry at `index` is promoted to a real row. */
2808
+ /**
2809
+ * Fired after a speculative entry at `index` is promoted to a real row.
2810
+ * @deprecated Use `advanceWatermark`; kept for external LookAheadConfig users.
2811
+ */
2313
2812
  onPromoted?(index: number): Promise<void>;
2314
2813
  }
2315
2814
  /**
@@ -2376,12 +2875,24 @@ declare class ContractManager implements IContractManager {
2376
2875
  private syncDegradedReason?;
2377
2876
  /** Epoch-ms of the last successful provider sync, if any. */
2378
2877
  private lastSyncedAt?;
2878
+ /** Last chain tip read, with the epoch-ms it was read at. @see currentChainTip */
2879
+ private chainTipCache?;
2880
+ /** In-flight chain tip read, so concurrent cache misses share one. */
2881
+ private chainTipInflight?;
2379
2882
  /** Speculative look-ahead scripts, keyed by script. @see LookAheadEntry */
2380
2883
  private lookAheadEntries;
2381
2884
  /** In-flight look-ahead drain, if any. @see scheduleLookAheadDrain */
2382
2885
  private lookAheadDrain?;
2383
2886
  /** A refill was requested while a drain was running. */
2384
2887
  private lookAheadDirty;
2888
+ /** A fire-and-forget drain failed, so the band is behind the watermark and
2889
+ * owes a retry. @see requestLookAheadDrain */
2890
+ private lookAheadRefillOwed;
2891
+ /** Set by {@link dispose}, cleared by a re-`initialize`. A drain is a
2892
+ * fire-and-forget async loop that outlives the synchronous `dispose()`,
2893
+ * so it re-checks this at every await boundary instead of running on
2894
+ * against a torn-down watcher. */
2895
+ private disposed;
2385
2896
  private constructor();
2386
2897
  /**
2387
2898
  * Static factory method for creating a new ContractManager.
@@ -2401,6 +2912,17 @@ declare class ContractManager implements IContractManager {
2401
2912
  */
2402
2913
  getSyncState(): ContractSyncState;
2403
2914
  private markSyncOnline;
2915
+ /** Contracts a sync could not annotate, as `script → reason`. */
2916
+ private annotationFailures;
2917
+ private annotationDegradedReason;
2918
+ /**
2919
+ * Fold one batch's verdict in: what it annotated clears, what it could not
2920
+ * sets. Merged rather than replaced because a batch can cover a subset of
2921
+ * the wallet's contracts (a single-contract fetch, the pending-only
2922
+ * reconcile), and those must not erase what a wider sync found. A row
2923
+ * repaired by an upgrade clears itself on the next batch that includes it.
2924
+ */
2925
+ private recordAnnotationFailures;
2404
2926
  private markSyncDegraded;
2405
2927
  private initialize;
2406
2928
  /**
@@ -2425,6 +2947,10 @@ declare class ContractManager implements IContractManager {
2425
2947
  private reconcileStaleIntents;
2426
2948
  /** @see IContractManager.refillLookAhead */
2427
2949
  refillLookAhead(): Promise<void>;
2950
+ /** @see IContractManager.getNextSigningDescriptor */
2951
+ getNextSigningDescriptor(): Promise<string | undefined>;
2952
+ /** @see IContractManager.advanceSigningDescriptorWatermark */
2953
+ advanceSigningDescriptorWatermark(index: number): Promise<void>;
2428
2954
  /**
2429
2955
  * Serialized drain of the look-ahead band: concurrent callers join the
2430
2956
  * active drain and mark it dirty, an idle call starts a new one. Promotion
@@ -2435,7 +2961,13 @@ declare class ContractManager implements IContractManager {
2435
2961
  private scheduleLookAheadDrain;
2436
2962
  /**
2437
2963
  * Request a drain without awaiting it. Used from inside a sync (promotion),
2438
- * where awaiting the drain that the sync itself is part of would deadlock.
2964
+ * and after an allocation the drain must not be able to fail the
2965
+ * watermark already moved, and a retry would burn another index.
2966
+ *
2967
+ * A failure here is not terminal: it leaves the watch band behind the
2968
+ * watermark, so funded indices inside it would go unregistered and the
2969
+ * balance would under-report for the rest of the session. Record the debt
2970
+ * so the next contract event retries it. @see handleContractEvent
2439
2971
  */
2440
2972
  private requestLookAheadDrain;
2441
2973
  /**
@@ -2468,6 +3000,7 @@ declare class ContractManager implements IContractManager {
2468
3000
  * exist. Targeted + explicitly windowed, so the global cursor stays put.
2469
3001
  */
2470
3002
  private runLookAheadCatchUp;
3003
+ private advanceLookAheadWatermark;
2471
3004
  /**
2472
3005
  * Promote every look-ahead entry funded by `vtxos` into a real repository
2473
3006
  * row, returning the persisted rows keyed by script.
@@ -2572,7 +3105,15 @@ declare class ContractManager implements IContractManager {
2572
3105
  */
2573
3106
  getContracts(filter?: GetContractsFilter): Promise<Contract[]>;
2574
3107
  getContractsWithVtxos(filter?: GetContractsFilter, pageSize?: number): Promise<ContractWithVtxos[]>;
2575
- annotateVtxos(vtxos: VirtualCoin[]): Promise<NormalizedExtendedVirtualCoin[]>;
3108
+ annotateVtxos(vtxos: VirtualCoin[], tapscripts?: ContractTapscriptCache): Promise<NormalizedExtendedVirtualCoin[]>;
3109
+ /** @inheritdoc */
3110
+ assertAnnotatable(vtxos: readonly {
3111
+ txid: string;
3112
+ vout: number;
3113
+ script: string;
3114
+ }[]): Promise<void>;
3115
+ /** @inheritdoc */
3116
+ assertSpendableNow(vtxos: readonly AssertSpendableInput[], walletPubKey?: () => Promise<string | undefined>): Promise<void>;
2576
3117
  private buildContractsDbFilter;
2577
3118
  /**
2578
3119
  * Update a contract.
@@ -2593,18 +3134,39 @@ declare class ContractManager implements IContractManager {
2593
3134
  updateContractParams(script: string, updates: Contract["params"]): Promise<Contract>;
2594
3135
  /**
2595
3136
  * Set a contract's state. Retiring (`inactive`) keeps it watched;
2596
- * see {@link ContractState}. To stop watching, use
2597
- * {@link deleteContract}.
3137
+ * see {@link ContractState}. To stop watching while keeping the row,
3138
+ * use {@link setContractWatchState}.
2598
3139
  */
2599
3140
  setContractState(script: string, state: ContractState): Promise<void>;
3141
+ /** @see IContractManager.setContractWatchState */
3142
+ setContractWatchState(script: string, watch: ContractWatchState): Promise<void>;
2600
3143
  /**
2601
- * Delete a contract. Also removes it from the watcher the only way
2602
- * to stop watching a contract (retiring it via
2603
- * {@link setContractState} does not).
3144
+ * Delete a contract, dropping the row along with the watch. To stop
3145
+ * watching a finished contract without losing its history, use
3146
+ * {@link setContractWatchState}(`"retained"`).
2604
3147
  *
2605
3148
  * @param script - Contract script
2606
3149
  */
2607
3150
  deleteContract(script: string): Promise<void>;
3151
+ /**
3152
+ * Chain tip height for a {@link PathContext}, or `undefined` when there is
3153
+ * no source configured or it cannot be read.
3154
+ *
3155
+ * Cached for {@link CHAIN_TIP_TTL_MS} so a caller resolving paths for many
3156
+ * contracts does not pay a provider round trip each time. Blocks arrive
3157
+ * ~10 minutes apart, so a cache this short can only ever be one block
3158
+ * stale, and a stale-low height is the conservative direction: a path is
3159
+ * reported unspendable slightly longer than it truly is, never spendable
3160
+ * before it is.
3161
+ */
3162
+ private currentChainTip;
3163
+ /**
3164
+ * One chain tip read, bounded by {@link CHAIN_TIP_TIMEOUT_MS}. Never
3165
+ * rejects: an unreadable tip is "unknown", which is what the callers did
3166
+ * before a tip existed at all, and a path query is not worth failing over
3167
+ * a provider hiccup.
3168
+ */
3169
+ private readChainTip;
2608
3170
  /**
2609
3171
  * Get currently spendable paths for a contract.
2610
3172
  *
@@ -2614,6 +3176,11 @@ declare class ContractManager implements IContractManager {
2614
3176
  /**
2615
3177
  * Get every currently valid spending path for a contract.
2616
3178
  *
3179
+ * No `blockHeight`: this enumerates paths "regardless of current
3180
+ * spendability", so no handler evaluates a timelock here and the tip would
3181
+ * be fetched only to be discarded — leaving a purely local answer waiting
3182
+ * on the network for nothing.
3183
+ *
2617
3184
  * @param options - Options for getting spending paths
2618
3185
  */
2619
3186
  getAllSpendingPaths(options: GetAllSpendingPathsOptions): Promise<PathSelection[]>;
@@ -2670,6 +3237,20 @@ declare class ContractManager implements IContractManager {
2670
3237
  * other contracts still need to pick up.
2671
3238
  */
2672
3239
  private syncContracts;
3240
+ /**
3241
+ * Demote every `awaiting-funds` contract in `contracts` that has been
3242
+ * funded — the automatic half of {@link ContractWatchState}.
3243
+ *
3244
+ * Runs after the sync has persisted, so the funding VTXO is saved
3245
+ * while the contract is still watched, and reads the repository
3246
+ * rather than this sync's delta: funds that landed while the app was
3247
+ * closed are outside every later window, and a contract asked to
3248
+ * watch until it is funded must still stop once it is.
3249
+ *
3250
+ * Best-effort. A demotion that fails costs coverage that is merely
3251
+ * no longer needed, and must not fail the sync that carried it.
3252
+ */
3253
+ private demoteFundedAwaitingContracts;
2673
3254
  /**
2674
3255
  * Fetch all pending (unfinalized) virtual outputs and upsert them into the
2675
3256
  * repository. This catches virtual outputs whose state changed outside the delta
@@ -2701,14 +3282,48 @@ declare class ContractManager implements IContractManager {
2701
3282
  }
2702
3283
 
2703
3284
  /**
2704
- * Contract lifecycle state. Both states stay monitored the watcher
2705
- * subscribes and sweeps every registered contract regardless
2706
- * (see {@link ContractWatcher.getWatchedContracts}), because a retired
2707
- * receive address can still be paid. `inactive` only demotes a contract
2708
- * out of receive-address selection; it does **not** unsubscribe it.
2709
- * Use {@link IContractManager.deleteContract} to stop watching.
3285
+ * Contract lifecycle state. Neither state affects coverage: the watcher
3286
+ * subscribes and sweeps a contract according to {@link Contract.watch}
3287
+ * alone, because a retired receive address can still be paid. `inactive`
3288
+ * only demotes a contract out of receive-address selection; it does
3289
+ * **not** unsubscribe it. To stop watching but keep the row, set
3290
+ * {@link ContractWatchState} to `retained`; to drop both, use
3291
+ * {@link IContractManager.deleteContract}.
2710
3292
  */
2711
3293
  type ContractState = "active" | "inactive";
3294
+ /**
3295
+ * Whether a contract is covered by background monitoring — the
3296
+ * subscription and the failsafe/indexer sweep
3297
+ * ({@link ContractWatcher.getWatchedContracts}).
3298
+ *
3299
+ * Orthogonal to {@link ContractState}, which governs receive-address
3300
+ * selection only. A contract can be the wallet's display address and
3301
+ * watched, or terminal and retained; the two questions never answer each
3302
+ * other.
3303
+ *
3304
+ * NArk calls this `ContractActivityState` (`Active` / `Inactive` /
3305
+ * `AwaitingFundsBeforeDeactivate`). The concept is the same; the names
3306
+ * differ because TS already spends `active`/`inactive` on
3307
+ * {@link ContractState}, and a row reading `state: "active",
3308
+ * activityState: "inactive"` would be unreadable.
3309
+ */
3310
+ type ContractWatchState =
3311
+ /** Subscribed and polled. */
3312
+ "watched"
3313
+ /**
3314
+ * Watched until the first VTXO lands at the script, then
3315
+ * automatically demoted to `retained` by the contract manager.
3316
+ * For one-shot destinations — a refund address, a swap lockup —
3317
+ * that only need coverage until they are funded.
3318
+ */
3319
+ | "awaiting-funds"
3320
+ /**
3321
+ * Kept for history, restore and classification, but absent from
3322
+ * every background channel. The row still resolves in
3323
+ * `getContracts`, still annotates its VTXOs, and still feeds
3324
+ * transaction history; nothing subscribes or polls it.
3325
+ */
3326
+ | "retained";
2712
3327
  /**
2713
3328
  * Represents a contract that can receive and manage virtual outputs.
2714
3329
  *
@@ -2759,6 +3374,11 @@ interface Contract {
2759
3374
  address: string;
2760
3375
  /** Current state of the contract. */
2761
3376
  state: ContractState;
3377
+ /**
3378
+ * Background-monitoring scope. Absent means `watched`.
3379
+ * @see ContractWatchState
3380
+ */
3381
+ watch?: ContractWatchState;
2762
3382
  /** Unix timestamp in milliseconds when this contract was created. */
2763
3383
  createdAt: number;
2764
3384
  /**
@@ -2833,6 +3453,17 @@ interface PathContext {
2833
3453
  * fallback — against the contract's sender/receiver params.
2834
3454
  */
2835
3455
  role?: string;
3456
+ /**
3457
+ * Chain tip timestamp in SECONDS, when known.
3458
+ *
3459
+ * Timelocks mature against chain time, not the machine's clock, so any
3460
+ * seconds-typed comparison should prefer this and fall back to
3461
+ * {@link currentTime} only when it is absent. The two differ by more than
3462
+ * pedantry: the server matures absolute locktimes against median-time-past,
3463
+ * which trails wall clock, and a host whose clock drifts turns a local
3464
+ * decision into a wrong one in whichever direction it drifted.
3465
+ */
3466
+ chainTime?: number;
2836
3467
  /** The specific virtual output being evaluated. */
2837
3468
  vtxo?: VirtualCoin;
2838
3469
  }
@@ -2904,6 +3535,50 @@ interface ContractHandler<P = Record<string, unknown>, S extends VtxoScript = Vt
2904
3535
  * Returns empty array if no paths are available.
2905
3536
  */
2906
3537
  getSpendablePaths(script: S, contract: Contract, context: PathContext): PathSelection[];
3538
+ /**
3539
+ * Whether this contract's VTXOs may be picked by *generic* wallet spending —
3540
+ * send, settle, renewal, asset operations, offboard, `available` balance.
3541
+ * Explicit-input APIs (`settle({ inputs })`, `sendBitcoin({ selectedVtxos })`,
3542
+ * …) stay open regardless: naming an outpoint is the intent this gate protects.
3543
+ *
3544
+ * Pure, synchronous and offline — it runs inside the service worker, so no
3545
+ * chain tip, no network, no live plugin object. Absent or `false` ⇒ NOT
3546
+ * spendable: a type core cannot reason about must not leak by omission.
3547
+ *
3548
+ * No `script` parameter: deriving it costs a taproot tree per contract on a
3549
+ * read path (#521) and no shipped handler needs it. A handler that does can
3550
+ * call its own `createScript(contract.params)`.
3551
+ */
3552
+ isGenericallySpendable?(contract: Contract): boolean;
3553
+ /**
3554
+ * Refuse a spend this contract definitively cannot make right now, with a
3555
+ * reason the caller can act on. Called before anything is signed or
3556
+ * submitted, for inputs the caller named explicitly.
3557
+ *
3558
+ * This is the counterpart to {@link isGenericallySpendable}, not a
3559
+ * duplicate of it. That gate keeps escrow out of GENERIC selection and
3560
+ * deliberately leaves explicit-input APIs open, because naming an outpoint
3561
+ * is the intent it protects. Naming one too early is still a mistake
3562
+ * though, and without this it is a mistake the server reports — as a
3563
+ * protocol-level rejection, after the round trip, in terms that do not name
3564
+ * the timelock that was not yet mature.
3565
+ *
3566
+ * **Throw only on a definite no.** Absent, silent, or unsure all mean "no
3567
+ * opinion" and the spend proceeds. A handler must not refuse merely because
3568
+ * it found no path: `getSpendablePaths` legitimately returns empty for
3569
+ * spendable contracts — `arkade`'s skips every covenant leaf, so a program
3570
+ * spendable only through its emulator-signed leaf reports nothing — and an
3571
+ * unreadable timelock (height-typed with no chain tip) is unknown, not
3572
+ * immature. @see cltvMaturity, which keeps those apart.
3573
+ *
3574
+ * Returning a promise is allowed so a handler needing I/O is not forced to
3575
+ * throw synchronously — callers await the result. Prefer synchronous where
3576
+ * possible: this runs on the path between a caller's decision to spend and
3577
+ * the spend itself.
3578
+ *
3579
+ * @throws Error when the contract provably cannot be spent at `context`
3580
+ */
3581
+ assertSpendableNow?(script: S, contract: Contract, context: PathContext): void | Promise<void>;
2907
3582
  }
2908
3583
  /**
2909
3584
  * What a {@link Discoverable.discoverAt} call returns — exactly the
@@ -3183,6 +3858,8 @@ declare class ContractWatcher {
3183
3858
  /** See {@link withCoalescedSubscription}. */
3184
3859
  private subscriptionBatchDepth;
3185
3860
  private subscriptionUpdateDeferred;
3861
+ /** See {@link reportEventSourceUnavailable} — said once, not per attempt. */
3862
+ private eventSourceReported;
3186
3863
  /**
3187
3864
  * Create a contract watcher with the given providers and polling settings.
3188
3865
  *
@@ -3194,7 +3871,8 @@ declare class ContractWatcher {
3194
3871
  * Add a contract to be watched.
3195
3872
  *
3196
3873
  * Once watching, every contract is subscribed and polled whatever
3197
- * its state.
3874
+ * its {@link ContractState} — a `retained` one is held for reads
3875
+ * only, and never enters a background channel.
3198
3876
  *
3199
3877
  * @see getWatchedContracts
3200
3878
  */
@@ -3220,15 +3898,22 @@ declare class ContractWatcher {
3220
3898
  */
3221
3899
  getAllContracts(): Contract[];
3222
3900
  /**
3223
- * Every registered contract, retired (`inactive`) ones included.
3901
+ * Every registered contract except the `retained` ones, retired
3902
+ * (`inactive`) receive addresses included.
3224
3903
  *
3225
3904
  * Feeds both the subscription and the indexer sweep scope, so
3226
3905
  * narrowing it drops a contract from every background channel at
3227
- * once. Nothing may be narrowed out: an Ark receive address can be
3906
+ * once. `state` may never narrow it: an Ark receive address can be
3228
3907
  * paid again after the wallet has rotated past it, and a payment
3229
3908
  * that lands outside every background channel is invisible until
3230
3909
  * some foreground read happens to sweep it. Retirement therefore
3231
3910
  * governs receive-address selection, not coverage.
3911
+ *
3912
+ * {@link ContractWatchState} is the one thing that does narrow it,
3913
+ * and only when an owner has explicitly said the script is done —
3914
+ * a settled swap lockup, a funded one-shot destination. The row
3915
+ * stays in {@link getAllContracts} so reads, annotation and history
3916
+ * are unaffected.
3232
3917
  */
3233
3918
  getWatchedContracts(): Contract[];
3234
3919
  /**
@@ -3265,400 +3950,82 @@ declare class ContractWatcher {
3265
3950
  */
3266
3951
  private connect;
3267
3952
  /**
3268
- * Schedule a reconnection attempt.
3269
- */
3270
- private scheduleReconnect;
3271
- /**
3272
- * Start the failsafe polling interval.
3273
- */
3274
- private startFailsafePolling;
3275
- private pollAllContracts;
3276
- /**
3277
- * Poll specific contracts and emit events for changes.
3278
- */
3279
- private pollContracts;
3280
- /**
3281
- * Run `fn` with subscription updates coalesced into a single
3282
- * `subscribeForScripts` on the way out.
3283
- *
3284
- * {@link addContract} re-subscribes eagerly (the watcher may already be
3285
- * running), and every subscribe posts the *whole* accumulated script list —
3286
- * so a restore scan that discovers N contracts sends N growing POSTs,
3287
- * quadratic in script-slots. Inside this scope those updates are only
3288
- * marked dirty, flushed once on the way out (success and error path alike).
3289
- *
3290
- * A contract added inside the scope is therefore not streaming until the
3291
- * flush. Nothing in the watcher closes that window — the failsafe poll
3292
- * replays repository state and cannot see VTXOs no one has fetched yet. The
3293
- * one caller, `scanContracts`, is covered because `Wallet.restore` follows
3294
- * it with a bulk `refreshVtxos`. A new caller must provide its own
3295
- * equivalent catch-up, or keep the scope short enough not to need one.
3296
- */
3297
- withCoalescedSubscription<T>(fn: () => Promise<T>): Promise<T>;
3298
- private tryUpdateSubscription;
3299
- /**
3300
- * Update the subscription with scripts that should be watched.
3301
- *
3302
- * @see getWatchedContracts
3303
- */
3304
- private updateSubscription;
3305
- /**
3306
- * Main listening loop for subscription events.
3307
- */
3308
- private listenLoop;
3309
- /**
3310
- * Handle a subscription update.
3311
- *
3312
- * Normalization boundary: `getSubscription` is part of the public `IndexerProvider` interface,
3313
- * so a consumer implementation may yield legacy-shaped VTXOs. Normalizing on ingest also fixes
3314
- * the shape of the payloads emitted to external event consumers.
3315
- */
3316
- private handleSubscriptionUpdate;
3317
- /**
3318
- * Process virtual outputs from subscription and route each VTXO to the
3319
- * single contract that actually locks it via `vtxo.script`. If the script
3320
- * doesn't match any watched contract, skip the VTXO rather than fan it
3321
- * out to every matching contract — fan-out produced phantom state in
3322
- * non-owning contracts that then never reconciled.
3323
- */
3324
- private processSubscriptionVtxos;
3325
- /**
3326
- * Emit a virtual output event for a contract.
3327
- */
3328
- private emitVtxoEvent;
3329
- }
3330
-
3331
- /**
3332
- * Intent proof implementation for Bitcoin message signing.
3333
- *
3334
- * Intent proof defines a standard for signing Bitcoin messages as well as proving
3335
- * ownership of outputs.
3336
- *
3337
- * This namespace provides utilities for creating and validating Intent proof.
3338
- *
3339
- * It is greatly inspired by BIP322.
3340
- * @see https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki
3341
- *
3342
- * @example
3343
- * ```typescript
3344
- * // Create a Intent proof
3345
- * const proof = Intent.create(
3346
- * "Hello Bitcoin!",
3347
- * [input],
3348
- * [output]
3349
- * );
3350
- *
3351
- * // Sign the proof
3352
- * const signedProof = await identity.sign(proof);
3353
- *
3354
- */
3355
- declare namespace Intent {
3356
- type Proof = Transaction;
3357
- /**
3358
- * Creates a new Intent proof unsigned transaction.
3359
- *
3360
- * This function constructs a special transaction that can be signed to prove
3361
- * ownership of onchain and virtual outputs. The proof includes the message to be
3362
- * signed and the inputs/outputs that demonstrate ownership.
3363
- *
3364
- * @param message - The Intent message to be signed, either raw string of Message object
3365
- * @param ins - Array of transaction inputs to prove ownership of
3366
- * @param outputs - Optional array of transaction outputs
3367
- * @returns An unsigned Intent proof transaction
3368
- */
3369
- function create(message: string | Message, ins: (TransactionInput | ExtendedCoin)[], outputs?: TransactionOutput[]): Proof;
3370
- /**
3371
- * Compute the fee paid by an intent proof transaction.
3372
- *
3373
- * @param proof - Intent proof transaction
3374
- * @returns The fee in satoshis
3375
- */
3376
- function fee(proof: Proof): number;
3377
- type RegisterMessage = {
3378
- type: "register";
3379
- onchain_output_indexes: number[];
3380
- valid_at: number;
3381
- expire_at: number;
3382
- cosigners_public_keys: string[];
3383
- };
3384
- type DeleteMessage = {
3385
- type: "delete";
3386
- expire_at: number;
3387
- };
3388
- type GetPendingTxMessage = {
3389
- type: "get-pending-tx";
3390
- expire_at: number;
3391
- };
3392
- type Message = RegisterMessage | DeleteMessage | GetPendingTxMessage;
3393
- /**
3394
- * Serialize an intent message to the canonical JSON string used for signing.
3395
- *
3396
- * @param message - Intent message payload
3397
- * @returns Canonical string form of the message
3398
- */
3399
- function encodeMessage(message: Message): string;
3400
- }
3401
-
3402
- /**
3403
- * Delegate identity and fee information returned by `getDelegateInfo`.
3404
- */
3405
- interface DelegateInfo {
3406
- /** Delegate public key. */
3407
- pubkey: string;
3408
- /** Delegate fee amount or expression returned by the delegate. */
3409
- fee: string;
3410
- /** Address for delegate fee collection. Sourced from `delegatorAddress` in Fulmine response, for now. */
3411
- delegateAddress: string;
3412
- /** @deprecated alias for @see DelegateInfo.delegateAddress */
3413
- delegatorAddress?: string;
3414
- }
3415
- /**
3416
- * Optional delegate behavior flags.
3417
- */
3418
- interface DelegateOptions {
3419
- /**
3420
- * Instruct the delegate not to replace an existing delegation
3421
- * (meaning a signed register intent and its forfeit transactions)
3422
- * that already includes at least one virtual output from this request.
3423
- *
3424
- * @defaultValue `false`
3425
- */
3426
- rejectReplace?: boolean;
3427
- }
3428
- /**
3429
- * Provider interface for remote delegation service.
3430
- */
3431
- interface DelegateProvider {
3432
- /**
3433
- * Request delegation for a signed register intent and its forfeit transactions.
3434
- *
3435
- * @param intent - Signed register intent to delegate
3436
- * @param forfeitTxs - Forfeit transactions associated with the delegation request
3437
- * @param options - Optional delegate behavior flags
3438
- */
3439
- delegate(intent: SignedIntent<Intent.RegisterMessage>, forfeitTxs: string[], options?: DelegateOptions): Promise<void>;
3440
- /**
3441
- * Fetch delegate metadata such as pubkey, fee, and delegate address.
3953
+ * Handle "this environment has no `EventSource`": say so once, loudly and
3954
+ * actionably, and answer whether the caller should skip reconnecting.
3442
3955
  *
3443
- * @returns Delegate identity and fee information
3956
+ * Reconnecting is pointless here a missing global is not a dropped
3957
+ * connection, and the default backoff (unlimited attempts, capped at 5s)
3958
+ * would otherwise retry it forever, logging each failure and firing a
3959
+ * `connection_reset` every few seconds for the life of the wallet. Not even
3960
+ * one goes out: subscribers read that event as "the stream dropped, resync
3961
+ * and expect it back", and here it never opened and never will.
3962
+ * Failsafe polling keeps running, so the watcher stays correct and merely
3963
+ * slower; what it loses is push latency.
3444
3964
  */
3445
- getDelegateInfo(): Promise<DelegateInfo>;
3446
- }
3447
- /** @deprecated alias for @see DelegateProvider */
3448
- type DelegatorProvider = DelegateProvider;
3449
- /**
3450
- * REST-based delegate provider implementation.
3451
- * @example
3452
- * ```typescript
3453
- * const provider = new RestDelegateProvider('https://delegate.example.com');
3454
- * const info = await provider.getDelegateInfo();
3455
- * await provider.delegate(intent, forfeitTxs);
3456
- * ```
3457
- */
3458
- declare class RestDelegateProvider implements DelegateProvider {
3459
- url: string;
3965
+ private reportEventSourceUnavailable;
3460
3966
  /**
3461
- * Create a REST delegate provider targeting the given base URL.
3462
- *
3463
- * @param url - Base URL of the remote delegation service.
3967
+ * Schedule a reconnection attempt.
3464
3968
  */
3465
- constructor(url: string);
3969
+ private scheduleReconnect;
3466
3970
  /**
3467
- * Submit a delegation request to the remote delegation service.
3468
- *
3469
- * @param intent - Signed register intent to delegate
3470
- * @param forfeitTxs - Forfeit transactions associated with the delegation request
3471
- * @param options - Optional delegate behavior flags
3472
- * @throws Error if the remote service rejects the request
3971
+ * Start the failsafe polling interval.
3473
3972
  */
3474
- delegate(intent: SignedIntent<Intent.RegisterMessage>, forfeitTxs: string[], options?: DelegateOptions): Promise<void>;
3973
+ private startFailsafePolling;
3974
+ private pollAllContracts;
3475
3975
  /**
3476
- * Fetch delegate metadata exposed by the remote delegation service.
3477
- *
3478
- * @returns Delegate identity and fee information
3479
- * @throws Error if the remote service returns invalid data
3976
+ * Poll specific contracts and emit events for changes.
3480
3977
  */
3481
- getDelegateInfo(): Promise<DelegateInfo>;
3482
- }
3483
- /** @deprecated alias for @see RestDelegateProvider */
3484
- declare const RestDelegatorProvider: typeof RestDelegateProvider;
3485
- type RestDelegatorProvider = RestDelegateProvider;
3486
-
3487
- interface IDelegateManager {
3978
+ private pollContracts;
3488
3979
  /**
3489
- * Delegate virtual outputs to the remote delegation service.
3980
+ * Run `fn` with subscription updates coalesced into a single
3981
+ * `subscribeForScripts` on the way out.
3490
3982
  *
3491
- * Vtxos that are not locked to a delegate-type contract (no tap leaf
3492
- * matches the delegate's pubkey) are filtered out silently, since they
3493
- * cannot be co-signed by the delegate.
3983
+ * {@link addContract} re-subscribes eagerly (the watcher may already be
3984
+ * running), and every subscribe posts the *whole* accumulated script list —
3985
+ * so a restore scan that discovers N contracts sends N growing POSTs,
3986
+ * quadratic in script-slots. Inside this scope those updates are only
3987
+ * marked dirty, flushed once on the way out (success and error path alike).
3494
3988
  *
3495
- * @param vtxos - Virtual outputs to delegate
3496
- * @param destination - Arkade address that should receive renewed funds
3497
- * @param delegateAt - Optional timestamp to force a specific delegation time
3498
- * @returns Successfully delegated and failed outpoint groups
3989
+ * A contract added inside the scope is therefore not streaming until the
3990
+ * flush. Nothing in the watcher closes that window the failsafe poll
3991
+ * replays repository state and cannot see VTXOs no one has fetched yet. The
3992
+ * one caller, `scanContracts`, is covered because `Wallet.restore` follows
3993
+ * it with a bulk `refreshVtxos`. A new caller must provide its own
3994
+ * equivalent catch-up, or keep the scope short enough not to need one.
3499
3995
  */
3500
- delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
3501
- delegated: Outpoint[];
3502
- failed: {
3503
- outpoints: Outpoint[];
3504
- error: unknown;
3505
- }[];
3506
- }>;
3507
- /** Fetch delegate metadata such as pubkey, fee, and delegate address. */
3508
- getDelegateInfo(): Promise<DelegateInfo>;
3509
- }
3510
- /** @deprecated alias for @see IDelegateManager */
3511
- type IDelegatorManager = IDelegateManager;
3512
- declare class DelegateManagerImpl implements IDelegateManager {
3513
- readonly delegateProvider: DelegateProvider;
3514
- readonly arkInfoProvider: Pick<ArkProvider, "getInfo">;
3515
- readonly identity: Identity;
3516
- /** Create a delegate manager from the configured provider, Arkade info source, and wallet identity. */
3517
- constructor(delegateProvider: DelegateProvider, arkInfoProvider: Pick<ArkProvider, "getInfo">, identity: Identity);
3518
- getDelegateInfo(): Promise<DelegateInfo>;
3519
- delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
3520
- delegated: Outpoint[];
3521
- failed: {
3522
- outpoints: Outpoint[];
3523
- error: unknown;
3524
- }[];
3525
- }>;
3526
- }
3527
- /** @deprecated alias for @see DelegateManagerImpl */
3528
- declare const DelegatorManagerImpl: typeof DelegateManagerImpl;
3529
- type DelegatorManagerImpl = DelegateManagerImpl;
3530
-
3531
- /** One transaction's participation in one logical action. */
3532
- interface GroupMembership {
3996
+ withCoalescedSubscription<T>(fn: () => Promise<T>): Promise<T>;
3997
+ private tryUpdateSubscription;
3533
3998
  /**
3534
- * Stable id of the action; txs sharing it group together. Third-party
3535
- * resolvers should namespace it (`"vendor:thing"`) to avoid colliding with
3536
- * other resolvers' groups. SDK built-ins use namespaced ids such as `boarding:`.
3537
- * A membership with an empty groupId is dropped.
3999
+ * Update the subscription with scripts that should be watched.
4000
+ *
4001
+ * @see getWatchedContracts
3538
4002
  */
3539
- groupId: string;
3540
- /** Human label for the action, e.g. "Dice game". */
3541
- label?: string;
3542
- /** App category for icon/filtering, e.g. "game". */
3543
- kind?: string;
4003
+ private updateSubscription;
3544
4004
  /**
3545
- * Free-form row data. Same-group metadata is shallow-merged with
3546
- * earlier-resolver keys winning.
4005
+ * Main listening loop for subscription events.
3547
4006
  */
3548
- metadata?: Record<string, unknown>;
4007
+ private listenLoop;
3549
4008
  /**
3550
- * This tx's unsigned sat contribution to this group. Defaults to the tx's
3551
- * full amount; the builder applies direction. Use it to split a batched tx
3552
- * across groups. Same-key receive rows paired with a sent row are treated
3553
- * as change and excluded from `Activity.amount`. A membership with a
3554
- * non-finite amount (NaN/Infinity) is dropped.
4009
+ * Handle a subscription update.
4010
+ *
4011
+ * Normalization boundary: `getSubscription` is part of the public `IndexerProvider` interface,
4012
+ * so a consumer implementation may yield legacy-shaped VTXOs. Normalizing on ingest also fixes
4013
+ * the shape of the payloads emitted to external event consumers.
3555
4014
  */
3556
- amount?: number;
3557
- }
3558
- /** A pluggable resolver keyed by `id`. */
3559
- interface ActivityResolver {
4015
+ private handleSubscriptionUpdate;
3560
4016
  /**
3561
- * Registry key override or remove by it. Namespace it (`"vendor:games"`)
3562
- * so independent libraries don't clobber each other; `use()` overwrites
3563
- * silently on a duplicate id.
4017
+ * Process virtual outputs from subscription and route each VTXO to the
4018
+ * single contract that actually locks it via `vtxo.script`. If the script
4019
+ * doesn't match any watched contract, skip the VTXO rather than fan it
4020
+ * out to every matching contract — fan-out produced phantom state in
4021
+ * non-owning contracts that then never reconciled.
3564
4022
  */
3565
- id: string;
4023
+ private processSubscriptionVtxos;
3566
4024
  /**
3567
- * Load correlation data before `resolve` runs. If it rejects, this resolver
3568
- * contributes no memberships.
4025
+ * Emit a virtual output event for a contract.
3569
4026
  */
3570
- prepare?(): Promise<void>;
3571
- /** Pure and synchronous. The groups this tx belongs to, or undefined to leave it plain. */
3572
- resolve(tx: ArkTransaction): GroupMembership[] | undefined;
3573
- }
3574
- /** The non-id, non-amount part of a {@link GroupMembership}. */
3575
- interface ActivityIntent {
3576
- /** Human label for the action, e.g. "Dice game". */
3577
- label?: string;
3578
- /** App category for icon/filtering, e.g. "game". */
3579
- kind?: string;
3580
- /** Free-form row data, shallow-merged across the group's resolvers (first-writer-wins). */
3581
- metadata?: Record<string, unknown>;
3582
- }
3583
- /** One logical activity. */
3584
- interface Activity {
3585
- /** The groupId, or the natural tx key for untagged rows. */
3586
- id: string;
3587
- /** Merged intent for the group, if any resolver tagged it. */
3588
- intent?: ActivityIntent;
3589
- /** Member txs, oldest-first. */
3590
- txs: ArkTransaction[];
3591
- /** Signed net sats: positive received, negative sent; same-key change rows are excluded. */
3592
- amount: number;
3593
- /** Earliest member createdAt (ms since epoch). */
3594
- createdAt: number;
3595
- /** True once every member tx is settled. */
3596
- settled: boolean;
3597
- }
3598
- /** Resolver registry keyed by id. */
3599
- declare class ActivityRegistry {
3600
- private readonly resolvers;
3601
- /** Add a resolver, or override an existing one with the same id (kept in place). */
3602
- use(resolver: ActivityResolver): void;
3603
- /** Remove a resolver (built-in or custom) by id. */
3604
- remove(id: string): void;
3605
- /** The registered resolver ids, in registration order. */
3606
- list(): string[];
3607
- /** All registered resolvers, in registration (priority) order. */
3608
- all(): ActivityResolver[];
3609
- }
3610
- /** Built-in resolver: labels on-chain boarding (deposit) transactions. */
3611
- declare function boardingResolver(): ActivityResolver;
3612
- /** Built-in resolver: labels collaborative exits (VTXOs forfeited to chain in a batch). */
3613
- declare function collabExitResolver(): ActivityResolver;
3614
- /**
3615
- * Built-in resolver: labels the genesis transaction of a minted asset — "Asset
3616
- * mint" on the issuer's sent tx, "Asset receive" when the fresh supply arrives
3617
- * in the genesis tx itself. An asset id encodes its genesis txid; reissues and
3618
- * transfers carry the asset under a different `arkTxid`, so they are left plain.
3619
- *
3620
- * `metadata.amount` is the decimal string of the asset's `bigint` amount, kept
3621
- * as a string so large supplies survive JSON round-trips without truncation.
3622
- * Recover the value with `BigInt(metadata.amount as string)` — using it
3623
- * directly in arithmetic coerces (`"10" + 1` is `"101"`, not `11`) and loses
3624
- * precision past `Number.MAX_SAFE_INTEGER`.
3625
- */
3626
- declare function assetMintResolver(): ActivityResolver;
3627
- /**
3628
- * A registry pre-populated with the SDK's built-in resolvers: `boarding`,
3629
- * `collab-exit`, and `asset-mint`.
3630
- */
3631
- declare function createDefaultActivityRegistry(): ActivityRegistry;
3632
-
3633
- /**
3634
- * A source of unilateral-exit chain data for a set of VTXOs. Sources are tried
3635
- * in order by the resolver; a source returns `null` (chain) or omits keys (psbts)
3636
- * for data it cannot supply — a "miss" — and the resolver falls through.
3637
- */
3638
- interface ExitDataSource {
3639
- readonly name: string;
3640
- /** Full ancestry chain for a vtxo (all pages merged), or null on a miss. */
3641
- getVtxoChain(vtxo: Outpoint): Promise<ChainTx[] | null>;
3642
- /** Base64 PSBTs this source has, keyed by (unsigned) txid. Absent key = miss. */
3643
- getVirtualTxs(txids: string[]): Promise<Map<string, string>>;
3644
- }
3645
- /** Reads exit chain data through an ordered chain of sources. */
3646
- interface ExitChainResolver {
3647
- getVtxoChain(vtxo: Outpoint): Promise<ChainTx[]>;
3648
- getVirtualTxs(txids: string[]): Promise<string[]>;
4027
+ private emitVtxoEvent;
3649
4028
  }
3650
- /**
3651
- * Assemble the standard exit-data resolver: local repo (if configured) → any
3652
- * extra sources (e.g. a future provider) → indexer. Read-through persists to the
3653
- * repository. With no repository this is exactly the indexer path (a no-op seam).
3654
- */
3655
- declare function createExitChainResolver(params: {
3656
- indexer: IndexerProvider;
3657
- repository?: VirtualTxRepository;
3658
- extraSources?: ExitDataSource[];
3659
- }): ExitChainResolver;
3660
-
3661
- type ExitCaptureMode = "lite" | "full";
3662
4029
 
3663
4030
  /**
3664
4031
  * Wallet receive-address strategy.
@@ -3969,8 +4336,15 @@ interface WalletBalance {
3969
4336
  pendingRecovery: number;
3970
4337
  /** Total balance across offchain, recoverable, pending-recovery, and boarding funds. */
3971
4338
  total: number;
3972
- /** Asset balance entries (`assetId` & `amount`) */
4339
+ /** Asset balance entries (`assetId` & `amount`) the wallet owns. */
3973
4340
  assets: Asset[];
4341
+ /**
4342
+ * The subset of {@link assets} generic spending will accept, i.e. the asset
4343
+ * analogue of {@link available}. Assets have no owned/spendable split of
4344
+ * their own, so `assets - availableAssets` is what is held but not
4345
+ * selectable — escrowed, intent-locked or awaiting recovery.
4346
+ */
4347
+ availableAssets: Asset[];
3974
4348
  }
3975
4349
  /**
3976
4350
  * Parameters accepted by `OnchainWallet.send`.
@@ -3993,7 +4367,13 @@ interface SendBitcoinParams {
3993
4367
  * @deprecated Does not appear to have ever been used.
3994
4368
  */
3995
4369
  memo?: string;
3996
- /** Optional explicit virtual output selection used by `Wallet.sendBitcoin`. */
4370
+ /**
4371
+ * Optional explicit virtual output selection used by `Wallet.sendBitcoin`.
4372
+ * Ungated, like `settle({ inputs })`: whatever is named here is spent, even
4373
+ * if generic selection would skip it.
4374
+ *
4375
+ * @see IReadonlyWallet.getSpendableVtxos
4376
+ */
3997
4377
  selectedVtxos?: ExtendedVirtualCoin[];
3998
4378
  }
3999
4379
  /**
@@ -4522,6 +4902,20 @@ interface IReadonlyWallet {
4522
4902
  * @see GetVtxosFilter
4523
4903
  */
4524
4904
  getVtxos(filter?: GetVtxosFilter): Promise<NormalizedExtendedVirtualCoin[]>;
4905
+ /**
4906
+ * The subset of {@link getVtxos} that generic spending may select: the same
4907
+ * filter, minus contracts the generic-spending gate closes, minus funds
4908
+ * awaiting recovery under a past-cutoff signer, minus outpoints locked by an
4909
+ * in-flight intent. Every implicit coin selection in the SDK reads this;
4910
+ * `getVtxos` stays the raw reporting/recovery read.
4911
+ *
4912
+ * Both exclusion sets are derived from one contract snapshot, so they cannot
4913
+ * disagree about which VTXOs exist.
4914
+ *
4915
+ * @param filter - Same flags, same defaults, as {@link getVtxos}
4916
+ * @see GetVtxosFilter
4917
+ */
4918
+ getSpendableVtxos(filter?: GetVtxosFilter): Promise<NormalizedExtendedVirtualCoin[]>;
4525
4919
  /** @returns Onchain boarding inputs tracked by the wallet. */
4526
4920
  getBoardingUtxos(): Promise<ExtendedCoin[]>;
4527
4921
  /** @returns Wallet transaction history derived from boarding and Arkade activity. */
@@ -4546,6 +4940,94 @@ interface IReadonlyWallet {
4546
4940
  clear(): Promise<void>;
4547
4941
  }
4548
4942
 
4943
+ /**
4944
+ * Where the SDK gets its `EventSource`.
4945
+ *
4946
+ * Every server-sent-events stream this SDK opens — settlement events, the tx
4947
+ * feed, the indexer script subscription — needs one, and until now each site
4948
+ * reached for the global. That works in browsers and, via
4949
+ * {@link ExpoArkProvider}/{@link ExpoIndexerProvider}, in React Native. It does
4950
+ * NOT work in Node, which exposes `EventSource` only behind
4951
+ * `--experimental-eventsource` (24.x) — so a CLI, a server-side wallet or a
4952
+ * background worker got a `ReferenceError` out of the stream and everything
4953
+ * event-driven degraded to whatever polling happened to be running.
4954
+ *
4955
+ * Resolution order, per call: an explicit per-provider factory, then whatever
4956
+ * {@link configureEventSource} was given, then the global. When none answers,
4957
+ * {@link resolveEventSource} throws {@link EventSourceUnavailableError} rather
4958
+ * than a bare `ReferenceError`, so callers can tell "this environment has no
4959
+ * SSE" from "the connection dropped" — a distinction that matters, because the
4960
+ * first is not worth reconnecting for and the second is.
4961
+ */
4962
+ /**
4963
+ * The slice of `EventSource` this SDK actually uses.
4964
+ *
4965
+ * Structural rather than the DOM type on purpose: Node's `eventsource` package
4966
+ * and the React Native polyfills are not DOM `EventSource`s, and demanding one
4967
+ * made every consumer launder a perfectly capable object through
4968
+ * `as unknown as EventSource` — a cast that hides real mismatches as readily as
4969
+ * it waves through this one.
4970
+ */
4971
+ interface EventSourceLike {
4972
+ addEventListener(type: "message" | "error", listener: (event: MessageEvent) => void): void;
4973
+ removeEventListener(type: "message" | "error", listener: (event: MessageEvent) => void): void;
4974
+ close(): void;
4975
+ }
4976
+ /** Opens an SSE connection to `url`. `new EventSource(url)`, as a value. */
4977
+ type EventSourceFactory = (url: string) => EventSourceLike;
4978
+ /** Options shared by every provider that opens an SSE stream. */
4979
+ interface EventSourceCapable {
4980
+ /**
4981
+ * Where this provider gets its `EventSource`, overriding
4982
+ * {@link configureEventSource} and the global. Use it when one process
4983
+ * needs different transports per connection; otherwise configure once.
4984
+ */
4985
+ eventSource?: EventSourceFactory;
4986
+ }
4987
+ /**
4988
+ * No `EventSource` could be resolved, so no SSE stream can be opened.
4989
+ *
4990
+ * A property of the environment, not of the connection: retrying cannot fix it,
4991
+ * which is why {@link ContractWatcher} reports it once and stops reconnecting
4992
+ * instead of looping on it.
4993
+ */
4994
+ declare class EventSourceUnavailableError extends Error {
4995
+ constructor();
4996
+ }
4997
+ /**
4998
+ * Type guard for {@link EventSourceUnavailableError}.
4999
+ *
5000
+ * Falls back to the `name` because a custom error crossing the service-worker
5001
+ * `postMessage` boundary arrives as a plain `Error` — the same reason
5002
+ * `ProviderUnavailableError` keeps its state in the message.
5003
+ */
5004
+ declare function isEventSourceUnavailableError(error: unknown): error is Error;
5005
+ /**
5006
+ * Set the `EventSource` every provider uses by default. Call once at startup,
5007
+ * before opening a wallet; pass `undefined` to go back to the global.
5008
+ *
5009
+ * This exists because the provider-level option cannot reach providers the SDK
5010
+ * builds for you — `Wallet.create({ arkServerUrl })` constructs both itself.
5011
+ *
5012
+ * @example
5013
+ * ```typescript
5014
+ * import { EventSource } from "eventsource";
5015
+ * configureEventSource((url) => new EventSource(url));
5016
+ * ```
5017
+ */
5018
+ declare function configureEventSource(factory?: EventSourceFactory): void;
5019
+ /** What {@link configureEventSource} last set, if anything. */
5020
+ declare function getConfiguredEventSource(): EventSourceFactory | undefined;
5021
+ /**
5022
+ * Resolve the factory to open a stream with, or throw
5023
+ * {@link EventSourceUnavailableError}.
5024
+ *
5025
+ * The global is read on every call rather than captured at module load: a test
5026
+ * (or a polyfill) that assigns `globalThis.EventSource` after import must still
5027
+ * be seen.
5028
+ */
5029
+ declare function resolveEventSource(override?: EventSourceFactory): EventSourceFactory;
5030
+
4549
5031
  type PaginationOptions = {
4550
5032
  pageIndex?: number;
4551
5033
  pageSize?: number;
@@ -4813,7 +5295,9 @@ interface IndexerProvider {
4813
5295
  */
4814
5296
  declare class RestIndexerProvider implements IndexerProvider {
4815
5297
  serverUrl: string;
4816
- constructor(serverUrl?: string);
5298
+ /** Overrides {@link configureEventSource} for this provider's subscription. */
5299
+ protected readonly eventSource?: EventSourceFactory;
5300
+ constructor(serverUrl?: string, options?: EventSourceCapable);
4817
5301
  getVtxoTree(batchOutpoint: Outpoint, opts?: PaginationOptions): Promise<{
4818
5302
  vtxoTree: Tx[];
4819
5303
  page?: PageResponse;
@@ -5109,7 +5593,9 @@ interface ArkProvider {
5109
5593
  */
5110
5594
  declare class RestArkProvider implements ArkProvider {
5111
5595
  serverUrl: string;
5112
- constructor(serverUrl?: string);
5596
+ /** Overrides {@link configureEventSource} for this provider's streams. */
5597
+ protected readonly eventSource?: EventSourceFactory;
5598
+ constructor(serverUrl?: string, options?: EventSourceCapable);
5113
5599
  /**
5114
5600
  * Last server-info digest seen (from {@link getInfo}). Sent as `X-Digest`
5115
5601
  * on outgoing requests so arkd can reject a client whose cached info is
@@ -5303,4 +5789,4 @@ declare namespace ProtoTypes {
5303
5789
  export { };
5304
5790
  }
5305
5791
 
5306
- export { type TreeSignatureEvent as $, type ArkTransaction as A, type VirtualTxRepository as B, type ContractRepository as C, type VirtualTx as D, type ExtendedCoin as E, type VtxoBranch as F, type GetVtxosFilter as G, ChainedTxType as H, type IWallet as I, type Network as J, CSVMultisigTapscript as K, type SignerSet as L, type BatchStartedEvent as M, type NormalizedExtendedVirtualCoin as N, type Outpoint as O, type TreeSigningStartedEvent as P, TxTree as Q, type Recipient as R, type SendBitcoinParams as S, type TxNotification as T, type TreeNoncesEvent as U, VtxoScript as V, type WalletRepository as W, type BatchFinalizationEvent as X, type BatchFinalizedEvent as Y, type BatchFailedEvent as Z, type TreeTxEvent as _, type Identity as a, type BatchInfo as a$, type DescriptorProvider as a0, type IReadonlyWallet as a1, type ReadonlyIdentity as a2, type OnchainProvider as a3, type DelegateProvider as a4, type ReadonlyWalletConfig as a5, type ExitCaptureMode as a6, type ExitDataSource as a7, type IReadonlyAssetManager as a8, type ContractSyncState as a9, type IssuanceParams as aA, type ReissuanceParams as aB, type BurnParams as aC, type RenewVtxosOptions as aD, type ContractWithVtxos as aE, type PathSelection as aF, type ContractEvent as aG, type AssetDetails as aH, type IssuanceResult as aI, type DelegateInfo as aJ, type MigrationGlobalSkipReason as aK, type MigrationLegSkipReason as aL, type SignerStatus as aM, type StorageConfig as aN, type IVtxoManager as aO, type ExplorerTransaction as aP, type EncodedVtxoScript as aQ, type Status as aR, type ChainTx as aS, type PathContext as aT, type ActivityIntent as aU, type ActivityResolver as aV, type ArkIntentState as aW, type ArkTapscript as aX, type AssetMetadata as aY, BITCOIN_EMULATOR_PUBKEY as aZ, type BaseWalletConfig as a_, type NetworkName as aa, type ArkInfo as ab, ArkAddress as ac, type Coin as ad, ContractManager as ae, type ContractManagerConfig as af, type SettlementConfig as ag, VtxoManager as ah, type SignerSession as ai, type SignedIntent as aj, Intent as ak, type TimeHeight as al, type DescriptorSigningRequest as am, Transaction as an, type IntentFeeConfig as ao, type OffchainInput as ap, FeeAmount as aq, type OnchainInput as ar, type FeeOutput as as, type ContractWatcherConfig as at, type Asset as au, type FeeInfo as av, type CreateContractParams as aw, type GetContractsFilter as ax, type GetSpendablePathsOptions as ay, type GetAllSpendingPathsOptions as az, type WalletConfig as b, type TxTag as b$, type BatchSignableIdentity as b0, CLTVMultisigTapscript as b1, type CandidateDeps as b2, ChainTxType as b3, type CommitmentTx as b4, ConditionCSVMultisigTapscript as b5, ConditionMultisigTapscript as b6, type ContractBalance as b7, type ContractEventCallback as b8, type ContractHandler as b9, type MigrationVtxoRef as bA, MultisigTapscript as bB, type Nonces as bC, type Output as bD, type PageResponse as bE, type PaginationOptions as bF, PartialSig as bG, type ProviderClass as bH, REGTEST_EMULATOR_PUBKEY as bI, RestDelegateProvider as bJ, RestDelegatorProvider as bK, type ScanContractsOptions as bL, type ScanResult as bM, type ScheduledSession as bN, SettlementEventType as bO, type SignRequest as bP, type SignerClassification as bQ, type SubscriptionEvent as bR, type SubscriptionHeartbeat as bS, type TapLeaves as bT, TapTreeCoder as bU, TapscriptType as bV, type TreeNonces as bW, type TreePartialSigs as bX, type Tx as bY, type TxHistoryRecord as bZ, type TxKey as b_, type ContractState as ba, type ContractVtxo as bb, ContractWatcher as bc, DelegateManagerImpl as bd, type DelegateOptions as be, DelegatorManagerImpl as bf, type DelegatorProvider as bg, type DeprecatedSignerMigrationReport as bh, type DeprecatedSignerReport as bi, DigestMismatchError as bj, type Discoverable as bk, type DiscoveredContract as bl, type DiscoveryDeps as bm, ESPLORA_URL as bn, EsploraProvider as bo, type ExitChainResolver as bp, type ExtendedContractVtxo as bq, type GroupMembership as br, type HandlerError as bs, type IDelegatorManager as bt, INTENT_TERMINAL_STATES as bu, IndexerTxType as bv, type KnownMetadata as bw, MUTINYNET_EMULATOR_PUBKEY as bx, type MigrateDeprecatedSignerOptions as by, type MigrationLegReport as bz, type WalletBalance as c, type TxTreeNode as c0, TxType as c1, type VirtualStatus as c2, type Vtxo as c3, type VtxoChain as c4, type VtxoType as c5, type WalletMode as c6, assetMintResolver as c7, boardingResolver as c8, canRecoverOnchain as c9, signerSetFromInfo as cA, toXOnlySignerHex as cB, type TapscriptDeriving as cC, canSpendOffchain as ca, classifyAgainstSignerSet as cb, classifyContractSigner as cc, collabExitResolver as cd, createDefaultActivityRegistry as ce, createExitChainResolver as cf, decodeTapscript as cg, defaultEmulatorPubkey as ch, getNetwork as ci, getSequence as cj, hasCandidates as ck, hasTerminalSpend as cl, isBatchSignable as cm, isCooperativelyMigratable as cn, isDiscoverable as co, isExpired as cp, isPastExpiry as cq, isRecoverable as cr, isSpendable as cs, isSubdust as ct, isTerminalIntentState as cu, isVirtualCoin as cv, isVtxoExpiringSoon as cw, networks as cx, resolveEmulatorPubkey as cy, scriptFromTapLeafScript as cz, ActivityRegistry as d, type Activity as e, type IContractManager as f, type IDelegateManager as g, type SettleParams as h, type SettlementEvent as i, type IAssetManager as j, RestArkProvider as k, RestIndexerProvider as l, type SubscriptionResponse as m, type ArkProvider as n, type IndexerProvider as o, type RelativeTimelock as p, type TapLeafScript as q, type VirtualCoin as r, type Contract as s, type ExtendedVirtualCoin as t, type VtxoRepositoryKey as u, type WalletState as v, type ContractFilter as w, type IntentRepository as x, type ArkIntent as y, type IntentFilter as z };
5792
+ export { type DescriptorProvider as $, type ArkTransaction as A, type VirtualTxRepository as B, type ContractRepository as C, type VirtualTx as D, type ExtendedCoin as E, type VtxoBranch as F, type GetVtxosFilter as G, ChainedTxType as H, type IWallet as I, type Network as J, CSVMultisigTapscript as K, type BatchStartedEvent as L, type TreeSigningStartedEvent as M, type NormalizedExtendedVirtualCoin as N, type Outpoint as O, TxTree as P, type TreeNoncesEvent as Q, type Recipient as R, type SendBitcoinParams as S, type TxNotification as T, type BatchFinalizationEvent as U, VtxoScript as V, type WalletRepository as W, type BatchFinalizedEvent as X, type BatchFailedEvent as Y, type TreeTxEvent as Z, type TreeSignatureEvent as _, type Identity as a, type BaseWalletConfig as a$, type IReadonlyWallet as a0, type ReadonlyIdentity as a1, type OnchainProvider as a2, type DelegateProvider as a3, type ReadonlyWalletConfig as a4, type ExitCaptureMode as a5, type ExitDataSource as a6, type IReadonlyAssetManager as a7, type ContractSyncState as a8, type RecipientAddressContext as a9, type GetSpendablePathsOptions as aA, type GetAllSpendingPathsOptions as aB, type IssuanceParams as aC, type ReissuanceParams as aD, type BurnParams as aE, type RenewVtxosOptions as aF, type PathSelection as aG, type ContractEvent as aH, type AssetDetails as aI, type IssuanceResult as aJ, type DelegateInfo as aK, type MigrationGlobalSkipReason as aL, type MigrationLegSkipReason as aM, type SignerStatus as aN, type StorageConfig as aO, type IVtxoManager as aP, type ExplorerTransaction as aQ, type EncodedVtxoScript as aR, type Status as aS, type ChainTx as aT, type PathContext as aU, type ActivityIntent as aV, type ActivityResolver as aW, type ArkIntentState as aX, type ArkTapscript as aY, type AssetMetadata as aZ, BITCOIN_EMULATOR_PUBKEY as a_, type NetworkName as aa, type ArkInfo as ab, ArkAddress as ac, type ContractWithVtxos as ad, selectPendingRecoveryOutpoints as ae, type Coin as af, ContractManager as ag, type ContractManagerConfig as ah, type SettlementConfig as ai, VtxoManager as aj, type SignerSession as ak, type SignedIntent as al, Intent as am, type TimeHeight as an, type DescriptorSigningRequest as ao, Transaction as ap, type IntentFeeConfig as aq, type OffchainInput as ar, FeeAmount as as, type OnchainInput as at, type FeeOutput as au, type ContractWatcherConfig as av, type Asset as aw, type FeeInfo as ax, type CreateContractParams as ay, type GetContractsFilter as az, type WalletConfig as b, TapscriptType as b$, type BatchInfo as b0, type BatchSignableIdentity as b1, CLTVMultisigTapscript as b2, type CandidateDeps as b3, ChainTxType as b4, type CommitmentTx as b5, ConditionCSVMultisigTapscript as b6, ConditionMultisigTapscript as b7, type ContractBalance as b8, type ContractEventCallback as b9, IndexerTxType as bA, type KnownMetadata as bB, MUTINYNET_EMULATOR_PUBKEY as bC, type MigrateDeprecatedSignerOptions as bD, type MigrationLegReport as bE, type MigrationVtxoRef as bF, MultisigTapscript as bG, type Nonces as bH, type Output as bI, type PageResponse as bJ, type PaginationOptions as bK, PartialSig as bL, type ProviderClass as bM, REGTEST_EMULATOR_PUBKEY as bN, RestDelegateProvider as bO, RestDelegatorProvider as bP, type ScanContractsOptions as bQ, type ScanResult as bR, type ScheduledSession as bS, SettlementEventType as bT, type SignRequest as bU, type SignerClassification as bV, type SignerSet as bW, type SubscriptionEvent as bX, type SubscriptionHeartbeat as bY, type TapLeaves as bZ, TapTreeCoder as b_, type ContractHandler as ba, type ContractState as bb, type ContractVtxo as bc, ContractWatcher as bd, DelegateManagerImpl as be, type DelegateOptions as bf, DelegatorManagerImpl as bg, type DelegatorProvider as bh, type DeprecatedSignerMigrationReport as bi, type DeprecatedSignerReport as bj, DigestMismatchError as bk, type Discoverable as bl, type DiscoveredContract as bm, type DiscoveryDeps as bn, ESPLORA_URL as bo, EsploraProvider as bp, type EventSourceCapable as bq, type EventSourceFactory as br, type EventSourceLike as bs, EventSourceUnavailableError as bt, type ExitChainResolver as bu, type ExtendedContractVtxo as bv, type GroupMembership as bw, type HandlerError as bx, type IDelegatorManager as by, INTENT_TERMINAL_STATES as bz, type WalletBalance as c, type TreeNonces as c0, type TreePartialSigs as c1, type Tx as c2, type TxHistoryRecord as c3, type TxKey as c4, type TxTag as c5, type TxTreeNode as c6, TxType as c7, type VirtualStatus as c8, type Vtxo as c9, isPastExpiry as cA, isRecoverable as cB, isSpendable as cC, isSubdust as cD, isTerminalIntentState as cE, isVirtualCoin as cF, isVtxoExpiringSoon as cG, networks as cH, resolveEmulatorPubkey as cI, resolveEventSource as cJ, scriptFromTapLeafScript as cK, signerSetFromInfo as cL, toXOnlySignerHex as cM, type TapscriptDeriving as cN, type VtxoChain as ca, type VtxoType as cb, type WalletMode as cc, assetMintResolver as cd, boardingResolver as ce, canRecoverOnchain as cf, canSpendOffchain as cg, classifyAgainstSignerSet as ch, classifyContractSigner as ci, collabExitResolver as cj, configureEventSource as ck, createDefaultActivityRegistry as cl, createExitChainResolver as cm, decodeTapscript as cn, defaultEmulatorPubkey as co, getConfiguredEventSource as cp, getNetwork as cq, getRandomId as cr, getSequence as cs, hasCandidates as ct, hasTerminalSpend as cu, isBatchSignable as cv, isCooperativelyMigratable as cw, isDiscoverable as cx, isEventSourceUnavailableError as cy, isExpired as cz, ActivityRegistry as d, type Activity as e, type IContractManager as f, type IDelegateManager as g, type SettleParams as h, type SettlementEvent as i, type IAssetManager as j, RestArkProvider as k, RestIndexerProvider as l, type SubscriptionResponse as m, type ArkProvider as n, type IndexerProvider as o, type RelativeTimelock as p, type TapLeafScript as q, type VirtualCoin as r, type Contract as s, type ExtendedVirtualCoin as t, type VtxoRepositoryKey as u, type WalletState as v, type ContractFilter as w, type IntentRepository as x, type ArkIntent as y, type IntentFilter as z };