@arkade-os/sdk 0.4.21 → 0.4.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -12
- package/dist/cjs/contracts/arkcontract.js +2 -1
- package/dist/cjs/contracts/contractWatcher.js +16 -18
- package/dist/cjs/identity/descriptor.js +75 -4
- package/dist/cjs/identity/hdCapableIdentity.js +2 -0
- package/dist/cjs/identity/seedIdentity.js +225 -103
- package/dist/cjs/identity/serialize.js +5 -0
- package/dist/cjs/identity/staticDescriptorProvider.js +1 -1
- package/dist/cjs/index.js +12 -3
- package/dist/cjs/providers/electrum.js +285 -79
- package/dist/cjs/providers/expoIndexer.js +1 -1
- package/dist/cjs/providers/indexer.js +2 -2
- package/dist/cjs/providers/onchain.js +9 -3
- package/dist/cjs/repositories/migrations/walletRepositoryImpl.js +6 -2
- package/dist/cjs/repositories/realm/walletRepository.js +2 -2
- package/dist/cjs/repositories/serialization.js +34 -1
- package/dist/cjs/repositories/sqlite/walletRepository.js +4 -2
- package/dist/cjs/script/address.js +2 -1
- package/dist/cjs/utils/transactionHistory.js +4 -4
- package/dist/cjs/wallet/asset-manager.js +18 -18
- package/dist/cjs/wallet/asset.js +10 -8
- package/dist/cjs/wallet/delegator.js +29 -20
- package/dist/cjs/wallet/hdDescriptorProvider.js +159 -0
- package/dist/cjs/wallet/index.js +5 -1
- package/dist/cjs/wallet/onchain.js +2 -1
- package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +4 -2
- package/dist/cjs/wallet/serviceWorker/wallet.js +5 -4
- package/dist/cjs/wallet/validation.js +2 -3
- package/dist/cjs/wallet/vtxo-manager.js +7 -5
- package/dist/cjs/wallet/wallet.js +13 -14
- package/dist/esm/contracts/arkcontract.js +2 -1
- package/dist/esm/contracts/contractWatcher.js +14 -16
- package/dist/esm/identity/descriptor.js +74 -5
- package/dist/esm/identity/hdCapableIdentity.js +1 -0
- package/dist/esm/identity/seedIdentity.js +225 -103
- package/dist/esm/identity/serialize.js +5 -0
- package/dist/esm/identity/staticDescriptorProvider.js +1 -1
- package/dist/esm/index.js +7 -4
- package/dist/esm/providers/electrum.js +284 -78
- package/dist/esm/providers/expoIndexer.js +1 -1
- package/dist/esm/providers/indexer.js +2 -2
- package/dist/esm/providers/onchain.js +9 -3
- package/dist/esm/repositories/migrations/walletRepositoryImpl.js +6 -2
- package/dist/esm/repositories/realm/walletRepository.js +3 -3
- package/dist/esm/repositories/serialization.js +27 -0
- package/dist/esm/repositories/sqlite/walletRepository.js +5 -3
- package/dist/esm/script/address.js +2 -1
- package/dist/esm/utils/transactionHistory.js +4 -4
- package/dist/esm/wallet/asset-manager.js +18 -18
- package/dist/esm/wallet/asset.js +10 -8
- package/dist/esm/wallet/delegator.js +29 -20
- package/dist/esm/wallet/hdDescriptorProvider.js +155 -0
- package/dist/esm/wallet/index.js +4 -0
- package/dist/esm/wallet/onchain.js +2 -1
- package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +4 -2
- package/dist/esm/wallet/serviceWorker/wallet.js +5 -4
- package/dist/esm/wallet/validation.js +2 -3
- package/dist/esm/wallet/vtxo-manager.js +7 -5
- package/dist/esm/wallet/wallet.js +12 -14
- package/dist/types/contracts/arkcontract.d.ts +1 -1
- package/dist/types/contracts/types.d.ts +5 -5
- package/dist/types/identity/descriptor.d.ts +26 -0
- package/dist/types/identity/descriptorProvider.d.ts +11 -4
- package/dist/types/identity/hdCapableIdentity.d.ts +44 -0
- package/dist/types/identity/index.d.ts +1 -0
- package/dist/types/identity/seedIdentity.d.ts +113 -29
- package/dist/types/identity/serialize.d.ts +12 -0
- package/dist/types/identity/staticDescriptorProvider.d.ts +1 -1
- package/dist/types/index.d.ts +6 -3
- package/dist/types/providers/electrum.d.ts +115 -15
- package/dist/types/providers/onchain.d.ts +6 -0
- package/dist/types/repositories/serialization.d.ts +26 -2
- package/dist/types/script/address.d.ts +1 -1
- package/dist/types/wallet/delegator.d.ts +8 -3
- package/dist/types/wallet/hdDescriptorProvider.d.ts +93 -0
- package/dist/types/wallet/index.d.ts +19 -10
- package/dist/types/wallet/onchain.d.ts +1 -1
- package/dist/types/wallet/serviceWorker/wallet.d.ts +1 -1
- package/dist/types/wallet/wallet.d.ts +4 -1
- package/package.json +4 -4
|
@@ -1,7 +1,39 @@
|
|
|
1
1
|
import type { ElectrumWS } from "ws-electrumx-client";
|
|
2
|
-
import type { Network } from "../networks";
|
|
2
|
+
import type { Network, NetworkName } from "../networks";
|
|
3
3
|
import type { Coin } from "../wallet";
|
|
4
4
|
import type { ExplorerTransaction, OnchainProvider } from "./onchain";
|
|
5
|
+
/**
|
|
6
|
+
* Default WebSocket Electrum endpoints. Mainnet, mutinynet, and signet
|
|
7
|
+
* point at Ark Labs–operated Fulcrum 2.1 deployments (which support
|
|
8
|
+
* `blockchain.transaction.broadcast_package` for atomic 1P1C TRUC
|
|
9
|
+
* relay; see `ElectrumOnchainProvider.broadcastTransaction`). Testnet
|
|
10
|
+
* defaults to Blockstream's public Fulcrum because Ark doesn't host
|
|
11
|
+
* it. Regtest assumes the `electrum-ws` websocat bridge from
|
|
12
|
+
* `vulpemventures/nigiri`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { ElectrumWS } from "ws-electrumx-client";
|
|
17
|
+
* import { ELECTRUM_WS_URL, ElectrumOnchainProvider, networks } from "@arkade-os/sdk";
|
|
18
|
+
*
|
|
19
|
+
* const ws = new ElectrumWS(ELECTRUM_WS_URL.bitcoin);
|
|
20
|
+
* const provider = new ElectrumOnchainProvider(ws, networks.bitcoin);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const ELECTRUM_WS_URL: Record<NetworkName, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Hostnames for Electrum endpoints reachable over raw TCP. Provided as
|
|
26
|
+
* a reference for Node-side consumers — the SDK's
|
|
27
|
+
* {@link ElectrumOnchainProvider} only speaks WebSocket because it has
|
|
28
|
+
* to run in browsers, so this map is informational only and not
|
|
29
|
+
* consumed by any built-in provider.
|
|
30
|
+
*
|
|
31
|
+
* Public Ark Labs Fulcrum instances expose:
|
|
32
|
+
* - port 50001 — plain TCP (Electrum protocol)
|
|
33
|
+
* - port 50002 — TCP + TLS (Electrum protocol)
|
|
34
|
+
* - port 50003 — WebSocket (Electrum-over-WS, see {@link ELECTRUM_WS_URL})
|
|
35
|
+
*/
|
|
36
|
+
export declare const ELECTRUM_TCP_HOST: Record<NetworkName, string | null>;
|
|
5
37
|
export type TransactionHistory = {
|
|
6
38
|
tx_hash: string;
|
|
7
39
|
height: number;
|
|
@@ -70,12 +102,46 @@ export declare class WsElectrumChainSource {
|
|
|
70
102
|
private cachedTip;
|
|
71
103
|
private headersSubscribePromise;
|
|
72
104
|
constructor(ws: ElectrumWS, network: Network);
|
|
105
|
+
/**
|
|
106
|
+
* Send N requests in parallel and aggregate the results, replacement
|
|
107
|
+
* for `ws.batchRequest`. The library's batchRequest is implemented as
|
|
108
|
+
* `Promise.all` over individual request promises — when one element
|
|
109
|
+
* rejects, the others remain pending. When their (often error)
|
|
110
|
+
* responses arrive later, the library rejects them too, and nobody is
|
|
111
|
+
* awaiting them: the rejections become unhandled and crash the test
|
|
112
|
+
* runner / pollute production logs.
|
|
113
|
+
*
|
|
114
|
+
* `safeBatchRequest` issues each request through `ws.request` (so each
|
|
115
|
+
* has its own request-promise lifecycle), waits for all of them via
|
|
116
|
+
* `Promise.allSettled` (every promise gets an explicit handler), and
|
|
117
|
+
* then surfaces the first error if any failed. Same wall-clock cost
|
|
118
|
+
* as the library's batch (parallel send), no orphan rejections.
|
|
119
|
+
*
|
|
120
|
+
* Use this in place of `ws.batchRequest` for any call where one or
|
|
121
|
+
* more elements may legitimately error (e.g. electrs index lag
|
|
122
|
+
* surfacing as `missingheight` for a subset of heights/txids).
|
|
123
|
+
*/
|
|
124
|
+
safeBatchRequest<T>(requests: {
|
|
125
|
+
method: string;
|
|
126
|
+
params: unknown[];
|
|
127
|
+
}[]): Promise<T[]>;
|
|
73
128
|
fetchTransactions(txids: string[]): Promise<{
|
|
74
129
|
txID: string;
|
|
75
130
|
hex: string;
|
|
76
131
|
}[]>;
|
|
77
132
|
fetchVerboseTransaction(txid: string): Promise<VerboseTransaction>;
|
|
78
133
|
fetchVerboseTransactions(txids: string[]): Promise<VerboseTransaction[]>;
|
|
134
|
+
/**
|
|
135
|
+
* Look up the block height of a confirmed transaction without relying
|
|
136
|
+
* on the verbose-tx endpoint. `blockchain.transaction.get_merkle` is
|
|
137
|
+
* part of the standard SPV protocol and is supported by both Fulcrum
|
|
138
|
+
* and electrs (whereas `blockchain.transaction.get` with verbose=true
|
|
139
|
+
* is Fulcrum-only). Returns `null` when the tx is in the mempool —
|
|
140
|
+
* electrs in that case rejects with a "not yet in a block" error.
|
|
141
|
+
*/
|
|
142
|
+
fetchTxMerkle(txid: string): Promise<{
|
|
143
|
+
blockHeight: number;
|
|
144
|
+
} | null>;
|
|
79
145
|
unsubscribeScriptStatus(script: Uint8Array): Promise<void>;
|
|
80
146
|
subscribeScriptStatus(script: Uint8Array, callback: (scripthash: string, status: string | null) => void): Promise<void>;
|
|
81
147
|
fetchHistories(scripts: Uint8Array[]): Promise<TransactionHistory[][]>;
|
|
@@ -130,19 +196,45 @@ export declare class WsElectrumChainSource {
|
|
|
130
196
|
addressForScript(scriptHex: string): string | undefined;
|
|
131
197
|
}
|
|
132
198
|
/**
|
|
133
|
-
* Electrum-based implementation of the OnchainProvider interface.
|
|
134
|
-
* Replaces esplora polling with electrum subscriptions where possible.
|
|
199
|
+
* Electrum-based implementation of the {@link OnchainProvider} interface.
|
|
135
200
|
*
|
|
136
|
-
*
|
|
201
|
+
* Built around the subset of the Electrum protocol that both **Fulcrum**
|
|
202
|
+
* and **electrs** support — listunspent, get_history, transaction.get
|
|
203
|
+
* (non-verbose), transaction.get_merkle, block.header,
|
|
204
|
+
* headers.subscribe, scripthash.subscribe, estimatefee, relayfee, and
|
|
205
|
+
* broadcast. The verbose form of `transaction.get` is **not** used (it's
|
|
206
|
+
* Fulcrum-only and rejected by electrs); confirmation status is derived
|
|
207
|
+
* from `transaction.get_merkle` plus parsed block headers.
|
|
208
|
+
*
|
|
209
|
+
* Output amounts are derived from parsed raw transaction bytes (exact
|
|
210
|
+
* bigints), never the floating-point `value` fields some servers return.
|
|
211
|
+
*
|
|
212
|
+
* Atomic 1P1C package broadcast (TRUC / BIP 431) is supported via
|
|
213
|
+
* Fulcrum's `blockchain.transaction.broadcast_package`. There is **no
|
|
214
|
+
* fallback** to sequential parent-then-child broadcasts — TRUC packages
|
|
215
|
+
* with a zero-fee parent would silently fail, so the call surfaces an
|
|
216
|
+
* error against servers that don't support the method.
|
|
217
|
+
*
|
|
218
|
+
* @example Default URL via {@link ELECTRUM_WS_URL}
|
|
137
219
|
* ```typescript
|
|
138
220
|
* import { ElectrumWS } from "ws-electrumx-client";
|
|
139
|
-
* import {
|
|
140
|
-
*
|
|
221
|
+
* import {
|
|
222
|
+
* ElectrumOnchainProvider,
|
|
223
|
+
* ELECTRUM_WS_URL,
|
|
224
|
+
* networks,
|
|
225
|
+
* } from "@arkade-os/sdk";
|
|
141
226
|
*
|
|
142
|
-
* const ws = new ElectrumWS(
|
|
227
|
+
* const ws = new ElectrumWS(ELECTRUM_WS_URL.bitcoin);
|
|
143
228
|
* const provider = new ElectrumOnchainProvider(ws, networks.bitcoin);
|
|
144
229
|
*
|
|
145
230
|
* const coins = await provider.getCoins("bc1q...");
|
|
231
|
+
* await provider.close();
|
|
232
|
+
* ```
|
|
233
|
+
*
|
|
234
|
+
* @example Custom server
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const ws = new ElectrumWS("wss://my-fulcrum.example:50004");
|
|
237
|
+
* const provider = new ElectrumOnchainProvider(ws, networks.bitcoin);
|
|
146
238
|
* ```
|
|
147
239
|
*/
|
|
148
240
|
export declare class ElectrumOnchainProvider implements OnchainProvider {
|
|
@@ -178,15 +270,23 @@ export declare class ElectrumOnchainProvider implements OnchainProvider {
|
|
|
178
270
|
}[]>;
|
|
179
271
|
getTransactions(address: string): Promise<ExplorerTransaction[]>;
|
|
180
272
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
273
|
+
* Resolve a list of `{tx_hash, height}` entries (as returned by the
|
|
274
|
+
* scripthash history endpoint) into ExplorerTransaction shape **without
|
|
275
|
+
* using the verbose-tx endpoint**, which only Fulcrum implements. We
|
|
276
|
+
* reconstruct everything the verbose response would have given us:
|
|
277
|
+
* - vouts ← parse the raw tx (exact sat amounts, no float precision risk)
|
|
278
|
+
* - block_time ← batch-fetch the block headers for the heights present
|
|
279
|
+
* - addresses ← decode each output's scriptPubKey via @scure/btc-signer
|
|
280
|
+
*/
|
|
281
|
+
private historyToExplorerTxs;
|
|
282
|
+
/**
|
|
283
|
+
* Build an ExplorerTransaction from a history entry plus the raw tx hex
|
|
284
|
+
* (when known) and a height→block_time map. Parse errors propagate —
|
|
285
|
+
* silently returning an empty vout would hide real outputs (e.g. a
|
|
286
|
+
* deposit) and is far worse for protocol-level money handling than
|
|
287
|
+
* failing the whole batch.
|
|
188
288
|
*/
|
|
189
|
-
private
|
|
289
|
+
private buildExplorerTx;
|
|
190
290
|
/**
|
|
191
291
|
* Decode `address` into its scriptPubKey, throwing a clear error if the
|
|
192
292
|
* input is malformed. @scure/btc-signer raises a generic decode error
|
|
@@ -2,6 +2,12 @@ import type { NetworkName } from "../networks";
|
|
|
2
2
|
import { Coin } from "../wallet";
|
|
3
3
|
/**
|
|
4
4
|
* The default base URLs for esplora API providers.
|
|
5
|
+
*
|
|
6
|
+
* Mainnet, mutinynet, and signet point at Ark Labs–operated
|
|
7
|
+
* mempool deployments (mempool.space-compatible esplora API).
|
|
8
|
+
* Testnet falls back to the public mempool.space deployment
|
|
9
|
+
* because Ark doesn't host it. Regtest assumes a local nigiri
|
|
10
|
+
* stack on the standard port.
|
|
5
11
|
*/
|
|
6
12
|
export declare const ESPLORA_URL: Record<NetworkName, string>;
|
|
7
13
|
export type ExplorerTransaction = {
|
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import { TapLeafScript } from "../script/base";
|
|
2
|
-
import { ExtendedCoin, ExtendedVirtualCoin } from "../wallet";
|
|
2
|
+
import { ArkTransaction, Asset, ExtendedCoin, ExtendedVirtualCoin } from "../wallet";
|
|
3
3
|
export type SerializedTapLeaf = {
|
|
4
4
|
cb: string;
|
|
5
5
|
s: string;
|
|
6
6
|
};
|
|
7
7
|
export type SerializedVtxo = ReturnType<typeof serializeVtxo>;
|
|
8
8
|
export type SerializedUtxo = ReturnType<typeof serializeUtxo>;
|
|
9
|
+
export type SerializedTransaction = ReturnType<typeof serializeTransaction>;
|
|
10
|
+
export type SerializedAsset = {
|
|
11
|
+
assetId: string;
|
|
12
|
+
amount: string;
|
|
13
|
+
};
|
|
9
14
|
export declare const serializeTapLeaf: ([cb, s,]: TapLeafScript) => SerializedTapLeaf;
|
|
15
|
+
export declare const serializeAsset: (a: Asset) => SerializedAsset;
|
|
16
|
+
export declare const deserializeAsset: (a: {
|
|
17
|
+
assetId: string;
|
|
18
|
+
amount: string | number | bigint;
|
|
19
|
+
}) => Asset;
|
|
20
|
+
export declare const serializeAssets: (assets: Asset[] | undefined) => SerializedAsset[] | undefined;
|
|
21
|
+
export declare const deserializeAssets: (assets: Array<{
|
|
22
|
+
assetId: string;
|
|
23
|
+
amount: string | number | bigint;
|
|
24
|
+
}> | undefined) => Asset[] | undefined;
|
|
10
25
|
export declare const serializeVtxo: (v: ExtendedVirtualCoin) => {
|
|
11
26
|
tapTree: string;
|
|
12
27
|
forfeitTapLeafScript: SerializedTapLeaf;
|
|
13
28
|
intentTapLeafScript: SerializedTapLeaf;
|
|
14
29
|
extraWitness: string[] | undefined;
|
|
30
|
+
assets: SerializedAsset[] | undefined;
|
|
15
31
|
virtualStatus: import("../wallet").VirtualStatus;
|
|
16
32
|
spentBy?: string;
|
|
17
33
|
settledBy?: string;
|
|
@@ -19,7 +35,6 @@ export declare const serializeVtxo: (v: ExtendedVirtualCoin) => {
|
|
|
19
35
|
createdAt: Date;
|
|
20
36
|
isUnrolled: boolean;
|
|
21
37
|
isSpent?: boolean;
|
|
22
|
-
assets?: import("../wallet").Asset[];
|
|
23
38
|
script: string;
|
|
24
39
|
value: number;
|
|
25
40
|
status: import("../wallet").Status;
|
|
@@ -36,6 +51,15 @@ export declare const serializeUtxo: (u: ExtendedCoin) => {
|
|
|
36
51
|
txid: string;
|
|
37
52
|
vout: number;
|
|
38
53
|
};
|
|
54
|
+
export declare const serializeTransaction: (t: ArkTransaction) => {
|
|
55
|
+
assets: SerializedAsset[] | undefined;
|
|
56
|
+
key: import("../wallet").TxKey;
|
|
57
|
+
type: import("../wallet").TxType;
|
|
58
|
+
amount: number;
|
|
59
|
+
settled: boolean;
|
|
60
|
+
createdAt: number;
|
|
61
|
+
};
|
|
39
62
|
export declare const deserializeTapLeaf: (t: SerializedTapLeaf) => TapLeafScript;
|
|
40
63
|
export declare const deserializeVtxo: (o: SerializedVtxo) => ExtendedVirtualCoin;
|
|
41
64
|
export declare const deserializeUtxo: (o: SerializedUtxo) => ExtendedCoin;
|
|
65
|
+
export declare const deserializeTransaction: (o: SerializedTransaction) => ArkTransaction;
|
|
@@ -43,7 +43,7 @@ export declare class ArkAddress {
|
|
|
43
43
|
* @defaultValue `version = 0`
|
|
44
44
|
* @throws Error if either public key is not 32 bytes long
|
|
45
45
|
*/
|
|
46
|
-
constructor(serverPubKey: Bytes, vtxoTaprootKey: Bytes, hrp
|
|
46
|
+
constructor(serverPubKey: Bytes, vtxoTaprootKey: Bytes, hrp?: string, version?: number);
|
|
47
47
|
/**
|
|
48
48
|
* Decode an Arkade address from its bech32m string form.
|
|
49
49
|
*
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { TransactionOutput } from "@scure/btc-signer/psbt";
|
|
2
|
-
import { ArkProvider, DelegateInfo,
|
|
2
|
+
import { ArkProvider, DelegateInfo, Identity, Outpoint } from "..";
|
|
3
|
+
import { ContractVtxo } from "../contracts/types";
|
|
3
4
|
import { DelegatorProvider } from "../providers/delegator";
|
|
4
5
|
import { Bytes } from "@scure/btc-signer/utils";
|
|
5
6
|
export interface IDelegatorManager {
|
|
6
7
|
/**
|
|
7
8
|
* Delegate virtual outputs to the remote delegation service.
|
|
8
9
|
*
|
|
10
|
+
* Vtxos that are not locked to a delegate-type contract (no tap leaf
|
|
11
|
+
* matches the delegator's pubkey) are filtered out silently, since they
|
|
12
|
+
* cannot be co-signed by the delegator.
|
|
13
|
+
*
|
|
9
14
|
* @param vtxos - Virtual outputs to delegate
|
|
10
15
|
* @param destination - Arkade address that should receive renewed funds
|
|
11
16
|
* @param delegateAt - Optional timestamp to force a specific delegation time
|
|
12
17
|
* @returns Successfully delegated and failed outpoint groups
|
|
13
18
|
*/
|
|
14
|
-
delegate(vtxos:
|
|
19
|
+
delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
|
|
15
20
|
delegated: Outpoint[];
|
|
16
21
|
failed: {
|
|
17
22
|
outpoints: Outpoint[];
|
|
@@ -28,7 +33,7 @@ export declare class DelegatorManagerImpl implements IDelegatorManager {
|
|
|
28
33
|
/** Create a delegator manager from the configured provider, Arkade info source, and wallet identity. */
|
|
29
34
|
constructor(delegatorProvider: DelegatorProvider, arkInfoProvider: Pick<ArkProvider, "getInfo">, identity: Identity);
|
|
30
35
|
getDelegateInfo(): Promise<DelegateInfo>;
|
|
31
|
-
delegate(vtxos:
|
|
36
|
+
delegate(vtxos: ContractVtxo[], destination: string, delegateAt?: Date): Promise<{
|
|
32
37
|
delegated: Outpoint[];
|
|
33
38
|
failed: {
|
|
34
39
|
outpoints: Outpoint[];
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { DescriptorProvider, DescriptorSigningRequest } from "../identity/descriptorProvider";
|
|
2
|
+
import { HDCapableIdentity } from "../identity/hdCapableIdentity";
|
|
3
|
+
import { WalletRepository } from "../repositories/walletRepository";
|
|
4
|
+
import { Transaction } from "../utils/transaction";
|
|
5
|
+
/**
|
|
6
|
+
* HD-wallet {@link DescriptorProvider} that allocates a fresh signing
|
|
7
|
+
* descriptor on every call. The provider holds no notion of "current" — it
|
|
8
|
+
* is a pure rotating allocator. The question of "which descriptor is the
|
|
9
|
+
* wallet currently bound to?" is answered by querying the contract
|
|
10
|
+
* repository for active contracts, not by asking this provider.
|
|
11
|
+
*
|
|
12
|
+
* State is persisted under `WalletRepository.getWalletState().settings.hd` so
|
|
13
|
+
* that no storage-schema migration is required when switching a wallet from
|
|
14
|
+
* single-key to HD. The provider is backed by an {@link HDCapableIdentity},
|
|
15
|
+
* which carries the wildcard account descriptor template (for derivation)
|
|
16
|
+
* and the signing primitives.
|
|
17
|
+
*
|
|
18
|
+
* The read-modify-write of the persisted index runs inside the shared per-
|
|
19
|
+
* repo `updateWalletState` mutex, so two `getNextSigningDescriptor` callers
|
|
20
|
+
* — including those driving separate `HDDescriptorProvider` instances on
|
|
21
|
+
* the same repo — can never observe the same index.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const provider = await HDDescriptorProvider.create(identity, walletRepo);
|
|
26
|
+
* const descriptor = await provider.getNextSigningDescriptor();
|
|
27
|
+
* // descriptor: tr([fp/86'/0'/0']xpub/0/0)
|
|
28
|
+
* const next = await provider.getNextSigningDescriptor();
|
|
29
|
+
* // next: tr([fp/86'/0'/0']xpub/0/1)
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare class HDDescriptorProvider implements DescriptorProvider {
|
|
33
|
+
private readonly identity;
|
|
34
|
+
private readonly walletRepository;
|
|
35
|
+
private constructor();
|
|
36
|
+
/**
|
|
37
|
+
* Construct an HDDescriptorProvider. No I/O is performed here;
|
|
38
|
+
* persisted state is read lazily on the first call to
|
|
39
|
+
* `getNextSigningDescriptor`. A descriptor-mismatch error surfaces on
|
|
40
|
+
* first use rather than at boot.
|
|
41
|
+
*/
|
|
42
|
+
static create(identity: HDCapableIdentity, walletRepository: WalletRepository): Promise<HDDescriptorProvider>;
|
|
43
|
+
/**
|
|
44
|
+
* Allocate the next descriptor and return it. The first call on a fresh
|
|
45
|
+
* wallet returns descriptor at index 0; subsequent calls return 1, 2, 3,
|
|
46
|
+
* ... in order. Each call is atomic with respect to other rotations on
|
|
47
|
+
* the same repo: two concurrent callers can never observe the same
|
|
48
|
+
* index.
|
|
49
|
+
*/
|
|
50
|
+
getNextSigningDescriptor(): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Returns true when the given descriptor is derivable from this wallet's
|
|
53
|
+
* seed. Delegates to the underlying identity, which handles both HD and
|
|
54
|
+
* simple `tr(pubkey)` descriptors.
|
|
55
|
+
*/
|
|
56
|
+
isOurs(descriptor: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Signs each request with the key derived from its descriptor. Delegates
|
|
59
|
+
* to the identity's signing primitives — the identity, not the provider,
|
|
60
|
+
* holds the seed.
|
|
61
|
+
*/
|
|
62
|
+
signWithDescriptor(requests: DescriptorSigningRequest[]): Promise<Transaction[]>;
|
|
63
|
+
/** Signs a message using the key derived from `descriptor`. */
|
|
64
|
+
signMessageWithDescriptor(descriptor: string, message: Uint8Array, signatureType?: "schnorr" | "ecdsa"): Promise<Uint8Array>;
|
|
65
|
+
/**
|
|
66
|
+
* Substitute the wildcard in the identity's account-descriptor template
|
|
67
|
+
* with a concrete index, going through the descriptors-scure parser
|
|
68
|
+
* rather than ad-hoc string substitution. The parser's `expand({ index })`
|
|
69
|
+
* call validates that the input is a ranged template AND produces a
|
|
70
|
+
* canonical materialized key expression at the given index.
|
|
71
|
+
*/
|
|
72
|
+
private materializeAt;
|
|
73
|
+
/**
|
|
74
|
+
* Run the read-modify-write of HD settings inside the shared per-repo
|
|
75
|
+
* wallet-state mutex. The closure receives a freshly-validated settings
|
|
76
|
+
* snapshot, mutates it, and returns whatever value the caller wants to
|
|
77
|
+
* surface; the mutated settings are then persisted as part of the same
|
|
78
|
+
* atomic update.
|
|
79
|
+
*
|
|
80
|
+
* Doing the read inside the lock is what prevents two providers (or two
|
|
81
|
+
* concurrent callers on the same provider) from racing on a stale index.
|
|
82
|
+
*/
|
|
83
|
+
private mutate;
|
|
84
|
+
/**
|
|
85
|
+
* Validate the persisted HD settings (or initialize a fresh record when
|
|
86
|
+
* absent) and return a clone safe for the caller to mutate.
|
|
87
|
+
*
|
|
88
|
+
* The cast to `HDWalletSettings` trusts storage; a corrupted or
|
|
89
|
+
* partially-migrated repo could otherwise produce `NaN` descriptors.
|
|
90
|
+
* Fail loud rather than silently derive garbage.
|
|
91
|
+
*/
|
|
92
|
+
private parseSettings;
|
|
93
|
+
}
|
|
@@ -11,6 +11,10 @@ import { ContractRepository, WalletRepository } from "../repositories";
|
|
|
11
11
|
import { IContractManager } from "../contracts/contractManager";
|
|
12
12
|
import { IDelegatorManager } from "./delegator";
|
|
13
13
|
import { DelegatorProvider } from "../providers/delegator";
|
|
14
|
+
/** Defaults */
|
|
15
|
+
export declare const DEFAULT_ARKADE_SERVER_URL: "https://arkade.computer";
|
|
16
|
+
export declare const DEFAULT_ARKADE_HRP = "ark";
|
|
17
|
+
export declare const DEFAULT_NETWORK_NAME = "bitcoin";
|
|
14
18
|
/**
|
|
15
19
|
* Base configuration options shared by all wallet types.
|
|
16
20
|
*
|
|
@@ -22,9 +26,6 @@ import { DelegatorProvider } from "../providers/delegator";
|
|
|
22
26
|
* Provider-based configuration supplies concrete provider instances directly,
|
|
23
27
|
* including the ArkProvider, IndexerProvider, OnchainProvider, and DelegatorProvider.
|
|
24
28
|
*
|
|
25
|
-
* At least one of the following must be provided:
|
|
26
|
-
* - arkServerUrl OR arkProvider
|
|
27
|
-
*
|
|
28
29
|
* The wallet will use provided URLs to create default providers if custom provider
|
|
29
30
|
* instances are not supplied. If optional parameters are not provided, the wallet
|
|
30
31
|
* will fetch configuration from the Arkade server.
|
|
@@ -255,8 +256,12 @@ export interface SendBitcoinParams {
|
|
|
255
256
|
export interface Asset {
|
|
256
257
|
/** Asset identifier. */
|
|
257
258
|
assetId: string;
|
|
258
|
-
/**
|
|
259
|
-
|
|
259
|
+
/**
|
|
260
|
+
* Asset amount in base units. Typed as `bigint` because asset
|
|
261
|
+
* supplies routinely exceed `Number.MAX_SAFE_INTEGER` (2^53 - 1)
|
|
262
|
+
* and silently truncating in arithmetic would corrupt balances.
|
|
263
|
+
*/
|
|
264
|
+
amount: bigint;
|
|
260
265
|
}
|
|
261
266
|
/**
|
|
262
267
|
* Recipient accepted by `IWallet.send`.
|
|
@@ -310,8 +315,12 @@ export type AssetMetadata = KnownMetadata & Record<string, unknown>;
|
|
|
310
315
|
export type AssetDetails = {
|
|
311
316
|
/** Asset identifier. */
|
|
312
317
|
assetId: string;
|
|
313
|
-
/**
|
|
314
|
-
|
|
318
|
+
/**
|
|
319
|
+
* Total issued supply in base units. Typed as `bigint` for the
|
|
320
|
+
* same reason as {@link Asset.amount} — supplies often exceed
|
|
321
|
+
* `Number.MAX_SAFE_INTEGER`.
|
|
322
|
+
*/
|
|
323
|
+
supply: bigint;
|
|
315
324
|
/** Optional immutable metadata associated with the asset. */
|
|
316
325
|
metadata?: AssetMetadata;
|
|
317
326
|
/** Optional control asset id required for future reissuance. */
|
|
@@ -325,7 +334,7 @@ export type AssetDetails = {
|
|
|
325
334
|
*/
|
|
326
335
|
export interface IssuanceParams {
|
|
327
336
|
/** Initial amount of asset to issue */
|
|
328
|
-
amount:
|
|
337
|
+
amount: bigint;
|
|
329
338
|
/** Optional control asset ID that can be used for future reissuance */
|
|
330
339
|
controlAssetId?: string;
|
|
331
340
|
/** Immutable asset metadata including `ticker`, `decimals`, `icon` */
|
|
@@ -352,7 +361,7 @@ export interface ReissuanceParams {
|
|
|
352
361
|
/** Existing asset ID, made up of genesis (Arkade) transaction ID and zero-based asset group index */
|
|
353
362
|
assetId: string;
|
|
354
363
|
/** Amount of asset to issue */
|
|
355
|
-
amount:
|
|
364
|
+
amount: bigint;
|
|
356
365
|
}
|
|
357
366
|
/**
|
|
358
367
|
* Parameters accepted by `IAssetManager.burn`.
|
|
@@ -363,7 +372,7 @@ export interface BurnParams {
|
|
|
363
372
|
/** Existing asset ID, made up of genesis (Arkade) transaction ID and zero-based asset group index */
|
|
364
373
|
assetId: string;
|
|
365
374
|
/** Amount of asset to burn */
|
|
366
|
-
amount:
|
|
375
|
+
amount: bigint;
|
|
367
376
|
}
|
|
368
377
|
/**
|
|
369
378
|
* Explicit inputs and outputs accepted by `IWallet.settle`.
|
|
@@ -39,7 +39,7 @@ export declare class OnchainWallet implements AnchorBumper {
|
|
|
39
39
|
* @defaultValue `provider = new EsploraProvider('https://mempool.space/api')`
|
|
40
40
|
* @throws Error if the configured identity cannot produce a valid x-only public key
|
|
41
41
|
*/
|
|
42
|
-
static create(identity: Identity, networkName
|
|
42
|
+
static create(identity: Identity, networkName?: NetworkName, provider?: OnchainProvider): Promise<OnchainWallet>;
|
|
43
43
|
get address(): string;
|
|
44
44
|
/**
|
|
45
45
|
* Fetch spendable onchain outputs for the wallet address.
|
|
@@ -45,7 +45,7 @@ interface ServiceWorkerWalletOptions {
|
|
|
45
45
|
/** Optional Arkade server public key used to construct and validate Arkade addresses. */
|
|
46
46
|
arkServerPublicKey?: string;
|
|
47
47
|
/** Base URL of the Arkade server. */
|
|
48
|
-
arkServerUrl
|
|
48
|
+
arkServerUrl?: string;
|
|
49
49
|
/** Optional override for the indexer URL. */
|
|
50
50
|
indexerUrl?: string;
|
|
51
51
|
/** Optional override for the Esplora API URL. */
|
|
@@ -19,6 +19,9 @@ import { DelegatorProvider } from "../providers/delegator";
|
|
|
19
19
|
import { DelegateVtxo } from "../script/delegate";
|
|
20
20
|
import { IDelegatorManager } from "./delegator";
|
|
21
21
|
import { ContractManager } from "../contracts/contractManager";
|
|
22
|
+
export declare const getArkadeServerUrl: ({ arkServerUrl, }: {
|
|
23
|
+
arkServerUrl?: string;
|
|
24
|
+
}) => string;
|
|
22
25
|
export type IncomingFunds = {
|
|
23
26
|
type: "utxo";
|
|
24
27
|
coins: Coin[];
|
|
@@ -321,7 +324,7 @@ export declare class Wallet extends ReadonlyWallet implements IWallet {
|
|
|
321
324
|
* const txid = await wallet.send({
|
|
322
325
|
* address: 'ark1q...',
|
|
323
326
|
* amount: 1000, // (optional, default to dust) btc amount to send to the output
|
|
324
|
-
* assets: [{ assetId: 'abc123...', amount:
|
|
327
|
+
* assets: [{ assetId: 'abc123...', amount: 50n }] // (optional) list of assets to send
|
|
325
328
|
* });
|
|
326
329
|
* ```
|
|
327
330
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkade-os/sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.23",
|
|
4
4
|
"description": "TypeScript SDK for building Bitcoin wallets using the Arkade protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -109,9 +109,9 @@
|
|
|
109
109
|
"peerDependencies": {
|
|
110
110
|
"@react-native-async-storage/async-storage": ">=1.0.0",
|
|
111
111
|
"expo": ">=54.0.0",
|
|
112
|
-
"expo-background-task": "~1.0.10",
|
|
113
|
-
"expo-sqlite": "~16.0.10",
|
|
114
|
-
"expo-task-manager": "~14.0.9"
|
|
112
|
+
"expo-background-task": "~1.0.10 || >=55.0.0",
|
|
113
|
+
"expo-sqlite": "~16.0.10 || >=55.0.0",
|
|
114
|
+
"expo-task-manager": "~14.0.9 || >=55.0.0"
|
|
115
115
|
},
|
|
116
116
|
"peerDependenciesMeta": {
|
|
117
117
|
"expo": {
|