@arkade-os/sdk 0.4.14 → 0.4.16

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 (203) hide show
  1. package/README.md +287 -215
  2. package/dist/cjs/arkfee/estimator.js +1 -1
  3. package/dist/cjs/arkfee/types.js +2 -1
  4. package/dist/cjs/arknote/index.js +43 -4
  5. package/dist/cjs/bip322/index.js +1 -1
  6. package/dist/cjs/contracts/arkcontract.js +1 -1
  7. package/dist/cjs/contracts/contractManager.js +40 -24
  8. package/dist/cjs/contracts/contractWatcher.js +29 -22
  9. package/dist/cjs/contracts/handlers/default.js +1 -1
  10. package/dist/cjs/contracts/handlers/delegate.js +1 -1
  11. package/dist/cjs/contracts/handlers/helpers.js +25 -1
  12. package/dist/cjs/contracts/handlers/vhtlc.js +2 -4
  13. package/dist/cjs/extension/asset/assetGroup.js +92 -5
  14. package/dist/cjs/extension/asset/assetId.js +67 -3
  15. package/dist/cjs/extension/asset/assetInput.js +18 -0
  16. package/dist/cjs/extension/asset/assetOutput.js +15 -0
  17. package/dist/cjs/extension/asset/assetRef.js +66 -0
  18. package/dist/cjs/extension/asset/metadata.js +15 -0
  19. package/dist/cjs/extension/asset/packet.js +4 -1
  20. package/dist/cjs/extension/index.js +1 -1
  21. package/dist/cjs/forfeit.js +14 -0
  22. package/dist/cjs/identity/index.js +6 -0
  23. package/dist/cjs/identity/seedIdentity.js +5 -5
  24. package/dist/cjs/identity/singleKey.js +4 -0
  25. package/dist/cjs/index.js +5 -3
  26. package/dist/cjs/intent/index.js +28 -12
  27. package/dist/cjs/providers/ark.js +3 -2
  28. package/dist/cjs/providers/delegator.js +20 -1
  29. package/dist/cjs/providers/expoArk.js +2 -2
  30. package/dist/cjs/providers/indexer.js +2 -2
  31. package/dist/cjs/providers/onchain.js +2 -1
  32. package/dist/cjs/repositories/realm/schemas.js +2 -2
  33. package/dist/cjs/repositories/realm/types.js +1 -1
  34. package/dist/cjs/script/address.js +37 -6
  35. package/dist/cjs/script/base.js +70 -1
  36. package/dist/cjs/script/default.js +3 -0
  37. package/dist/cjs/script/delegate.js +4 -0
  38. package/dist/cjs/script/tapscript.js +25 -4
  39. package/dist/cjs/script/vhtlc.js +35 -27
  40. package/dist/cjs/storage/fileSystem.js +1 -1
  41. package/dist/cjs/storage/inMemory.js +1 -1
  42. package/dist/cjs/storage/indexedDB.js +1 -1
  43. package/dist/cjs/storage/localStorage.js +1 -1
  44. package/dist/cjs/tree/validation.js +1 -1
  45. package/dist/cjs/utils/arkTransaction.js +5 -5
  46. package/dist/cjs/utils/bip21.js +16 -3
  47. package/dist/cjs/utils/syncCursors.js +4 -4
  48. package/dist/cjs/utils/transaction.js +1 -1
  49. package/dist/cjs/utils/transactionHistory.js +11 -11
  50. package/dist/cjs/utils/unknownFields.js +3 -3
  51. package/dist/cjs/wallet/asset-manager.js +4 -4
  52. package/dist/cjs/wallet/batch.js +5 -5
  53. package/dist/cjs/wallet/delegator.js +9 -8
  54. package/dist/cjs/wallet/expo/background.js +3 -3
  55. package/dist/cjs/wallet/expo/wallet.js +7 -7
  56. package/dist/cjs/wallet/index.js +43 -0
  57. package/dist/cjs/wallet/onchain.js +43 -5
  58. package/dist/cjs/wallet/ramps.js +44 -14
  59. package/dist/cjs/wallet/serviceWorker/wallet-message-handler.js +22 -22
  60. package/dist/cjs/wallet/serviceWorker/wallet.js +28 -24
  61. package/dist/cjs/wallet/unroll.js +12 -8
  62. package/dist/cjs/wallet/utils.js +1 -1
  63. package/dist/cjs/wallet/vtxo-manager.js +123 -82
  64. package/dist/cjs/wallet/wallet.js +231 -98
  65. package/dist/cjs/worker/expo/asyncStorageTaskQueue.js +1 -1
  66. package/dist/cjs/worker/expo/processors/contractPollProcessor.js +2 -2
  67. package/dist/cjs/worker/expo/taskRunner.js +3 -3
  68. package/dist/cjs/worker/messageBus.js +3 -0
  69. package/dist/esm/arkfee/estimator.js +1 -1
  70. package/dist/esm/arkfee/types.js +2 -1
  71. package/dist/esm/arknote/index.js +43 -4
  72. package/dist/esm/bip322/index.js +1 -1
  73. package/dist/esm/contracts/arkcontract.js +1 -1
  74. package/dist/esm/contracts/contractManager.js +40 -24
  75. package/dist/esm/contracts/contractWatcher.js +29 -22
  76. package/dist/esm/contracts/handlers/default.js +1 -1
  77. package/dist/esm/contracts/handlers/delegate.js +1 -1
  78. package/dist/esm/contracts/handlers/helpers.js +24 -1
  79. package/dist/esm/contracts/handlers/vhtlc.js +3 -5
  80. package/dist/esm/extension/asset/assetGroup.js +92 -5
  81. package/dist/esm/extension/asset/assetId.js +67 -3
  82. package/dist/esm/extension/asset/assetInput.js +18 -0
  83. package/dist/esm/extension/asset/assetOutput.js +15 -0
  84. package/dist/esm/extension/asset/assetRef.js +66 -0
  85. package/dist/esm/extension/asset/metadata.js +15 -0
  86. package/dist/esm/extension/asset/packet.js +4 -1
  87. package/dist/esm/extension/index.js +1 -1
  88. package/dist/esm/forfeit.js +14 -0
  89. package/dist/esm/identity/index.js +5 -0
  90. package/dist/esm/identity/seedIdentity.js +5 -5
  91. package/dist/esm/identity/singleKey.js +4 -0
  92. package/dist/esm/index.js +3 -2
  93. package/dist/esm/intent/index.js +28 -12
  94. package/dist/esm/providers/ark.js +3 -2
  95. package/dist/esm/providers/delegator.js +20 -1
  96. package/dist/esm/providers/expoArk.js +2 -2
  97. package/dist/esm/providers/indexer.js +2 -2
  98. package/dist/esm/providers/onchain.js +2 -1
  99. package/dist/esm/repositories/realm/schemas.js +2 -2
  100. package/dist/esm/repositories/realm/types.js +1 -1
  101. package/dist/esm/script/address.js +37 -6
  102. package/dist/esm/script/base.js +70 -1
  103. package/dist/esm/script/default.js +3 -0
  104. package/dist/esm/script/delegate.js +4 -0
  105. package/dist/esm/script/tapscript.js +25 -4
  106. package/dist/esm/script/vhtlc.js +35 -27
  107. package/dist/esm/storage/fileSystem.js +1 -1
  108. package/dist/esm/storage/inMemory.js +1 -1
  109. package/dist/esm/storage/indexedDB.js +1 -1
  110. package/dist/esm/storage/localStorage.js +1 -1
  111. package/dist/esm/tree/validation.js +1 -1
  112. package/dist/esm/utils/arkTransaction.js +5 -5
  113. package/dist/esm/utils/bip21.js +16 -3
  114. package/dist/esm/utils/syncCursors.js +4 -4
  115. package/dist/esm/utils/transaction.js +1 -1
  116. package/dist/esm/utils/transactionHistory.js +11 -11
  117. package/dist/esm/utils/unknownFields.js +3 -3
  118. package/dist/esm/wallet/asset-manager.js +4 -4
  119. package/dist/esm/wallet/batch.js +5 -5
  120. package/dist/esm/wallet/delegator.js +9 -8
  121. package/dist/esm/wallet/expo/background.js +3 -3
  122. package/dist/esm/wallet/expo/wallet.js +7 -7
  123. package/dist/esm/wallet/index.js +43 -0
  124. package/dist/esm/wallet/onchain.js +43 -5
  125. package/dist/esm/wallet/ramps.js +44 -14
  126. package/dist/esm/wallet/serviceWorker/wallet-message-handler.js +22 -22
  127. package/dist/esm/wallet/serviceWorker/wallet.js +28 -24
  128. package/dist/esm/wallet/unroll.js +12 -8
  129. package/dist/esm/wallet/utils.js +1 -1
  130. package/dist/esm/wallet/vtxo-manager.js +122 -81
  131. package/dist/esm/wallet/wallet.js +232 -99
  132. package/dist/esm/worker/expo/asyncStorageTaskQueue.js +1 -1
  133. package/dist/esm/worker/expo/processors/contractPollProcessor.js +2 -2
  134. package/dist/esm/worker/expo/taskRunner.js +3 -3
  135. package/dist/esm/worker/messageBus.js +3 -0
  136. package/dist/types/arkfee/estimator.d.ts +1 -1
  137. package/dist/types/arkfee/types.d.ts +2 -1
  138. package/dist/types/arknote/index.d.ts +44 -4
  139. package/dist/types/bip322/index.d.ts +1 -1
  140. package/dist/types/contracts/arkcontract.d.ts +1 -1
  141. package/dist/types/contracts/contractManager.d.ts +40 -63
  142. package/dist/types/contracts/contractWatcher.d.ts +39 -18
  143. package/dist/types/contracts/handlers/default.d.ts +1 -1
  144. package/dist/types/contracts/handlers/delegate.d.ts +1 -1
  145. package/dist/types/contracts/handlers/helpers.d.ts +11 -1
  146. package/dist/types/contracts/types.d.ts +36 -26
  147. package/dist/types/extension/asset/assetGroup.d.ts +92 -1
  148. package/dist/types/extension/asset/assetId.d.ts +67 -3
  149. package/dist/types/extension/asset/assetInput.d.ts +18 -0
  150. package/dist/types/extension/asset/assetOutput.d.ts +15 -0
  151. package/dist/types/extension/asset/assetRef.d.ts +66 -0
  152. package/dist/types/extension/asset/metadata.d.ts +15 -0
  153. package/dist/types/extension/asset/packet.d.ts +4 -1
  154. package/dist/types/extension/index.d.ts +1 -1
  155. package/dist/types/forfeit.d.ts +14 -0
  156. package/dist/types/identity/index.d.ts +36 -0
  157. package/dist/types/identity/seedIdentity.d.ts +10 -8
  158. package/dist/types/identity/singleKey.d.ts +4 -0
  159. package/dist/types/index.d.ts +3 -3
  160. package/dist/types/intent/index.d.ts +19 -6
  161. package/dist/types/providers/ark.d.ts +40 -2
  162. package/dist/types/providers/delegator.d.ts +54 -1
  163. package/dist/types/providers/expoArk.d.ts +2 -2
  164. package/dist/types/providers/indexer.d.ts +105 -2
  165. package/dist/types/providers/onchain.d.ts +62 -1
  166. package/dist/types/repositories/realm/schemas.d.ts +2 -2
  167. package/dist/types/repositories/realm/types.d.ts +2 -2
  168. package/dist/types/repositories/walletRepository.d.ts +16 -0
  169. package/dist/types/script/address.d.ts +35 -2
  170. package/dist/types/script/base.d.ts +66 -1
  171. package/dist/types/script/default.d.ts +3 -0
  172. package/dist/types/script/delegate.d.ts +4 -0
  173. package/dist/types/script/tapscript.d.ts +17 -2
  174. package/dist/types/script/vhtlc.d.ts +35 -27
  175. package/dist/types/storage/fileSystem.d.ts +1 -1
  176. package/dist/types/storage/inMemory.d.ts +1 -1
  177. package/dist/types/storage/index.d.ts +1 -1
  178. package/dist/types/storage/indexedDB.d.ts +1 -1
  179. package/dist/types/storage/localStorage.d.ts +1 -1
  180. package/dist/types/utils/arkTransaction.d.ts +3 -3
  181. package/dist/types/utils/bip21.d.ts +17 -0
  182. package/dist/types/utils/syncCursors.d.ts +4 -4
  183. package/dist/types/utils/transaction.d.ts +1 -1
  184. package/dist/types/utils/transactionHistory.d.ts +3 -3
  185. package/dist/types/utils/unknownFields.d.ts +5 -5
  186. package/dist/types/wallet/asset-manager.d.ts +3 -3
  187. package/dist/types/wallet/batch.d.ts +27 -7
  188. package/dist/types/wallet/delegator.d.ts +10 -0
  189. package/dist/types/wallet/expo/background.d.ts +4 -4
  190. package/dist/types/wallet/expo/wallet.d.ts +10 -10
  191. package/dist/types/wallet/index.d.ts +457 -25
  192. package/dist/types/wallet/onchain.d.ts +42 -4
  193. package/dist/types/wallet/ramps.d.ts +40 -10
  194. package/dist/types/wallet/serviceWorker/wallet-message-handler.d.ts +4 -4
  195. package/dist/types/wallet/serviceWorker/wallet.d.ts +71 -33
  196. package/dist/types/wallet/unroll.d.ts +8 -6
  197. package/dist/types/wallet/vtxo-manager.d.ts +146 -93
  198. package/dist/types/wallet/wallet.d.ts +91 -33
  199. package/dist/types/worker/expo/asyncStorageTaskQueue.d.ts +1 -1
  200. package/dist/types/worker/expo/processors/contractPollProcessor.d.ts +1 -1
  201. package/dist/types/worker/expo/taskRunner.d.ts +6 -6
  202. package/dist/types/worker/messageBus.d.ts +5 -3
  203. package/package.json +18 -10
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Arkade TypeScript SDK
2
2
 
