@arkade-os/sdk 0.3.0-alpha.7 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +99 -14
  2. package/dist/cjs/adapters/expo.js +8 -0
  3. package/dist/cjs/arknote/index.js +3 -3
  4. package/dist/cjs/forfeit.js +2 -2
  5. package/dist/cjs/identity/singleKey.js +8 -8
  6. package/dist/cjs/index.js +14 -5
  7. package/dist/cjs/{bip322 → intent}/index.js +38 -61
  8. package/dist/cjs/musig2/index.js +2 -1
  9. package/dist/cjs/musig2/nonces.js +4 -0
  10. package/dist/cjs/providers/ark.js +76 -45
  11. package/dist/cjs/providers/errors.js +59 -0
  12. package/dist/cjs/providers/expoArk.js +82 -0
  13. package/dist/cjs/providers/expoIndexer.js +105 -0
  14. package/dist/cjs/providers/expoUtils.js +124 -0
  15. package/dist/cjs/providers/indexer.js +3 -1
  16. package/dist/cjs/providers/onchain.js +19 -20
  17. package/dist/cjs/repositories/walletRepository.js +64 -28
  18. package/dist/cjs/script/base.js +15 -7
  19. package/dist/cjs/script/tapscript.js +20 -21
  20. package/dist/cjs/script/vhtlc.js +2 -2
  21. package/dist/cjs/tree/signingSession.js +44 -11
  22. package/dist/cjs/tree/txTree.js +3 -4
  23. package/dist/cjs/tree/validation.js +2 -3
  24. package/dist/cjs/utils/arkTransaction.js +118 -15
  25. package/dist/cjs/utils/transaction.js +28 -0
  26. package/dist/cjs/utils/unknownFields.js +7 -7
  27. package/dist/cjs/wallet/index.js +1 -1
  28. package/dist/cjs/wallet/onchain.js +6 -7
  29. package/dist/cjs/wallet/serviceWorker/response.js +32 -0
  30. package/dist/cjs/wallet/serviceWorker/utils.js +2 -9
  31. package/dist/cjs/wallet/serviceWorker/wallet.js +7 -8
  32. package/dist/cjs/wallet/serviceWorker/worker.js +48 -32
  33. package/dist/cjs/wallet/unroll.js +7 -9
  34. package/dist/cjs/wallet/utils.js +20 -0
  35. package/dist/cjs/wallet/vtxo-manager.js +323 -0
  36. package/dist/cjs/wallet/wallet.js +165 -174
  37. package/dist/esm/adapters/expo.js +3 -0
  38. package/dist/esm/arknote/index.js +2 -2
  39. package/dist/esm/forfeit.js +1 -1
  40. package/dist/esm/identity/singleKey.js +9 -9
  41. package/dist/esm/index.js +14 -10
  42. package/dist/esm/{bip322 → intent}/index.js +32 -54
  43. package/dist/esm/musig2/index.js +1 -1
  44. package/dist/esm/musig2/nonces.js +3 -0
  45. package/dist/esm/providers/ark.js +76 -45
  46. package/dist/esm/providers/errors.js +54 -0
  47. package/dist/esm/providers/expoArk.js +78 -0
  48. package/dist/esm/providers/expoIndexer.js +101 -0
  49. package/dist/esm/providers/expoUtils.js +87 -0
  50. package/dist/esm/providers/indexer.js +3 -1
  51. package/dist/esm/providers/onchain.js +19 -20
  52. package/dist/esm/repositories/walletRepository.js +64 -28
  53. package/dist/esm/script/base.js +12 -4
  54. package/dist/esm/script/tapscript.js +1 -2
  55. package/dist/esm/script/vhtlc.js +1 -1
  56. package/dist/esm/tree/signingSession.js +45 -12
  57. package/dist/esm/tree/txTree.js +3 -4
  58. package/dist/esm/tree/validation.js +2 -3
  59. package/dist/esm/utils/arkTransaction.js +110 -9
  60. package/dist/esm/utils/transaction.js +24 -0
  61. package/dist/esm/utils/unknownFields.js +3 -3
  62. package/dist/esm/wallet/index.js +1 -1
  63. package/dist/esm/wallet/onchain.js +3 -4
  64. package/dist/esm/wallet/serviceWorker/response.js +32 -0
  65. package/dist/esm/wallet/serviceWorker/utils.js +1 -8
  66. package/dist/esm/wallet/serviceWorker/wallet.js +8 -9
  67. package/dist/esm/wallet/serviceWorker/worker.js +49 -33
  68. package/dist/esm/wallet/unroll.js +5 -7
  69. package/dist/esm/wallet/utils.js +16 -0
  70. package/dist/esm/wallet/vtxo-manager.js +317 -0
  71. package/dist/esm/wallet/wallet.js +159 -168
  72. package/dist/types/adapters/expo.d.ts +4 -0
  73. package/dist/types/arknote/index.d.ts +1 -1
  74. package/dist/types/forfeit.d.ts +2 -2
  75. package/dist/types/identity/index.d.ts +2 -2
  76. package/dist/types/identity/singleKey.d.ts +2 -2
  77. package/dist/types/index.d.ts +11 -9
  78. package/dist/types/intent/index.d.ts +41 -0
  79. package/dist/types/musig2/index.d.ts +1 -1
  80. package/dist/types/musig2/nonces.d.ts +1 -0
  81. package/dist/types/providers/ark.d.ts +197 -27
  82. package/dist/types/providers/errors.d.ts +13 -0
  83. package/dist/types/providers/expoArk.d.ts +22 -0
  84. package/dist/types/providers/expoIndexer.d.ts +18 -0
  85. package/dist/types/providers/expoUtils.d.ts +18 -0
  86. package/dist/types/providers/indexer.d.ts +8 -8
  87. package/dist/types/providers/onchain.d.ts +6 -2
  88. package/dist/types/repositories/walletRepository.d.ts +9 -5
  89. package/dist/types/script/base.d.ts +5 -2
  90. package/dist/types/tree/signingSession.d.ts +16 -11
  91. package/dist/types/utils/anchor.d.ts +2 -2
  92. package/dist/types/utils/arkTransaction.d.ts +15 -5
  93. package/dist/types/utils/transaction.d.ts +13 -0
  94. package/dist/types/utils/unknownFields.d.ts +4 -4
  95. package/dist/types/wallet/index.d.ts +47 -7
  96. package/dist/types/wallet/onchain.d.ts +1 -1
  97. package/dist/types/wallet/serviceWorker/response.d.ts +16 -2
  98. package/dist/types/wallet/serviceWorker/utils.d.ts +1 -2
  99. package/dist/types/wallet/serviceWorker/wallet.d.ts +2 -2
  100. package/dist/types/wallet/serviceWorker/worker.d.ts +7 -1
  101. package/dist/types/wallet/unroll.d.ts +1 -1
  102. package/dist/types/wallet/utils.d.ts +3 -0
  103. package/dist/types/wallet/vtxo-manager.d.ts +179 -0
  104. package/dist/types/wallet/wallet.d.ts +17 -5
  105. package/package.json +11 -3
  106. package/dist/cjs/bip322/errors.js +0 -13
  107. package/dist/esm/bip322/errors.js +0 -9
  108. package/dist/types/bip322/errors.d.ts +0 -6
  109. package/dist/types/bip322/index.d.ts +0 -57
@@ -1,12 +1,11 @@
1
- import { Transaction } from "@scure/btc-signer/transaction.js";
2
- import { VirtualCoin } from "../wallet";
1
+ import { TransactionOutput } from "@scure/btc-signer/psbt.js";
2
+ import { ExtendedCoin, VirtualCoin } from "../wallet";
3
+ import { RelativeTimelock } from "../script/tapscript";
3
4
  import { EncodedVtxoScript, TapLeafScript } from "../script/base";
4
5
  import { CSVMultisigTapscript } from "../script/tapscript";
5
- import { TransactionOutput } from "@scure/btc-signer/psbt.js";
6
- import { Bytes } from "@scure/btc-signer/utils.js";
6
+ import { Transaction } from "./transaction";
7
7
  export type ArkTxInput = {
8
8
  tapLeafScript: TapLeafScript;
9
- checkpointTapLeafScript?: Bytes;
10
9
  } & EncodedVtxoScript & Pick<VirtualCoin, "txid" | "vout" | "value">;
11
10
  export type OffchainTx = {
12
11
  arkTx: Transaction;
@@ -25,3 +24,14 @@ export type OffchainTx = {
25
24
  * @returns Object containing the virtual transaction and checkpoint transactions
26
25
  */
27
26
  export declare function buildOffchainTx(inputs: ArkTxInput[], outputs: TransactionOutput[], serverUnrollScript: CSVMultisigTapscript.Type): OffchainTx;
27
+ export declare function hasBoardingTxExpired(coin: ExtendedCoin, boardingTimelock: RelativeTimelock): boolean;
28
+ /**
29
+ * Verify tapscript signatures on a transaction input
30
+ * @param tx Transaction to verify
31
+ * @param inputIndex Index of the input to verify
32
+ * @param requiredSigners List of required signer pubkeys (hex encoded)
33
+ * @param excludePubkeys List of pubkeys to exclude from verification (hex encoded, e.g., server key not yet signed)
34
+ * @param allowedSighashTypes List of allowed sighash types (defaults to [SigHash.DEFAULT])
35
+ * @throws Error if verification fails
36
+ */
37
+ export declare function verifyTapscriptSignatures(tx: Transaction, inputIndex: number, requiredSigners: string[], excludePubkeys?: string[], allowedSighashTypes?: number[]): void;
@@ -0,0 +1,13 @@
1
+ import { Transaction as BtcSignerTransaction } from "@scure/btc-signer";
2
+ import { TxOpts } from "@scure/btc-signer/transaction";
3
+ import { Bytes } from "@scure/btc-signer/utils";
4
+ /**
5
+ * Transaction is a wrapper around the @scure/btc-signer Transaction class.
6
+ * It adds the Ark protocol specific options to the transaction.
7
+ */
8
+ export declare class Transaction extends BtcSignerTransaction {
9
+ static ARK_TX_OPTS: TxOpts;
10
+ constructor(opts?: TxOpts);
11
+ static fromPSBT(psbt_: Bytes, opts?: TxOpts): Transaction;
12
+ static fromRaw(raw: Bytes, opts?: TxOpts): Transaction;
13
+ }
@@ -1,5 +1,5 @@
1
- import { Transaction } from "@scure/btc-signer/transaction.js";
2
- import { TransactionInputUpdate } from "@scure/btc-signer/psbt";
1
+ import { Transaction } from "@scure/btc-signer";
2
+ import { TransactionInputUpdate } from "@scure/btc-signer/psbt.js";
3
3
  /**
4
4
  * ArkPsbtFieldKey is the key values for ark psbt fields.
5
5
  */
@@ -11,9 +11,9 @@ export declare enum ArkPsbtFieldKey {
11
11
  }
12
12
  /**
13
13
  * ArkPsbtFieldKeyType is the type of the ark psbt field key.
14
- * Every ark psbt field has key type 255.
14
+ * Every ark psbt field has key type 222.
15
15
  */
16
- export declare const ArkPsbtFieldKeyType = 255;
16
+ export declare const ArkPsbtFieldKeyType = 222;
17
17
  /**
18
18
  * ArkPsbtFieldCoder is the coder for the ark psbt fields.
19
19
  * each type has its own coder.
@@ -1,25 +1,64 @@
1
- import { Output, SettlementEvent } from "../providers/ark";
1
+ import { Bytes } from "@scure/btc-signer/utils.js";
2
+ import { ArkProvider, Output, SettlementEvent } from "../providers/ark";
2
3
  import { Identity } from "../identity";
3
4
  import { RelativeTimelock } from "../script/tapscript";
4
5
  import { EncodedVtxoScript, TapLeafScript } from "../script/base";
5
- import { Bytes } from "@scure/btc-signer/utils.js";
6
6
  import { StorageAdapter } from "../storage";
7
+ import { RenewalConfig } from "./vtxo-manager";
8
+ import { IndexerProvider } from "../providers/indexer";
9
+ import { OnchainProvider } from "../providers/onchain";
7
10
  /**
8
11
  * Configuration options for wallet initialization.
9
12
  *
10
- * Defines the parameters required to create and configure a wallet instance,
11
- * including identity, server URLs, and optional timelock settings.
12
- * If optional parameters are not provided, the wallet will fetch them from the
13
- * Ark server.
13
+ * Supports two configuration modes:
14
+ * 1. URL-based: Provide arkServerUrl, indexerUrl (optional), and esploraUrl
15
+ * 2. Provider-based: Provide arkProvider, indexerProvider, and onchainProvider instances
16
+ *
17
+ * At least one of the following must be provided:
18
+ * - arkServerUrl OR arkProvider
19
+ *
20
+ * The wallet will use provided URLs to create default providers if custom provider
21
+ * instances are not supplied. If optional parameters are not provided, the wallet
22
+ * will fetch configuration from the Ark server.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // URL-based configuration
27
+ * const wallet = await Wallet.create({
28
+ * identity: SingleKey.fromHex('...'),
29
+ * arkServerUrl: 'https://ark.example.com',
30
+ * esploraUrl: 'https://mempool.space/api'
31
+ * });
32
+ *
33
+ * // Provider-based configuration (e.g., for Expo/React Native)
34
+ * const wallet = await Wallet.create({
35
+ * identity: SingleKey.fromHex('...'),
36
+ * arkProvider: new ExpoArkProvider('https://ark.example.com'),
37
+ * indexerProvider: new ExpoIndexerProvider('https://ark.example.com'),
38
+ * onchainProvider: new EsploraProvider('https://mempool.space/api')
39
+ * });
40
+ * ```
14
41
  */
15
42
  export interface WalletConfig {
16
43
  identity: Identity;
17
- arkServerUrl: string;
44
+ arkServerUrl?: string;
45
+ indexerUrl?: string;
18
46
  esploraUrl?: string;
19
47
  arkServerPublicKey?: string;
20
48
  boardingTimelock?: RelativeTimelock;
21
49
  exitTimelock?: RelativeTimelock;
22
50
  storage?: StorageAdapter;
51
+ arkProvider?: ArkProvider;
52
+ indexerProvider?: IndexerProvider;
53
+ onchainProvider?: OnchainProvider;
54
+ renewalConfig?: RenewalConfig;
55
+ }
56
+ /**
57
+ * Provider class constructor interface for dependency injection.
58
+ * Ensures provider classes follow the consistent constructor pattern.
59
+ */
60
+ export interface ProviderClass<T> {
61
+ new (serverUrl: string): T;
23
62
  }
24
63
  export interface WalletBalance {
25
64
  boarding: {
@@ -73,6 +112,7 @@ export interface VirtualCoin extends Coin {
73
112
  arkTxId?: string;
74
113
  createdAt: Date;
75
114
  isUnrolled: boolean;
115
+ isSpent?: boolean;
76
116
  }
77
117
  export declare enum TxType {
78
118
  TxSent = "SENT",
@@ -3,8 +3,8 @@ import { Coin, SendBitcoinParams } from ".";
3
3
  import { Identity } from "../identity";
4
4
  import { Network, NetworkName } from "../networks";
5
5
  import { OnchainProvider } from "../providers/onchain";
6
- import { Transaction } from "@scure/btc-signer/transaction.js";
7
6
  import { AnchorBumper } from "../utils/anchor";
7
+ import { Transaction } from "../utils/transaction";
8
8
  /**
9
9
  * Onchain Bitcoin wallet implementation for traditional Bitcoin transactions.
10
10
  *
@@ -1,10 +1,11 @@
1
- import { WalletBalance, VirtualCoin, ArkTransaction, IWallet } from "..";
1
+ import { WalletBalance, VirtualCoin, ArkTransaction, IWallet, Coin } from "..";
2
+ import { ExtendedVirtualCoin } from "../..";
2
3
  import { SettlementEvent } from "../../providers/ark";
3
4
  /**
4
5
  * Response is the namespace that contains the response types for the service worker.
5
6
  */
6
7
  export declare namespace Response {
7
- type Type = "WALLET_INITIALIZED" | "WALLET_RELOADED" | "SETTLE_EVENT" | "SETTLE_SUCCESS" | "ADDRESS" | "BOARDING_ADDRESS" | "BALANCE" | "VTXOS" | "VIRTUAL_COINS" | "BOARDING_UTXOS" | "SEND_BITCOIN_SUCCESS" | "TRANSACTION_HISTORY" | "WALLET_STATUS" | "ERROR" | "CLEAR_RESPONSE";
8
+ type Type = "WALLET_INITIALIZED" | "WALLET_RELOADED" | "SETTLE_EVENT" | "SETTLE_SUCCESS" | "ADDRESS" | "BOARDING_ADDRESS" | "BALANCE" | "VTXOS" | "VIRTUAL_COINS" | "BOARDING_UTXOS" | "SEND_BITCOIN_SUCCESS" | "TRANSACTION_HISTORY" | "WALLET_STATUS" | "ERROR" | "CLEAR_RESPONSE" | "VTXO_UPDATE" | "UTXO_UPDATE";
8
9
  interface Base {
9
10
  type: Type;
10
11
  success: boolean;
@@ -106,4 +107,17 @@ export declare namespace Response {
106
107
  }
107
108
  function isWalletReloaded(response: Base): response is WalletReloaded;
108
109
  function walletReloaded(id: string, success: boolean): WalletReloaded;
110
+ interface VtxoUpdate extends Base {
111
+ type: "VTXO_UPDATE";
112
+ spentVtxos: ExtendedVirtualCoin[];
113
+ newVtxos: ExtendedVirtualCoin[];
114
+ }
115
+ function isVtxoUpdate(response: Base): response is VtxoUpdate;
116
+ function vtxoUpdate(newVtxos: ExtendedVirtualCoin[], spentVtxos: ExtendedVirtualCoin[]): VtxoUpdate;
117
+ interface UtxoUpdate extends Base {
118
+ type: "UTXO_UPDATE";
119
+ coins: Coin[];
120
+ }
121
+ function isUtxoUpdate(response: Base): response is UtxoUpdate;
122
+ function utxoUpdate(coins: Coin[]): UtxoUpdate;
109
123
  }
@@ -1,4 +1,4 @@
1
- import { ExtendedVirtualCoin, VirtualCoin, Wallet } from "../..";
1
+ export declare const DEFAULT_DB_NAME = "arkade-service-worker";
2
2
  /**
3
3
  * setupServiceWorker sets up the service worker.
4
4
  * @param path - the path to the service worker script
@@ -8,4 +8,3 @@ import { ExtendedVirtualCoin, VirtualCoin, Wallet } from "../..";
8
8
  * ```
9
9
  */
10
10
  export declare function setupServiceWorker(path: string): Promise<ServiceWorker>;
11
- export declare function extendVirtualCoin(wallet: Wallet, vtxo: VirtualCoin): ExtendedVirtualCoin;
@@ -2,7 +2,6 @@ import { IWallet, WalletBalance, SendBitcoinParams, SettleParams, ArkTransaction
2
2
  import { Response } from "./response";
3
3
  import { SettlementEvent } from "../../providers/ark";
4
4
  import { Identity } from "../../identity";
5
- import { StorageAdapter } from "../../storage";
6
5
  import { WalletRepository } from "../../repositories/walletRepository";
7
6
  import { ContractRepository } from "../../repositories/contractRepository";
8
7
  export type PrivateKeyIdentity = Identity & {
@@ -44,8 +43,9 @@ interface ServiceWorkerWalletOptions {
44
43
  arkServerPublicKey?: string;
45
44
  arkServerUrl: string;
46
45
  esploraUrl?: string;
46
+ dbName?: string;
47
+ dbVersion?: number;
47
48
  identity: PrivateKeyIdentity;
48
- storage?: StorageAdapter;
49
49
  }
50
50
  export type ServiceWorkerWalletCreateOptions = ServiceWorkerWalletOptions & {
51
51
  serviceWorker: ServiceWorker;
@@ -3,6 +3,8 @@
3
3
  * it aims to be run in a service worker context
4
4
  */
5
5
  export declare class Worker {
6
+ readonly dbName: string;
7
+ readonly dbVersion: number;
6
8
  private readonly messageCallback;
7
9
  private wallet;
8
10
  private arkProvider;
@@ -10,7 +12,7 @@ export declare class Worker {
10
12
  private incomingFundsSubscription;
11
13
  private walletRepository;
12
14
  private storage;
13
- constructor(messageCallback?: (message: ExtendableMessageEvent) => void);
15
+ constructor(dbName?: string, dbVersion?: number, messageCallback?: (message: ExtendableMessageEvent) => void);
14
16
  /**
15
17
  * Get spendable vtxos for the current wallet address
16
18
  */
@@ -23,6 +25,10 @@ export declare class Worker {
23
25
  * Get all vtxos categorized by type
24
26
  */
25
27
  private getAllVtxos;
28
+ /**
29
+ * Get all boarding utxos from wallet repository
30
+ */
31
+ private getAllBoardingUtxos;
26
32
  start(withServiceWorkerUpdate?: boolean): Promise<void>;
27
33
  clear(): Promise<void>;
28
34
  reload(): Promise<void>;
@@ -1,9 +1,9 @@
1
- import { Transaction } from "@scure/btc-signer/transaction.js";
2
1
  import { ChainTx, IndexerProvider } from "../providers/indexer";
3
2
  import { AnchorBumper } from "../utils/anchor";
4
3
  import { OnchainProvider } from "../providers/onchain";
5
4
  import { Outpoint } from ".";
6
5
  import { Wallet } from "./wallet";
6
+ import { Transaction } from "../utils/transaction";
7
7
  export declare namespace Unroll {
8
8
  enum StepType {
9
9
  UNROLL = 0,
@@ -0,0 +1,3 @@
1
+ import type { Coin, ExtendedCoin, ExtendedVirtualCoin, VirtualCoin, Wallet } from "..";
2
+ export declare function extendVirtualCoin(wallet: Wallet, vtxo: VirtualCoin): ExtendedVirtualCoin;
3
+ export declare function extendCoin(wallet: Wallet, utxo: Coin): ExtendedCoin;
@@ -0,0 +1,179 @@
1
+ import { ExtendedVirtualCoin, IWallet } from ".";
2
+ import { SettlementEvent } from "../providers/ark";
3
+ /**
4
+ * Configuration options for automatic VTXO renewal
5
+ */
6
+ export interface RenewalConfig {
7
+ /**
8
+ * Enable automatic renewal monitoring
9
+ * @default false
10
+ */
11
+ enabled?: boolean;
12
+ /**
13
+ * Percentage of expiry time to use as threshold (0-100)
14
+ * E.g., 10 means renew when 10% of time until expiry remains
15
+ * @default 10
16
+ */
17
+ thresholdPercentage?: number;
18
+ }
19
+ /**
20
+ * Default renewal configuration values
21
+ */
22
+ export declare const DEFAULT_RENEWAL_CONFIG: Required<Omit<RenewalConfig, "enabled">>;
23
+ /**
24
+ * Check if a VTXO is expiring soon based on threshold
25
+ *
26
+ * @param vtxo - The virtual coin to check
27
+ * @param thresholdMs - Threshold in milliseconds from now
28
+ * @returns true if VTXO expires within threshold, false otherwise
29
+ */
30
+ export declare function isVtxoExpiringSoon(vtxo: ExtendedVirtualCoin, percentage: number): boolean;
31
+ /**
32
+ * Filter VTXOs that are expiring soon or are recoverable/subdust
33
+ *
34
+ * @param vtxos - Array of virtual coins to check
35
+ * @param thresholdMs - Threshold in milliseconds from now
36
+ * @param dustAmount - Dust threshold amount in satoshis
37
+ * @returns Array of VTXOs expiring within threshold
38
+ */
39
+ export declare function getExpiringAndRecoverableVtxos(vtxos: ExtendedVirtualCoin[], percentage: number, dustAmount: bigint): ExtendedVirtualCoin[];
40
+ /**
41
+ * VtxoManager is a unified class for managing VTXO lifecycle operations including
42
+ * recovery of swept/expired VTXOs and renewal to prevent expiration.
43
+ *
44
+ * Key Features:
45
+ * - **Recovery**: Reclaim swept or expired VTXOs back to the wallet
46
+ * - **Renewal**: Refresh VTXO expiration time before they expire
47
+ * - **Smart subdust handling**: Automatically includes subdust VTXOs when economically viable
48
+ * - **Expiry monitoring**: Check for VTXOs that are expiring soon
49
+ *
50
+ * VTXOs become recoverable when:
51
+ * - The Ark server sweeps them (virtualStatus.state === "swept") and they remain spendable
52
+ * - They are preconfirmed subdust (to consolidate small amounts without locking liquidity on settled VTXOs)
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Initialize with renewal config
57
+ * const manager = new VtxoManager(wallet, {
58
+ * enabled: true,
59
+ * thresholdPercentage: 10
60
+ * });
61
+ *
62
+ * // Check recoverable balance
63
+ * const balance = await manager.getRecoverableBalance();
64
+ * if (balance.recoverable > 0n) {
65
+ * console.log(`Can recover ${balance.recoverable} sats`);
66
+ * const txid = await manager.recoverVtxos();
67
+ * }
68
+ *
69
+ * // Check for expiring VTXOs
70
+ * const expiring = await manager.getExpiringVtxos();
71
+ * if (expiring.length > 0) {
72
+ * console.log(`${expiring.length} VTXOs expiring soon`);
73
+ * const txid = await manager.renewVtxos();
74
+ * }
75
+ * ```
76
+ */
77
+ export declare class VtxoManager {
78
+ readonly wallet: IWallet;
79
+ readonly renewalConfig?: RenewalConfig | undefined;
80
+ constructor(wallet: IWallet, renewalConfig?: RenewalConfig | undefined);
81
+ /**
82
+ * Recover swept/expired VTXOs by settling them back to the wallet's Ark address.
83
+ *
84
+ * This method:
85
+ * 1. Fetches all VTXOs (including recoverable ones)
86
+ * 2. Filters for swept but still spendable VTXOs and preconfirmed subdust
87
+ * 3. Includes subdust VTXOs if the total value >= dust threshold
88
+ * 4. Settles everything back to the wallet's Ark address
89
+ *
90
+ * Note: Settled VTXOs with long expiry are NOT recovered to avoid locking liquidity unnecessarily.
91
+ * Only preconfirmed subdust is recovered to consolidate small amounts.
92
+ *
93
+ * @param eventCallback - Optional callback to receive settlement events
94
+ * @returns Settlement transaction ID
95
+ * @throws Error if no recoverable VTXOs found
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const manager = new VtxoManager(wallet);
100
+ *
101
+ * // Simple recovery
102
+ * const txid = await manager.recoverVtxos();
103
+ *
104
+ * // With event callback
105
+ * const txid = await manager.recoverVtxos((event) => {
106
+ * console.log('Settlement event:', event.type);
107
+ * });
108
+ * ```
109
+ */
110
+ recoverVtxos(eventCallback?: (event: SettlementEvent) => void): Promise<string>;
111
+ /**
112
+ * Get information about recoverable balance without executing recovery.
113
+ *
114
+ * Useful for displaying to users before they decide to recover funds.
115
+ *
116
+ * @returns Object containing recoverable amounts and subdust information
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * const manager = new VtxoManager(wallet);
121
+ * const balance = await manager.getRecoverableBalance();
122
+ *
123
+ * if (balance.recoverable > 0n) {
124
+ * console.log(`You can recover ${balance.recoverable} sats`);
125
+ * if (balance.includesSubdust) {
126
+ * console.log(`This includes ${balance.subdust} sats from subdust VTXOs`);
127
+ * }
128
+ * }
129
+ * ```
130
+ */
131
+ getRecoverableBalance(): Promise<{
132
+ recoverable: bigint;
133
+ subdust: bigint;
134
+ includesSubdust: boolean;
135
+ vtxoCount: number;
136
+ }>;
137
+ /**
138
+ * Get VTXOs that are expiring soon based on renewal configuration
139
+ *
140
+ * @param thresholdPercentage - Optional override for threshold percentage (0-100)
141
+ * @returns Array of expiring VTXOs, empty array if renewal is disabled or no VTXOs expiring
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * const manager = new VtxoManager(wallet, { enabled: true, thresholdPercentage: 10 });
146
+ * const expiringVtxos = await manager.getExpiringVtxos();
147
+ * if (expiringVtxos.length > 0) {
148
+ * console.log(`${expiringVtxos.length} VTXOs expiring soon`);
149
+ * }
150
+ * ```
151
+ */
152
+ getExpiringVtxos(thresholdPercentage?: number): Promise<ExtendedVirtualCoin[]>;
153
+ /**
154
+ * Renew expiring VTXOs by settling them back to the wallet's address
155
+ *
156
+ * This method collects all expiring spendable VTXOs (including recoverable ones) and settles
157
+ * them back to the wallet, effectively refreshing their expiration time. This is the
158
+ * primary way to prevent VTXOs from expiring.
159
+ *
160
+ * @param eventCallback - Optional callback for settlement events
161
+ * @returns Settlement transaction ID
162
+ * @throws Error if no VTXOs available to renew
163
+ * @throws Error if total amount is below dust threshold
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const manager = new VtxoManager(wallet);
168
+ *
169
+ * // Simple renewal
170
+ * const txid = await manager.renewVtxos();
171
+ *
172
+ * // With event callback
173
+ * const txid = await manager.renewVtxos((event) => {
174
+ * console.log('Settlement event:', event.type);
175
+ * });
176
+ * ```
177
+ */
178
+ renewVtxos(eventCallback?: (event: SettlementEvent) => void): Promise<string>;
179
+ }
@@ -1,3 +1,4 @@
1
+ import { Bytes } from "@scure/btc-signer/utils.js";
1
2
  import { ArkAddress } from "../script/address";
2
3
  import { DefaultVtxo } from "../script/default";
3
4
  import { Network, NetworkName } from "../networks";
@@ -5,7 +6,6 @@ import { OnchainProvider } from "../providers/onchain";
5
6
  import { SettlementEvent, ArkProvider } from "../providers/ark";
6
7
  import { Identity } from "../identity";
7
8
  import { ArkTransaction, Coin, ExtendedCoin, ExtendedVirtualCoin, GetVtxosFilter, IWallet, SendBitcoinParams, SettleParams, WalletBalance, WalletConfig } from ".";
8
- import { Bytes } from "@scure/btc-signer/utils.js";
9
9
  import { CSVMultisigTapscript } from "../script/tapscript";
10
10
  import { IndexerProvider } from "../providers/indexer";
11
11
  import { WalletRepository } from "../repositories/walletRepository";
@@ -25,13 +25,21 @@ export type IncomingFunds = {
25
25
  *
26
26
  * @example
27
27
  * ```typescript
28
- * // Create a wallet
28
+ * // Create a wallet with URL configuration
29
29
  * const wallet = await Wallet.create({
30
30
  * identity: SingleKey.fromHex('your_private_key'),
31
31
  * arkServerUrl: 'https://ark.example.com',
32
32
  * esploraUrl: 'https://mempool.space/api'
33
33
  * });
34
34
  *
35
+ * // Or with custom provider instances (e.g., for Expo/React Native)
36
+ * const wallet = await Wallet.create({
37
+ * identity: SingleKey.fromHex('your_private_key'),
38
+ * arkProvider: new ExpoArkProvider('https://ark.example.com'),
39
+ * indexerProvider: new ExpoIndexerProvider('https://ark.example.com'),
40
+ * esploraUrl: 'https://mempool.space/api'
41
+ * });
42
+ *
35
43
  * // Get addresses
36
44
  * const arkAddress = await wallet.getAddress();
37
45
  * const boardingAddress = await wallet.getBoardingAddress();
@@ -55,10 +63,15 @@ export declare class Wallet implements IWallet {
55
63
  readonly boardingTapscript: DefaultVtxo.Script;
56
64
  readonly serverUnrollScript: CSVMultisigTapscript.Type;
57
65
  readonly forfeitOutputScript: Bytes;
66
+ readonly forfeitPubkey: Bytes;
58
67
  readonly dustAmount: bigint;
59
68
  static MIN_FEE_RATE: number;
60
69
  readonly walletRepository: WalletRepository;
61
70
  readonly contractRepository: ContractRepository;
71
+ readonly renewalConfig: Required<Omit<WalletConfig["renewalConfig"], "enabled">> & {
72
+ enabled: boolean;
73
+ thresholdPercentage: number;
74
+ };
62
75
  private constructor();
63
76
  static create(config: WalletConfig): Promise<Wallet>;
64
77
  get arkAddress(): ArkAddress;
@@ -78,12 +91,11 @@ export declare class Wallet implements IWallet {
78
91
  notifyIncomingFunds(eventCallback: (coins: IncomingFunds) => void): Promise<() => void>;
79
92
  private handleBatchStartedEvent;
80
93
  private handleSettlementSigningEvent;
81
- private handleSettlementSigningNoncesGeneratedEvent;
94
+ private handleSettlementTreeNoncesEvent;
82
95
  private handleSettlementFinalizationEvent;
83
96
  private makeRegisterIntentSignature;
84
97
  private makeDeleteIntentSignature;
85
- private prepareBIP322Inputs;
86
- private makeBIP322Signature;
98
+ private prepareIntentProofInputs;
87
99
  }
88
100
  /**
89
101
  * Wait for incoming funds to the wallet
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkade-os/sdk",
3
- "version": "0.3.0-alpha.7",
3
+ "version": "0.3.0",
4
4
  "description": "Bitcoin wallet SDK with Taproot and Ark integration",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -14,6 +14,12 @@
14
14
  "require": "./dist/cjs/index.js",
15
15
  "default": "./dist/esm/index.js"
16
16
  },
17
+ "./adapters/expo": {
18
+ "types": "./dist/types/adapters/expo.d.ts",
19
+ "import": "./dist/esm/adapters/expo.js",
20
+ "require": "./dist/cjs/adapters/expo.js",
21
+ "default": "./dist/esm/adapters/expo.js"
22
+ },
17
23
  "./adapters/localStorage": {
18
24
  "types": "./dist/types/adapters/localStorage.d.ts",
19
25
  "import": "./dist/esm/adapters/localStorage.js",
@@ -48,7 +54,6 @@
48
54
  },
49
55
  "dependencies": {
50
56
  "@noble/curves": "2.0.0",
51
- "@noble/hashes": "2.0.0",
52
57
  "@noble/secp256k1": "3.0.0",
53
58
  "@scure/base": "2.0.0",
54
59
  "@scure/btc-signer": "2.0.1",
@@ -58,6 +63,7 @@
58
63
  "@types/node": "24.3.1",
59
64
  "@vitest/coverage-v8": "3.2.4",
60
65
  "esbuild": "^0.25.9",
66
+ "expo": "~52.0.47",
61
67
  "eventsource": "4.0.0",
62
68
  "glob": "11.0.3",
63
69
  "husky": "9.1.7",
@@ -78,7 +84,7 @@
78
84
  "author": "Ark Labs",
79
85
  "license": "MIT",
80
86
  "engines": {
81
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
87
+ "node": ">=20.0.0"
82
88
  },
83
89
  "scripts": {
84
90
  "build": "rimraf dist && pnpm run build:esm && node scripts/add-extensions.js && pnpm run build:cjs && pnpm run build:types && node scripts/generate-package-files.js",
@@ -101,6 +107,8 @@
101
107
  "test:watch": "vitest",
102
108
  "test:coverage": "vitest run --coverage",
103
109
  "test:sw": "pnpm run build:browser && node test/serviceWorker/serve.js",
110
+ "expo:web:install": "cd examples/expo-demo && pnpm install",
111
+ "expo:web": "cd examples/expo-demo && pnpm start",
104
112
  "format": "prettier --write src test examples",
105
113
  "lint": "prettier --check src test examples",
106
114
  "audit": "pnpm audit",
@@ -1,13 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ErrMissingWitnessUtxo = exports.ErrMissingData = exports.ErrMissingInputs = exports.BIP322Error = void 0;
4
- class BIP322Error extends Error {
5
- constructor(message) {
6
- super(message);
7
- this.name = "BIP322Error";
8
- }
9
- }
10
- exports.BIP322Error = BIP322Error;
11
- exports.ErrMissingInputs = new BIP322Error("missing inputs");
12
- exports.ErrMissingData = new BIP322Error("missing data");
13
- exports.ErrMissingWitnessUtxo = new BIP322Error("missing witness utxo");
@@ -1,9 +0,0 @@
1
- export class BIP322Error extends Error {
2
- constructor(message) {
3
- super(message);
4
- this.name = "BIP322Error";
5
- }
6
- }
7
- export const ErrMissingInputs = new BIP322Error("missing inputs");
8
- export const ErrMissingData = new BIP322Error("missing data");
9
- export const ErrMissingWitnessUtxo = new BIP322Error("missing witness utxo");
@@ -1,6 +0,0 @@
1
- export declare class BIP322Error extends Error {
2
- constructor(message: string);
3
- }
4
- export declare const ErrMissingInputs: BIP322Error;
5
- export declare const ErrMissingData: BIP322Error;
6
- export declare const ErrMissingWitnessUtxo: BIP322Error;
@@ -1,57 +0,0 @@
1
- import { Transaction } from "@scure/btc-signer/transaction.js";
2
- import { TransactionInput, TransactionOutput } from "@scure/btc-signer/psbt.js";
3
- /**
4
- * BIP-322 signature implementation for Bitcoin message signing.
5
- *
6
- * BIP-322 defines a standard for signing Bitcoin messages as well as proving
7
- * ownership of coins. This namespace provides utilities for creating and
8
- * validating BIP-322.
9
- *
10
- * @see https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki
11
- *
12
- * @example
13
- * ```typescript
14
- * // Create a BIP-322 proof
15
- * const proof = BIP322.create(
16
- * "Hello Bitcoin!",
17
- * [input],
18
- * [output]
19
- * );
20
- *
21
- * // Sign the proof
22
- * const signedProof = await identity.sign(proof);
23
- *
24
- * // Extract the signature
25
- * const signature = BIP322.signature(signedProof);
26
- * ```
27
- */
28
- export declare namespace BIP322 {
29
- type FullProof = Transaction;
30
- type Signature = string;
31
- /**
32
- * Creates a new BIP-322 "full" proof of funds unsigned transaction.
33
- *
34
- * This function constructs a special transaction that can be signed to prove
35
- * ownership of VTXOs and UTXOs. The proof includes the message to be
36
- * signed and the inputs/outputs that demonstrate ownership.
37
- *
38
- * @param message - The BIP-322 message to be signed
39
- * @param inputs - Array of transaction inputs to prove ownership of
40
- * @param outputs - Optional array of transaction outputs
41
- * @returns An unsigned BIP-322 proof transaction
42
- */
43
- function create(message: string, inputs: TransactionInput[], outputs?: TransactionOutput[]): FullProof;
44
- /**
45
- * Finalizes and extracts the FullProof transaction into a BIP-322 signature.
46
- *
47
- * This function takes a signed proof transaction and converts it into a
48
- * base64-encoded signature string. If the proof's inputs have special
49
- * spending conditions, a custom finalizer can be provided.
50
- *
51
- * @param signedProof - The signed BIP-322 proof transaction
52
- * @param finalizer - Optional custom finalizer function
53
- * @returns Base64-encoded BIP-322 signature
54
- */
55
- function signature(signedProof: FullProof, finalizer?: (tx: FullProof) => void): Signature;
56
- }
57
- export declare function craftToSpendTx(message: string, pkScript: Uint8Array): Transaction;