3
- The Arkade SDK is a TypeScript library for building Bitcoin wallets with support for both on-chain and off-chain transactions via the Ark protocol.
3
+ The Arkade SDK is a TypeScript library for building Bitcoin wallets using the Arkade protocol.
4
4
 
5
- [![TypeScript Documentation](https://img.shields.io/badge/TypeScript-Documentation-blue?style=flat-square)](https://arkade-os.github.io/ts-sdk/)
5
+ [![TypeDoc](https://img.shields.io/badge/TypeScript-Documentation-blue?style=flat-square)](https://arkade-os.github.io/ts-sdk/)
6
6
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/arkade-os/ts-sdk)
7
7
 
8
8
  ## Installation
@@ -19,52 +19,43 @@ npm install @arkade-os/sdk
19
19
  import {
20
20
  MnemonicIdentity,
21
21
  Wallet,
22
- IndexedDBWalletRepository,
23
- IndexedDBContractRepository
24
22
  } from '@arkade-os/sdk'
25
23
  import { generateMnemonic } from '@scure/bip39'
26
24
  import { wordlist } from '@scure/bip39/wordlists/english.js'
27
25
 
28
26
  // Generate a new mnemonic or use an existing one
29
27
  const mnemonic = generateMnemonic(wordlist)
30
- const identity = MnemonicIdentity.fromMnemonic(mnemonic, { isMainnet: false })
28
+ const identity = MnemonicIdentity.fromMnemonic(mnemonic)
31
29
 
32
- // Create a wallet with Ark support
30
+ // Create a wallet with Arkade support
33
31
  const wallet = await Wallet.create({
34
32
  identity,
35
- // Esplora API, can be left empty - mempool.space API will be used
36
- esploraUrl: 'https://mutinynet.com/api',
37
- arkServerUrl: 'https://mutinynet.arkade.sh',
38
- // Optional: provide repositories for persistence (defaults to IndexedDB)
39
- // storage: {
40
- // walletRepository: new IndexedDBWalletRepository('my-wallet-db'),
41
- // contractRepository: new IndexedDBContractRepository('my-wallet-db')
42
- // }
33
+ arkServerUrl: 'https://arkade.computer',
43
34
  })
44
35
  ```
45
36
 
46
- ### Readonly Wallets (Watch-Only)
37
+ ### Read-Only Wallets (Watch-Only)
47
38
 
48
- The SDK supports readonly wallets that allow you to query wallet state without exposing private keys. This is useful for:
39
+ The SDK supports read-only wallets that allow you to query wallet state without exposing private keys. This is useful for:
49
40
 
50
41
  - **Watch-only wallets**: Monitor addresses and balances without transaction capabilities
51
42
  - **Public interfaces**: Display wallet information safely in public-facing applications
52
43
  - **Separate concerns**: Keep signing operations isolated from query operations
53
44
 
54
- #### Creating a Readonly Wallet
45
+ #### Creating a Read-Only Wallet
55
46
 
56
47
  ```typescript
57
- import { ReadonlySingleKey, ReadonlyWallet } from '@arkade-os/sdk'
48
+ import { SingleKey, ReadonlySingleKey, ReadonlyWallet } from '@arkade-os/sdk'
58
49
 
59
- // Create a readonly identity from a public key
60
- const identity = SingleKey.fromHex('your_public_key_hex')
50
+ // Create a read-only identity from a public key
51
+ const identity = SingleKey.fromHex('e09ca...56609')
61
52
  const publicKey = await identity.compressedPublicKey()
62
53
  const readonlyIdentity = ReadonlySingleKey.fromPublicKey(publicKey)
63
54
 
64
- // Create a readonly wallet
55
+ // Create a read-only wallet
65
56
  const readonlyWallet = await ReadonlyWallet.create({
66
57
  identity: readonlyIdentity,
67
- arkServerUrl: 'https://mutinynet.arkade.sh'
58
+ arkServerUrl: 'https://arkade.computer'
68
59
  })
69
60
 
70
61
  // Query operations work normally
@@ -74,43 +65,43 @@ const vtxos = await readonlyWallet.getVtxos()
74
65
  const history = await readonlyWallet.getTransactionHistory()
75
66
 
76
67
  // Transaction methods are not available (TypeScript will prevent this)
77
- // await readonlyWallet.sendBitcoin(...) // ❌ Type error!
68
+ // await readonlyWallet.send(...) // ❌ Type error!
78
69
  ```
79
70
 
80
- #### Converting Wallets to Readonly
71
+ #### Converting Wallets to Read-Only
81
72
 
82
73
  ```typescript
83
- import { Wallet, SingleKey } from '@arkade-os/sdk'
74
+ import { Wallet, MnemonicIdentity } from '@arkade-os/sdk'
84
75
 
85
76
  // Create a full wallet
86
- const identity = SingleKey.fromHex('your_private_key_hex')
77
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
87
78
  const wallet = await Wallet.create({
88
79
  identity,
89
- arkServerUrl: 'https://mutinynet.arkade.sh'
80
+ arkServerUrl: 'https://arkade.computer'
90
81
  })
91
82
 
92
- // Convert to readonly wallet (safe to share)
83
+ // Convert to read-only wallet (safe to share)
93
84
  const readonlyWallet = await wallet.toReadonly()
94
85
 
95
- // The readonly wallet can query but not transact
86
+ // The read-only wallet can query but not transact
96
87
  const balance = await readonlyWallet.getBalance()
97
88
  ```
98
89
 
99
- #### Converting Identity to Readonly
90
+ #### Converting Identity to Read-Only
100
91
 
101
92
  ```typescript
102
- import { SingleKey } from '@arkade-os/sdk'
93
+ import { MnemonicIdentity } from '@arkade-os/sdk'
103
94
 
104
95
  // Full identity
105
- const identity = SingleKey.fromHex('your_private_key_hex')
96
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
106
97
 
107
- // Convert to readonly (no signing capability)
98
+ // Convert to read-only (no signing capability)
108
99
  const readonlyIdentity = await identity.toReadonly()
109
100
 
110
- // Use in readonly wallet
101
+ // Use in read-only wallet
111
102
  const readonlyWallet = await ReadonlyWallet.create({
112
103
  identity: readonlyIdentity,
113
- arkServerUrl: 'https://mutinynet.arkade.sh'
104
+ arkServerUrl: 'https://arkade.computer'
114
105
  })
115
106
  ```
116
107
 
@@ -131,18 +122,17 @@ import { wordlist } from '@scure/bip39/wordlists/english.js'
131
122
  const mnemonic = generateMnemonic(wordlist)
132
123
 
133
124
  // Create identity from a 12 or 24 word mnemonic
134
- const identity = MnemonicIdentity.fromMnemonic(mnemonic, { isMainnet: true })
125
+ const identity = MnemonicIdentity.fromMnemonic(mnemonic)
135
126
 
136
127
  // With optional passphrase for additional security
137
128
  const identityWithPassphrase = MnemonicIdentity.fromMnemonic(mnemonic, {
138
- isMainnet: true,
139
129
  passphrase: 'my secret passphrase'
140
130
  })
141
131
 
142
132
  // Create wallet as usual
143
133
  const wallet = await Wallet.create({
144
- identity,
145
- arkServerUrl: 'https://mutinynet.arkade.sh'
134
+ identity: identityWithPassphrase,
135
+ arkServerUrl: 'https://arkade.computer'
146
136
  })
147
137
  ```
148
138
 
@@ -154,13 +144,13 @@ import { mnemonicToSeedSync } from '@scure/bip39'
154
144
 
155
145
  // If you already have a 64-byte seed
156
146
  const seed = mnemonicToSeedSync(mnemonic)
157
- const identity = SeedIdentity.fromSeed(seed, { isMainnet: true })
147
+ const identity = SeedIdentity.fromSeed(seed)
158
148
 
159
149
  // Or with a custom output descriptor
160
- const identity2 = SeedIdentity.fromSeed(seed, { descriptor })
150
+ const identityWithDescriptor = SeedIdentity.fromSeed(seed, { descriptor })
161
151
 
162
152
  // Or with a custom descriptor and passphrase (MnemonicIdentity)
163
- const identity3 = MnemonicIdentity.fromMnemonic(mnemonic, {
153
+ const identityWithDescriptorAndPassphrase = MnemonicIdentity.fromMnemonic(mnemonic, {
164
154
  descriptor,
165
155
  passphrase: 'my secret passphrase'
166
156
  })
@@ -171,9 +161,13 @@ const identity3 = MnemonicIdentity.fromMnemonic(mnemonic, {
171
161
  Create watch-only wallets from an output descriptor:
172
162
 
173
163
  ```typescript
174
- import { ReadonlyDescriptorIdentity, ReadonlyWallet } from '@arkade-os/sdk'
164
+ import { MnemonicIdentity, ReadonlyDescriptorIdentity, ReadonlyWallet } from '@arkade-os/sdk'
165
+ import { generateMnemonic } from '@scure/bip39'
166
+ import { wordlist } from '@scure/bip39/wordlists/english.js'
175
167
 
176
168
  // From a full identity
169
+ const mnemonic = generateMnemonic(wordlist)
170
+ const identity = MnemonicIdentity.fromMnemonic(mnemonic)
177
171
  const readonly = await identity.toReadonly()
178
172
 
179
173
  // Or directly from a descriptor (e.g., from another wallet)
@@ -183,7 +177,7 @@ const readonlyFromDescriptor = ReadonlyDescriptorIdentity.fromDescriptor(descrip
183
177
  // Use in a watch-only wallet
184
178
  const readonlyWallet = await ReadonlyWallet.create({
185
179
  identity: readonly,
186
- arkServerUrl: 'https://mutinynet.arkade.sh'
180
+ arkServerUrl: 'https://arkade.computer'
187
181
  })
188
182
 
189
183
  // Can query but not sign
@@ -197,35 +191,71 @@ const balance = await readonlyWallet.getBalance()
197
191
 
198
192
  The descriptor format (`tr([fingerprint/path']xpub.../0/0)`) is HD-ready — future versions will support deriving multiple addresses and change outputs from the same seed.
199
193
 
194
+ ### Batch Signing for Browser Wallets
195
+
196
+ Arkade send transactions require N+1 PSBT signatures (N checkpoints + 1 main tx). With local identities like `SingleKey` or `SeedIdentity` this is invisible, but browser wallet extensions (Xverse, UniSat, OKX, etc.) show a confirmation popup per signature. The `BatchSignableIdentity` interface lets wallet providers reduce N+1 popups to a single batch confirmation.
197
+
198
+ ```typescript
199
+ import {
200
+ BatchSignableIdentity,
201
+ SignRequest,
202
+ isBatchSignable,
203
+ Wallet
204
+ } from '@arkade-os/sdk'
205
+
206
+ // Implement the interface in your wallet provider
207
+ class MyBrowserWallet implements BatchSignableIdentity {
208
+ // ... implement Identity methods (sign, signMessage, xOnlyPublicKey, etc.)
209
+
210
+ async signMultiple(requests: SignRequest[]): Promise<Transaction[]> {
211
+ // Convert all PSBTs to your wallet's batch signing API format
212
+ const psbts = requests.map(r => r.tx.toPSBT())
213
+ // Single wallet popup for all signatures
214
+ const signedPsbts = await myWalletExtension.signAllPSBTs(psbts)
215
+ return signedPsbts.map(psbt => Transaction.fromPSBT(psbt))
216
+ }
217
+ }
218
+
219
+ // The SDK automatically detects batch-capable identities
220
+ const identity = new MyBrowserWallet()
221
+ console.log(isBatchSignable(identity)) // true
222
+
223
+ // Wallet.send() uses one popup instead of N+1
224
+ const wallet = await Wallet.create({ identity, arkServerUrl: 'https://arkade.computer' })
225
+ await wallet.send({ address: 'ark1q...', amount: 1000 })
226
+ ```
227
+
228
+ Identities without `signMultiple` continue to work unchanged — each checkpoint is signed individually via `sign()`.
229
+
200
230
  ### Receiving Bitcoin
201
231
 
202
232
  ```typescript
203
233
  import { waitForIncomingFunds } from '@arkade-os/sdk'
204
234
 
205
235
  // Get wallet addresses
206
- const arkAddress = await wallet.getAddress()
236
+ const arkadeAddress = await wallet.getAddress()
207
237
  const boardingAddress = await wallet.getBoardingAddress()
208
- console.log('Ark Address:', arkAddress)
209
- console.log('Boarding Address:', boardingAddress)
238
+ console.log('Arkade Address:', arkadeAddress)
239
+ console.log('Boarding (Mainnet) Address:', boardingAddress)
210
240
 
211
241
  const incomingFunds = await waitForIncomingFunds(wallet)
212
242
  if (incomingFunds.type === "vtxo") {
213
- // Virtual coins received
214
- console.log("VTXOs: ", incomingFunds.vtxos)
243
+ // Virtual outputs received
244
+ console.log("VTXOs: ", incomingFunds.newVtxos)
215
245
  } else if (incomingFunds.type === "utxo") {
216
- // Boarding coins received
246
+ // Boarding inputs received
217
247
  console.log("UTXOs: ", incomingFunds.coins)
218
248
  }
219
249
  ```
220
250
 
221
251
  ### Onboarding
222
252
 
223
- Onboarding allows you to swap on-chain funds into VTXOs:
253
+ Onboarding allows you to swap onchain funds into virtual outputs:
224
254
 
225
255
  ```typescript
226
256
  import { Ramps } from '@arkade-os/sdk'
227
257
 
228
- const onboardTxid = await new Ramps(wallet).onboard();
258
+ const boardingTxId = await new Ramps(wallet).onboard();
229
259
  ```
230
260
 
231
261
  ### Checking Balance
@@ -240,105 +270,130 @@ console.log('Offchain Settled:', balance.settled)
240
270
  console.log('Offchain Preconfirmed:', balance.preconfirmed)
241
271
  console.log('Recoverable:', balance.recoverable)
242
272
 
243
- // Get virtual UTXOs (off-chain)
244
- const virtualCoins = await wallet.getVtxos()
273
+ // Get virtual outputs (available for offchain spending)
274
+ const vtxos = await wallet.getVtxos()
245
275
 
246
- // Get boarding UTXOs
247
- const boardingUtxos = await wallet.getBoardingUtxos()
276
+ // Get boarding inputs
277
+ const boardingInputs = await wallet.getBoardingUtxos()
248
278
  ```
249
279
 
250
280
  ### Sending Bitcoin
251
281
 
252
282
  ```typescript
253
- // Send bitcoin via Ark
254
- const txid = await wallet.sendBitcoin({
255
- address: 'ark1qq4...', // ark address
256
- amount: 50000, // in satoshis
283
+ // Send bitcoin instantly offchain
284
+ const txid = await wallet.send({
285
+ address: 'ark1q...', // arkade address
286
+ amount: 50_000, // in satoshis
257
287
  })
258
288
  ```
259
289
 
260
290
  ### Assets (Issue, Reissue, Burn, Send)
261
291
 
262
- The wallet's `assetManager` lets you create and manage assets on Ark. `send` method supports sending assets.
292
+ The wallet's `assetManager` lets you create and manage assets on Arkade. The `send` method supports sending assets.
263
293
 
264
294
  ```typescript
265
295
  // Issue a new asset (non-reissuable by default)
266
- const controlAssetIssuance = await wallet.assetManager.issue({
267
- amount: 1000,
268
- metadata: { name: 'My Token', ticker: 'MTK', decimals: 8 },
296
+ const { assetId: controlAssetId } = await wallet.assetManager.issue({
297
+ amount: 1,
298
+ metadata: {
299
+ ticker: 'ctrl-MTK'
300
+ }
269
301
  })
270
302
 
271
- // Issue a new asset using the control asset as reference
272
- const assetIssuance = await wallet.assetManager.issue({
303
+ // Issue a new asset referencing the control asset
304
+ const { assetId } = await wallet.assetManager.issue({
273
305
  amount: 500,
274
- controlAssetId: controlAssetIssuance.assetId,
306
+ controlAssetId,
307
+ metadata: {
308
+ ticker: 'MTK'
309
+ }
275
310
  })
276
311
 
277
- // Reissue more supply of the asset, need ownership of the control asset
278
- const reissuanceTxid = await wallet.assetManager.reissue({
279
- assetId: assetIssuance.assetId,
312
+ // Reissue more supply of the asset (requires ownership of the control asset)
313
+ const reissuanceTxId = await wallet.assetManager.reissue({
314
+ assetId,
280
315
  amount: 500,
281
316
  })
282
317
 
283
318
  // Burn some of the asset
284
- const burnTxid = await wallet.assetManager.burn({
285
- assetId: assetIssuance.assetId,
319
+ const burnTxId = await wallet.assetManager.burn({
320
+ assetId,
286
321
  amount: 200,
287
322
  })
288
323
 
289
- // Send asset to another Ark address
290
- const sendTxid = await wallet.send({
291
- address: 'ark1qq4...',
292
- assets: [{ assetId: assetIssuance.assetId, amount: 100 }],
324
+ // Send asset to another Arkade address
325
+ const sendTxId = await wallet.send({
326
+ address: 'ark1q...',
327
+ assets: [{ assetId, amount: 100 }],
293
328
  })
329
+
330
+ // Check remaining balance
331
+ const { assets } = await wallet.getBalance()
332
+ const assetBalance = assets.find(asset => asset.assetId === assetId)?.amount
294
333
  ```
295
334
 
296
- ### Batch Settlements
335
+ ### Batch Settlement
297
336
 
298
- This can be used to move preconfirmed balances into finalized balances and to manually convert UTXOs and VTXOs.
337
+ The `settle` method can be used to move preconfirmed balances into finalized balances and to manually convert onchain funds to virtual outputs.
299
338
 
300
339
  ```typescript
340
+ // Fetch offchain preconfirmed outputs and onchain boarding inputs
341
+ const [vtxos, boardingInputs] = await Promise.all([
342
+ wallet.getVtxos(),
343
+ wallet.getBoardingUtxos()
344
+ ])
345
+
301
346
  // For settling transactions
302
- const settleTxid = await wallet.settle({
303
- inputs, // from getVtxos() or getBoardingUtxos()
347
+ const settlementTxId = await wallet.settle({
348
+ inputs: [...vtxos, ...boardingInputs],
349
+ // Optional: specify a mainnet output
304
350
  outputs: [{
305
- address: destinationAddress,
306
- amount: BigInt(amount)
351
+ address: "bc1p...",
352
+ amount: 100_000n
307
353
  }]
308
354
  })
309
355
  ```
310
356
 
311
- ### VTXO Management (Renewal & Recovery)
357
+ ### Virtual Output Management (Renewal & Recovery)
312
358
 
313
- VTXOs have an expiration time (batch expiry). The SDK provides the `VtxoManager` class to handle:
359
+ Virtual outputs have an expiration time (batch expiry).
314
360
 
315
- - **Renewal**: Renew VTXOs before they expire to maintain unilateral control of the funds.
316
- - **Recovery**: Reclaim swept or expired VTXOs back to the wallet in case renewal window was missed.
317
- - **Boarding UTXO Sweep**: Sweep expired boarding UTXOs back to a fresh boarding address to restart the timelock.
361
+ The SDK provides the `VtxoManager` class to handle:
362
+
363
+ - **Renewal**: Renew virtual outputs before they expire to maintain unilateral control of the funds.
364
+ - **Recovery**: Reclaim swept or expired virtual outputs back to the wallet in case renewal window was missed.
365
+ - **Boarding Input Sweep**: Sweep expired boarding inputs back to a fresh boarding address to restart the timelock.
318
366
 
319
367
  #### Settlement Configuration
320
368
 
321
369
  The recommended way to configure `VtxoManager` is via `settlementConfig` on the wallet.
322
370
  If you omit `settlementConfig`, settlement is enabled with the default behavior:
323
- VTXO renewal at 3 days and boarding UTXO sweep enabled.
371
+ Virtual output renewal at 3 days and boarding input sweep enabled.
324
372
 
325
373
  ```typescript
326
374
  const wallet = await Wallet.create({
327
375
  identity,
328
- arkServerUrl: 'https://mutinynet.arkade.sh',
329
- // Enable settlement with defaults explicitly
330
- settlementConfig: {},
376
+ arkServerUrl: 'https://arkade.computer',
377
+ // Enable settlement with defaults explicitly:
378
+ settlementConfig: {
379
+ // Seconds before virtual output expiry to trigger renewal
380
+ vtxoThreshold: 60 * 60 * 24 * 3, // 3 days
381
+ // Whether to sweep expired boarding inputs back to a fresh boarding address
382
+ boardingUtxoSweep: true,
383
+ // Polling interval in milliseconds for checking boarding inputs
384
+ pollIntervalMs: 60_000 // 1 minute
385
+ },
331
386
  })
332
387
  ```
333
388
 
334
389
  ```typescript
335
- // Enable both VTXO renewal and boarding UTXO sweep
390
+ // Enable both virtual output renewal and boarding input sweep
336
391
  const wallet = await Wallet.create({
337
392
  identity,
338
- arkServerUrl: 'https://mutinynet.arkade.sh',
393
+ arkServerUrl: 'https://arkade.computer',
339
394
  settlementConfig: {
340
- vtxoThreshold: 86400, // renew when 24 hours remain (in seconds)
341
- boardingUtxoSweep: true, // sweep expired boarding UTXOs
395
+ vtxoThreshold: 60 * 60 * 24, // renew when 24 hours remain (in seconds)
396
+ boardingUtxoSweep: true, // sweep expired boarding inputs
342
397
  },
343
398
  })
344
399
  ```
@@ -347,68 +402,60 @@ const wallet = await Wallet.create({
347
402
  // Explicitly disable all settlement
348
403
  const wallet = await Wallet.create({
349
404
  identity,
350
- arkServerUrl: 'https://mutinynet.arkade.sh',
405
+ arkServerUrl: 'https://arkade.computer',
351
406
  settlementConfig: false,
352
407
  })
353
408
  ```
354
409
 
355
- Create the `VtxoManager` by passing the wallet and its settlement config:
410
+ Access the `VtxoManager` from the wallet after configuring `settlementConfig`:
356
411
 
357
412
  ```typescript
358
- import { VtxoManager } from '@arkade-os/sdk'
359
-
360
- const manager = new VtxoManager(
361
- wallet,
362
- undefined, // deprecated renewalConfig
363
- wallet.settlementConfig // new settlementConfig
364
- )
413
+ const manager = await wallet.getVtxoManager()
365
414
  ```
366
415
 
367
- > **Migration from `renewalConfig`:** The old `renewalConfig` with `enabled` and `thresholdMs` (milliseconds) is still supported but deprecated. If both are provided, `settlementConfig` takes precedence. The new `vtxoThreshold` uses **seconds** instead of milliseconds.
416
+ > **Migration from `renewalConfig`:** Directly initializing a `VtxoManager` with `renewalConfig` is still supported but deprecated. Prefer `settlementConfig` where `vtxoThreshold` is expressed in **seconds** instead of milliseconds.
368
417
 
369
418
  #### Renewal: Prevent Expiration
370
419
 
371
- Renew VTXOs before they expire to retain unilateral control of funds.
372
- This settles expiring and recoverable VTXOs back to your wallet, refreshing their expiration time.
420
+ Renew virtual outputs before they expire to retain unilateral control of funds.
421
+ This settles expiring and recoverable virtual outputs back to your wallet, refreshing their expiration time.
373
422
 
374
423
  ```typescript
375
- // Renew all VTXOs to prevent expiration
424
+ // Renew all virtual outputs to prevent expiration
376
425
  const txid = await manager.renewVtxos()
377
- console.log('Renewed:', txid)
378
-
379
- // Check which VTXOs are expiring soon
426
+ // Check which virtual outputs are expiring soon
380
427
  const expiringVtxos = await manager.getExpiringVtxos()
381
- // Override thresholdMs (e.g., renew when 5 seconds of time remains)
382
- const urgentlyExpiring = await manager.getExpiringVtxos(5_000)
428
+ // Override thresholdMs (e.g., get virtual outputs expiring in the next 60 seconds)
429
+ const urgentlyExpiring = await manager.getExpiringVtxos(60_000)
383
430
  ```
384
431
 
385
- #### Boarding UTXO Sweep
432
+ #### Boarding Input Sweep
386
433
 
387
- When a boarding UTXO's CSV timelock expires, it can no longer be onboarded into Ark cooperatively. The sweep feature detects these expired UTXOs and builds a raw on-chain transaction that spends them via the unilateral exit path back to a fresh boarding address, restarting the timelock.
434
+ When a boarding input's CSV timelock expires, it can no longer be onboarded into Arkade cooperatively. The sweep feature detects these expired UTXOs and builds a raw onchain transaction that spends them via the unilateral exit path back to a fresh boarding address, restarting the timelock.
388
435
 
389
436
  - Multiple expired UTXOs are batched into a single transaction (many inputs, one output)
390
437
  - A dust check ensures the sweep is skipped if fees would consume the entire value
391
438
 
392
439
  ```typescript
393
- // Check for expired boarding UTXOs
440
+ // Check for expired boarding inputs
394
441
  const expired = await manager.getExpiredBoardingUtxos()
395
- console.log(`${expired.length} expired boarding UTXOs`)
442
+ console.log(`${expired.length} expired boarding inputs`)
396
443
 
397
444
  // Sweep them back to a fresh boarding address (requires boardingUtxoSweep: true)
398
445
  try {
399
446
  const txid = await manager.sweepExpiredBoardingUtxos()
400
- console.log('Swept expired boarding UTXOs:', txid)
447
+ console.log('Swept expired boarding inputs:', txid)
401
448
  } catch (e) {
402
- // "No expired boarding UTXOs to sweep" or "Sweep not economical"
449
+ // "No expired boarding inputs to sweep" or "Sweep not economical"
403
450
  }
404
451
  ```
405
452
 
406
453
  #### Recovery: Reclaim Swept VTXOs
407
454
 
408
- Recover VTXOs that have been swept by the server or consolidate small amounts (subdust).
455
+ Recover virtual outputs that have been swept by the server or consolidate small amounts (subdust).
409
456
 
410
457
  ```typescript
411
- // Recover swept VTXOs and preconfirmed subdust
458
+ // Recover swept virtual outputs and preconfirmed subdust
412
459
  const txid = await manager.recoverVtxos((event) => {
413
460
  console.log('Settlement event:', event.type)
414
461
  })
@@ -418,71 +465,79 @@ const balance = await manager.getRecoverableBalance()
418
465
  ```
419
466
 
420
467
 
421
- ### VTXO Delegation
468
+ ### Delegation
469
+
470
+ Delegation allows users to outsource virtual output renewal to a third-party delegation service.
471
+
472
+ Instead of the delegating user renewing virtual outputs by themself, their delegate will automatically settle them before they expire, sending the funds back to the delegator's wallet address (minus a service fee).
473
+
474
+ This is useful for wallets that cannot be online 24/7.
422
475
 
423
- Delegation allows you to outsource VTXO renewal to a third-party delegator service. Instead of renewing VTXOs yourself, the delegator will automatically settle them before they expire, sending the funds back to your wallet address (minus a service fee). This is useful for wallets that cannot be online 24/7.
476
+ When a `delegatorProvider` is configured, the wallet address includes an extra tapscript path that authorizes the delegate to co-sign renewals alongside the Arkade server.
424
477
 
425
- When a `delegatorProvider` is configured, the wallet address includes an extra tapscript path that authorizes the delegator to co-sign renewals alongside the Ark server.
478
+ To run a delegation service, you'll need to set up a [Fulmine server](https://github.com/ArkLabsHQ/fulmine) with the [Delegation API](https://github.com/ArkLabsHQ/fulmine?tab=readme-ov-file#-delegate-api) enabled.
426
479
 
427
480
  #### Setting Up a Wallet with Delegation
428
481
 
429
482
  ```typescript
430
- import { Wallet, SingleKey, RestDelegatorProvider } from '@arkade-os/sdk'
431
-
432
- const identity = SingleKey.fromHex('your_private_key_hex')
483
+ import { Wallet, MnemonicIdentity, RestDelegatorProvider } from '@arkade-os/sdk'
433
484
 
434
485
  const wallet = await Wallet.create({
435
- identity,
436
- arkServerUrl: 'https://mutinynet.arkade.sh',
437
- delegatorProvider: new RestDelegatorProvider('https://delegator.example.com'),
486
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
487
+ arkServerUrl: 'https://arkade.computer',
488
+ delegatorProvider: new RestDelegatorProvider('http://localhost:7001'),
438
489
  })
439
490
  ```
440
491
 
441
492
  > **Note:** Adding a `delegatorProvider` changes your wallet address because the offchain tapscript includes an additional delegation path. Funds sent to an address without delegation cannot be delegated, and vice versa.
442
493
 
443
- #### Delegating VTXOs
494
+ #### Delegating Virtual Outputs
444
495
 
445
- Once the wallet is configured with a delegator, use `wallet.delegatorManager` to delegate your VTXOs:
496
+ Once the wallet is configured with a delegate, use `wallet.delegatorManager` to delegate your virtual outputs:
446
497
 
447
498
  ```typescript
448
- // Get spendable VTXOs
449
- const vtxos = (await wallet.getVtxos({ withRecoverable: true }))
450
- .filter(v => v.virtualStatus.type === 'confirmed')
499
+ // Get spendable virtual outputs (including recoverable)
500
+ const vtxos = await wallet.getVtxos({ withRecoverable: true })
451
501
 
452
- // Delegate all VTXOs — the delegator will renew them before expiry
453
- const myAddress = await wallet.getAddress()
454
- const result = await wallet.delegatorManager.delegate(vtxos, myAddress)
502
+ // Delegate all virtual outputs — the delegate will renew them before expiry
503
+ const arkadeAddress = await wallet.getAddress()
504
+ const delegatorManager = await wallet.getDelegatorManager();
505
+ const delegationResult = await delegatorManager.delegate(vtxos, arkadeAddress)
455
506
 
456
- console.log('Delegated:', result.delegated.length)
457
- console.log('Failed:', result.failed.length)
507
+ console.log('Delegated:', delegationResult.delegated.length)
508
+ console.log('Failed:', delegationResult.failed.length)
458
509
  ```
459
510
 
460
- The `delegate` method groups VTXOs by expiry date and submits them to the delegator service. By default, delegation is scheduled at 90% of each VTXO's remaining lifetime. You can override this with an explicit date:
511
+ The `delegate` method groups virtual outputs by expiry date and submits them to the delegation service.
512
+
513
+ By default, delegation is scheduled at 90% of each virtual output's remaining lifetime.
514
+
515
+ You can override this with an explicit date:
461
516
 
462
517
  ```typescript
463
518
  // Delegate with a specific renewal time
464
519
  const delegateAt = new Date(Date.now() + 12 * 60 * 60 * 1000) // 12 hours from now
465
- await wallet.delegatorManager.delegate(vtxos, myAddress, delegateAt)
520
+ await delegatorManager.delegate(vtxos, arkadeAddress, delegateAt)
466
521
  ```
467
522
 
468
523
  #### Service Worker Integration
469
524
 
470
- When using a service worker wallet, pass the `delegatorUrl` option. The service worker will automatically delegate VTXOs after each VTXO update:
525
+ When using a service worker wallet, pass the `delegatorUrl` option. The service worker will automatically delegate virtual outputs after each update:
471
526
 
472
527
  ```typescript
473
- import { ServiceWorkerWallet, SingleKey } from '@arkade-os/sdk'
528
+ import { ServiceWorkerWallet, MnemonicIdentity } from '@arkade-os/sdk'
474
529
 
475
530
  const wallet = await ServiceWorkerWallet.setup({
476
531
  serviceWorkerPath: '/service-worker.js',
477
- arkServerUrl: 'https://mutinynet.arkade.sh',
478
- identity: SingleKey.fromHex('your_private_key_hex'),
479
- delegatorUrl: 'https://delegator.example.com',
532
+ arkServerUrl: 'https://arkade.computer',
533
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
534
+ delegatorUrl: 'http://localhost:7001',
480
535
  })
481
536
  ```
482
537
 
483
- #### Querying Delegator Info
538
+ #### Querying Delegate Info
484
539
 
485
- You can query the delegator service directly to inspect its public key, fee, and payment address:
540
+ You can query the delegation service directly to inspect its public key, fee, and payment address:
486
541
 
487
542
  ```typescript
488
543
  import { RestDelegatorProvider } from '@arkade-os/sdk'
@@ -490,7 +545,7 @@ import { RestDelegatorProvider } from '@arkade-os/sdk'
490
545
  const provider = new RestDelegatorProvider('https://delegator.example.com')
491
546
  const info = await provider.getDelegateInfo()
492
547
 
493
- console.log('Delegator public key:', info.pubkey)
548
+ console.log('Delegate public key:', info.pubkey)
494
549
  console.log('Service fee (sats):', info.fee)
495
550
  console.log('Fee address:', info.delegatorAddress)
496
551
  ```
@@ -500,9 +555,9 @@ console.log('Fee address:', info.delegatorAddress)
500
555
  Sign and verify messages using [BIP-322](https://github.com/bitcoin/bips/blob/master/bip-0322.mediawiki). Supports P2TR (Taproot) signing, and verification for P2TR, P2WPKH, and legacy P2PKH addresses.
501
556
 
502
557
  ```typescript
503
- import { BIP322, SingleKey } from '@arkade-os/sdk'
558
+ import { BIP322, MnemonicIdentity } from '@arkade-os/sdk'
504
559
 
505
- const identity = SingleKey.fromHex('your_private_key_hex')
560
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
506
561
 
507
562
  // Sign a message (P2TR key-spend)
508
563
  const signature = await BIP322.sign('Hello Bitcoin!', identity)
@@ -520,44 +575,66 @@ BIP322.verify('Hello Bitcoin!', sig, '1A1zP1...') // legacy P2PKH
520
575
  ```typescript
521
576
  // Get transaction history
522
577
  const history = await wallet.getTransactionHistory()
578
+ /*
579
+ {
580
+ key: {
581
+ boardingTxid: string;
582
+ commitmentTxid: string;
583
+ arkTxid: string;
584
+ };
585
+ type: "SENT" | "RECEIVED";
586
+ amount: number;
587
+ settled: boolean;
588
+ createdAt: number;
589
+ assets?: Array<{
590
+ assetId: string,
591
+ amount: number
592
+ }>
593
+ }
594
+ */
523
595
  ```
524
596
 
525
597
  ### Offboarding
526
598
 
527
- Collaborative exit or "offboarding" allows you to withdraw your virtual funds to an on-chain address:
599
+ Collaborative exit or "offboarding" allows you to withdraw your virtual funds to an onchain address:
528
600
 
529
601
  ```typescript
530
- import { Ramps } from '@arkade-os/sdk'
602
+ import { Wallet, MnemonicIdentity, Ramps } from '@arkade-os/sdk'
603
+
604
+ const wallet = await Wallet.create({
605
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
606
+ arkServerUrl: 'https://arkade.computer'
607
+ })
531
608
 
532
609
  // Get fee information from the server
533
- const info = await wallet.arkProvider.getInfo();
610
+ const { fees: feeInfo } = await wallet.arkProvider.getInfo();
534
611
 
535
612
  const exitTxid = await new Ramps(wallet).offboard(
536
- onchainAddress,
537
- info.fees
613
+ 'bc1p...',
614
+ feeInfo
538
615
  );
539
616
  ```
540
617
 
541
618
  ### Unilateral Exit
542
619
 
543
- Unilateral exit allows you to withdraw your funds from the Ark protocol back to the Bitcoin blockchain without requiring cooperation from the Ark server. This process involves two main steps:
620
+ Unilateral exit allows you to withdraw your funds from the Arkade protocol back to the Bitcoin blockchain without requiring cooperation from the Arkade server. This process involves two main steps:
544
621
 
545
- 1. **Unrolling**: Broadcasting the transaction chain from off-chain back to on-chain
546
- 2. **Completing the exit**: Spending the unrolled VTXOs after the timelock expires
622
+ 1. **Unrolling**: Broadcasting the transaction chain from offchain back to onchain
623
+ 2. **Completing the exit**: Spending the unrolled virtual outputs after the timelock expires
547
624
 
548
- #### Step 1: Unrolling VTXOs
625
+ #### Step 1: Unrolling Virtual Outputs
549
626
 
550
627
  ```typescript
551
- import { Unroll, OnchainWallet, SingleKey } from '@arkade-os/sdk'
628
+ import { MnemonicIdentity, OnchainWallet, Unroll } from '@arkade-os/sdk'
552
629
 
553
630
  // Create an identity for the onchain wallet
554
- const onchainIdentity = SingleKey.fromHex('your_onchain_private_key_hex');
631
+ const onchainIdentity = MnemonicIdentity.fromMnemonic('abandon abandon...')
555
632
 
556
- // Create an onchain wallet to pay for P2A outputs in VTXO branches
633
+ // Create an onchain wallet to pay for P2A outputs in virtual output branches
557
634
  // OnchainWallet implements the AnchorBumper interface
558
635
  const onchainWallet = await OnchainWallet.create(onchainIdentity, 'regtest');
559
636
 
560
- // Unroll a specific VTXO
637
+ // Unroll a specific virtual output
561
638
  const vtxo = { txid: 'your_vtxo_txid', vout: 0 };
562
639
  const session = await Unroll.Session.create(
563
640
  vtxo,
@@ -576,7 +653,7 @@ for await (const step of session) {
576
653
  console.log(`Broadcasting transaction ${step.tx.id}`);
577
654
  break;
578
655
  case Unroll.StepType.DONE:
579
- console.log(`Unrolling complete for VTXO ${step.vtxoTxid}`);
656
+ console.log(`Unrolling complete for virtual output ${step.vtxoTxid}`);
580
657
  break;
581
658
  }
582
659
  }
@@ -585,29 +662,29 @@ for await (const step of session) {
585
662
  The unrolling process works by:
586
663
 
587
664
  - Traversing the transaction chain from the root (most recent) to the leaf (oldest)
588
- - Broadcasting each transaction that isn't already on-chain
665
+ - Broadcasting each transaction that isn't already onchain
589
666
  - Waiting for confirmations between steps
590
667
  - Using P2A (Pay-to-Anchor) transactions to pay for fees
591
668
 
592
669
  #### Step 2: Completing the Exit
593
670
 
594
- Once VTXOs are fully unrolled and the unilateral exit timelock has expired, you can complete the exit:
671
+ Once virtual outputs are fully unrolled and the unilateral exit timelock has expired, you can complete the exit:
595
672
 
596
673
  ```typescript
597
- // Complete the exit for specific VTXOs
674
+ // Complete the exit for specific virtual outputs
598
675
  await Unroll.completeUnroll(
599
676
  wallet,
600
- [vtxo.txid], // Array of VTXO transaction IDs to complete
677
+ [vtxo.txid], // Array of virtual output transaction IDs to complete
601
678
  onchainWallet.address // Address to receive the exit amount
602
679
  );
603
680
  ```
604
681
 
605
682
  **Important Notes:**
606
683
 
607
- - Each VTXO may require multiple unroll steps depending on the transaction chain length
684
+ - Each virtual output may require multiple unroll steps depending on the transaction chain length
608
685
  - Each unroll step must be confirmed before proceeding to the next
609
- - The `completeUnroll` method can only be called after VTXOs are fully unrolled and the timelock has expired
610
- - You need sufficient on-chain funds in the `OnchainWallet` to pay for P2A transaction fees
686
+ - The `completeUnroll` method can only be called after all virtual outputs are fully unrolled and the timelock has expired
687
+ - You need sufficient onchain funds in the `OnchainWallet` to pay for P2A transaction fees
611
688
 
612
689
  ### Running the wallet in a service worker
613
690
 
@@ -643,15 +720,13 @@ bus.start()
643
720
 
644
721
  ```typescript
645
722
  // app.ts
646
- import { ServiceWorkerWallet, SingleKey } from '@arkade-os/sdk'
647
-
648
- const identity = SingleKey.fromHex('your_private_key_hex')
723
+ import { ServiceWorkerWallet, MnemonicIdentity } from '@arkade-os/sdk'
649
724
 
650
725
  // One-liner: registers the SW, initializes the MessageBus, and creates the wallet
651
726
  const wallet = await ServiceWorkerWallet.setup({
652
727
  serviceWorkerPath: '/service-worker.js',
653
- arkServerUrl: 'https://mutinynet.arkade.sh',
654
- identity,
728
+ arkServerUrl: 'https://arkade.computer',
729
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
655
730
  })
656
731
 
657
732
  // Use like any other wallet — calls are proxied to the service worker
@@ -677,12 +752,9 @@ differ in orchestration and communication.
677
752
  See the platform READMEs for architecture details, runtime flow, and usage
678
753
  examples.
679
754
 
680
-
681
-
682
755
  ### Repositories (Storage)
683
756
 
684
- The `StorageAdapter` API is deprecated. Use repositories instead. If you omit
685
- `storage`, the SDK uses IndexedDB repositories with the default database name.
757
+ The `StorageAdapter` API is deprecated. Use repositories instead. If you omit `storage`, the SDK uses IndexedDB repositories with the default database name.
686
758
 
687
759
  #### Migration from v1 StorageAdapter
688
760
 
@@ -778,7 +850,7 @@ See [examples/node/multiple-wallets.ts](examples/node/multiple-wallets.ts) for
778
850
  a full working example using `better-sqlite3`.
779
851
 
780
852
  ```typescript
781
- import { SingleKey, Wallet } from '@arkade-os/sdk'
853
+ import { MnemonicIdentity, Wallet } from '@arkade-os/sdk'
782
854
  import { SQLiteWalletRepository, SQLiteContractRepository, SQLExecutor } from '@arkade-os/sdk/repositories/sqlite'
783
855
  import Database from 'better-sqlite3'
784
856
 
@@ -792,8 +864,8 @@ const executor: SQLExecutor = {
792
864
  }
793
865
 
794
866
  const wallet = await Wallet.create({
795
- identity: SingleKey.fromHex('your_private_key_hex'),
796
- arkServerUrl: 'https://mutinynet.arkade.sh',
867
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
868
+ arkServerUrl: 'https://arkade.computer',
797
869
  storage: {
798
870
  walletRepository: new SQLiteWalletRepository(executor),
799
871
  contractRepository: new SQLiteContractRepository(executor),
@@ -811,7 +883,7 @@ import { RealmWalletRepository, RealmContractRepository, ArkRealmSchemas } from
811
883
  const realm = await Realm.open({ schema: [...ArkRealmSchemas, ...yourSchemas] })
812
884
  const wallet = await Wallet.create({
813
885
  identity,
814
- arkServerUrl: 'https://mutinynet.arkade.sh',
886
+ arkServerUrl: 'https://arkade.computer',
815
887
  storage: {
816
888
  walletRepository: new RealmWalletRepository(realm),
817
889
  contractRepository: new RealmContractRepository(realm),
@@ -825,11 +897,11 @@ In the browser, the SDK defaults to IndexedDB repositories when no `storage`
825
897
  is provided:
826
898
 
827
899
  ```typescript
828
- import { SingleKey, Wallet } from '@arkade-os/sdk'
900
+ import { MnemonicIdentity, Wallet } from '@arkade-os/sdk'
829
901
 
830
902
  const wallet = await Wallet.create({
831
- identity: SingleKey.fromHex('your_private_key_hex'),
832
- arkServerUrl: 'https://mutinynet.arkade.sh',
903
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
904
+ arkServerUrl: 'https://arkade.computer',
833
905
  // Uses IndexedDB by default in the browser
834
906
  })
835
907
  ```
@@ -841,14 +913,15 @@ For ephemeral storage (no persistence), pass the in-memory repositories:
841
913
 
842
914
  ```typescript
843
915
  import {
916
+ MnemonicIdentity,
917
+ Wallet,
844
918
  InMemoryWalletRepository,
845
- InMemoryContractRepository,
846
- Wallet
919
+ InMemoryContractRepository
847
920
  } from '@arkade-os/sdk'
848
921
 
849
922
  const wallet = await Wallet.create({
850
- identity,
851
- arkServerUrl: 'https://mutinynet.arkade.sh',
923
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
924
+ arkServerUrl: 'https://arkade.computer',
852
925
  storage: {
853
926
  walletRepository: new InMemoryWalletRepository(),
854
927
  contractRepository: new InMemoryContractRepository()
@@ -869,7 +942,7 @@ import { EventSource } from "eventsource";
869
942
  (globalThis as any).EventSource = EventSource;
870
943
 
871
944
  // Use dynamic import so the polyfill is set before the SDK evaluates
872
- const { Wallet, SingleKey, Ramps } = await import("@arkade-os/sdk");
945
+ const { Wallet } = await import("@arkade-os/sdk");
873
946
  ```
874
947
 
875
948
  If you also need IndexedDB persistence (e.g. for `WalletRepository`), set up the shim before any SDK import:
@@ -895,16 +968,15 @@ See [`examples/node/multiple-wallets.ts`](examples/node/multiple-wallets.ts) for
895
968
  For React Native and Expo applications where standard EventSource and fetch streaming may not work properly, use the Expo-compatible providers:
896
969
 
897
970
  ```typescript
898
- import { Wallet, SingleKey } from '@arkade-os/sdk'
971
+ import { Wallet, MnemonicIdentity } from '@arkade-os/sdk'
899
972
  import { ExpoArkProvider, ExpoIndexerProvider } from '@arkade-os/sdk/adapters/expo'
900
973
 
901
- const identity = SingleKey.fromHex('your_private_key_hex')
974
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
902
975
 
903
976
  const wallet = await Wallet.create({
904
977
  identity: identity,
905
- esploraUrl: 'https://mutinynet.com/api',
906
- arkProvider: new ExpoArkProvider('https://mutinynet.arkade.sh'), // For settlement events and transactions streaming
907
- indexerProvider: new ExpoIndexerProvider('https://mutinynet.arkade.sh'), // For address subscriptions and VTXO updates
978
+ arkProvider: new ExpoArkProvider('https://arkade.computer'), // For settlement events and transactions streaming
979
+ indexerProvider: new ExpoIndexerProvider('https://arkade.computer'), // For address subscriptions and virtual output state updates
908
980
  })
909
981
 
910
982
  // use expo/fetch for streaming support (SSE)
@@ -916,7 +988,7 @@ const address = await wallet.getAddress()
916
988
  Both ExpoArkProvider and ExpoIndexerProvider are available as adapters following the SDK's modular architecture pattern. This keeps the main SDK bundle clean while providing opt-in functionality for specific environments:
917
989
 
918
990
  - **ExpoArkProvider**: Handles settlement events and transaction streaming using expo/fetch for Server-Sent Events
919
- - **ExpoIndexerProvider**: Handles address subscriptions and VTXO updates using expo/fetch for JSON streaming
991
+ - **ExpoIndexerProvider**: Handles address subscriptions and virtual output state updates using expo/fetch for JSON streaming
920
992
 
921
993
  For persistence in Expo/React Native, use the SQLite repository with `expo-sqlite`:
922
994
 
@@ -933,9 +1005,9 @@ const executor = {
933
1005
 
934
1006
  const wallet = await Wallet.create({
935
1007
  identity,
936
- arkServerUrl: 'https://mutinynet.arkade.sh',
937
- arkProvider: new ExpoArkProvider('https://mutinynet.arkade.sh'),
938
- indexerProvider: new ExpoIndexerProvider('https://mutinynet.arkade.sh'),
1008
+ arkServerUrl: 'https://arkade.computer',
1009
+ arkProvider: new ExpoArkProvider('https://arkade.computer'),
1010
+ indexerProvider: new ExpoIndexerProvider('https://arkade.computer'),
939
1011
  storage: {
940
1012
  walletRepository: new SQLiteWalletRepository(executor),
941
1013
  contractRepository: new SQLiteContractRepository(executor),
@@ -958,7 +1030,7 @@ if (!global.crypto) global.crypto = {} as any;
958
1030
  global.crypto.getRandomValues = Crypto.getRandomValues;
959
1031
 
960
1032
  // Now import the SDK
961
- import { Wallet, SingleKey } from '@arkade-os/sdk';
1033
+ import { Wallet, MnemonicIdentity } from '@arkade-os/sdk';
962
1034
  import { ExpoArkProvider, ExpoIndexerProvider } from '@arkade-os/sdk/adapters/expo';
963
1035
  ```
964
1036
 
@@ -966,7 +1038,7 @@ This is required for MuSig2 settlements and cryptographic operations.
966
1038
 
967
1039
  ### Contract Management
968
1040
 
969
- Both `Wallet` and `ServiceWorkerWallet` use a `ContractManager` internally to watch for VTXOs. This provides resilient connection handling with automatic reconnection and failsafe polling - for your wallet's default address and any external contracts you register (Boltz swaps, HTLCs, etc.).
1041
+ Both `Wallet` and `ServiceWorkerWallet` use a `ContractManager` internally to watch for virtual outputs. This provides resilient connection handling with automatic reconnection and failsafe polling - for your wallet's default address and any external contracts you register (Boltz swaps, HTLCs, etc.).
970
1042
 
971
1043
  When you call `wallet.notifyIncomingFunds()` or use `waitForIncomingFunds()`, it uses the ContractManager under the hood, giving you automatic reconnection and failsafe polling for free - no code changes needed.
972
1044
 
@@ -997,10 +1069,10 @@ const contract = await manager.createContract({
997
1069
  const unsubscribe = await manager.onContractEvent((event) => {
998
1070
  switch (event.type) {
999
1071
  case 'vtxo_received':
1000
- console.log(`Received ${event.vtxos.length} VTXOs on ${event.contractScript}`)
1072
+ console.log(`Received ${event.vtxos.length} virtual outputs to ${event.contractScript}`)
1001
1073
  break
1002
1074
  case 'vtxo_spent':
1003
- console.log(`Spent VTXOs on ${event.contractScript}`)
1075
+ console.log(`Spent virtual outputs from ${event.contractScript}`)
1004
1076
  break
1005
1077
  case 'contract_expired':
1006
1078
  console.log(`Contract ${event.contractScript} expired`)
@@ -1011,7 +1083,7 @@ const unsubscribe = await manager.onContractEvent((event) => {
1011
1083
  // Update contract data (e.g., set preimage when revealed)
1012
1084
  await manager.updateContractParams(contract.script, { preimage: revealedPreimage })
1013
1085
 
1014
- // Check spendable paths (requires a specific VTXO)
1086
+ // Check spendable paths (requires a specific virtual output)
1015
1087
  const [withVtxos] = await manager.getContractsWithVtxos({ script: contract.script })
1016
1088
  const vtxo = withVtxos.vtxos[0]
1017
1089
  const paths = manager.getSpendablePaths({
@@ -1025,17 +1097,17 @@ if (paths.length > 0) {
1025
1097
  }
1026
1098
 
1027
1099
  // Or list all possible paths for the current context (no spendability checks)
1028
- const allPaths = manager.getAllSpendingPaths({
1100
+ const allPaths = await manager.getAllSpendingPaths({
1029
1101
  contractScript: contract.script,
1030
1102
  collaborative: true,
1031
1103
  walletPubKey: myPubKey,
1032
1104
  })
1033
1105
 
1034
- // Get balances across all contracts
1035
- const balances = await manager.getAllBalances()
1106
+ // Fetch contracts together with their current virtual outputs
1107
+ const contractsWithVtxos = await manager.getContractsWithVtxos()
1036
1108
 
1037
- // Manually sweep all eligible contracts
1038
- const sweepResults = await manager.sweepAll()
1109
+ // Force a full refresh from the indexer when needed
1110
+ await manager.refreshVtxos()
1039
1111
 
1040
1112
  // Stop watching
1041
1113
  unsubscribe()
@@ -1051,7 +1123,7 @@ The watcher features:
1051
1123
  Access low-level data management through repositories:
1052
1124
 
1053
1125
  ```typescript
1054
- // VTXO management (automatically cached for performance)
1126
+ // Virtual output management (automatically cached for performance)
1055
1127
  const addr = await wallet.getAddress()
1056
1128
  const vtxos = await wallet.walletRepository.getVtxos(addr)
1057
1129
  await wallet.walletRepository.saveVtxos(addr, vtxos)
@@ -1069,7 +1141,7 @@ await wallet.contractRepository.saveToContractCollection(
1069
1141
  const swaps = await wallet.contractRepository.getContractCollection('swaps')
1070
1142
  ```
1071
1143
 
1072
- _For complete API documentation, visit our [TypeScript documentation](https://arkade-os.github.io/ts-sdk/)._
1144
+ _For complete API documentation, visit our [TypeDoc documentation](https://arkade-os.github.io/ts-sdk/)._
1073
1145
 
1074
1146
  ## Development
1075
1147