@arkade-os/sdk 0.4.13 → 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,9 @@
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/)
6
- [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ark-ts-sdk)
5
+ [![TypeDoc](https://img.shields.io/badge/TypeScript-Documentation-blue?style=flat-square)](https://arkade-os.github.io/ts-sdk/)
6
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/arkade-os/ts-sdk)
7
7
 
8
8
  ## Installation
9
9
 
@@ -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
48
  import { 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,23 +191,59 @@ 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: '...' })
225
+ await wallet.sendBitcoin({ address: arkAddress, 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
243
+ // Virtual UTXOs received
214
244
  console.log("VTXOs: ", incomingFunds.vtxos)
215
245
  } else if (incomingFunds.type === "utxo") {
216
- // Boarding coins received
246
+ // Boarding UTXOs received
217
247
  console.log("UTXOs: ", incomingFunds.coins)
218
248
  }
219
249
  ```
@@ -225,7 +255,7 @@ Onboarding allows you to swap on-chain funds into VTXOs:
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
@@ -241,7 +271,7 @@ console.log('Offchain Preconfirmed:', balance.preconfirmed)
241
271
  console.log('Recoverable:', balance.recoverable)
242
272
 
243
273
  // Get virtual UTXOs (off-chain)
244
- const virtualCoins = await wallet.getVtxos()
274
+ const virtualUtxos = await wallet.getVtxos()
245
275
 
246
276
  // Get boarding UTXOs
247
277
  const boardingUtxos = await wallet.getBoardingUtxos()
@@ -250,60 +280,73 @@ const boardingUtxos = await wallet.getBoardingUtxos()
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,
275
307
  })
276
308
 
277
- // Reissue more supply of the asset, need ownership of the control asset
278
- const reissuanceTxid = await wallet.assetManager.reissue({
279
- assetId: assetIssuance.assetId,
309
+ // Reissue more supply of the asset (requires ownership of the control asset)
310
+ const reissuanceTxId = await wallet.assetManager.reissue({
311
+ assetId,
280
312
  amount: 500,
281
313
  })
282
314
 
283
315
  // Burn some of the asset
284
- const burnTxid = await wallet.assetManager.burn({
285
- assetId: assetIssuance.assetId,
316
+ const burnTxId = await wallet.assetManager.burn({
317
+ assetId,
286
318
  amount: 200,
287
319
  })
288
320
 
289
- // Send asset to another Ark address
290
- const sendTxid = await wallet.send({
291
- address: 'ark1qq4...',
292
- assets: [{ assetId: assetIssuance.assetId, amount: 100 }],
321
+ // Send asset to another Arkade address
322
+ const sendTxId = await wallet.send({
323
+ address: 'ark1q...',
324
+ assets: [{ assetId, amount: 100 }],
293
325
  })
326
+
327
+ // Check remaining balance
328
+ const { assets } = await wallet.getBalance()
329
+ const assetBalance = assets.find(asset => asset.assetId === assetId)?.amount
294
330
  ```
295
331
 
296
- ### Batch Settlements
332
+ ### Batch Settlement
297
333
 
298
- This can be used to move preconfirmed balances into finalized balances and to manually convert UTXOs and VTXOs.
334
+ The `settle` method can be used to move preconfirmed balances into finalized balances and to manually convert UTXOs to VTXOs.
299
335
 
300
336
  ```typescript
337
+ // Fetch offchain preconfirmed VTXOs and onchain boarding UTXOs
338
+ const [virtualUtxos, boardingUtxos] = await Promise.all([
339
+ wallet.getVtxos(),
340
+ wallet.getBoardingUtxos()
341
+ ])
342
+
301
343
  // For settling transactions
302
- const settleTxid = await wallet.settle({
303
- inputs, // from getVtxos() or getBoardingUtxos()
344
+ const settlementTxId = await wallet.settle({
345
+ inputs: [...virtualUtxos, ...boardingUtxos],
346
+ // Optional: specify a mainnet output
304
347
  outputs: [{
305
- address: destinationAddress,
306
- amount: BigInt(amount)
348
+ address: "bc1p...",
349
+ amount: 100_000n
307
350
  }]
308
351
  })
309
352
  ```
@@ -325,9 +368,16 @@ VTXO renewal at 3 days and boarding UTXO sweep enabled.
325
368
  ```typescript
326
369
  const wallet = await Wallet.create({
327
370
  identity,
328
- arkServerUrl: 'https://mutinynet.arkade.sh',
329
- // Enable settlement with defaults explicitly
330
- settlementConfig: {},
371
+ arkServerUrl: 'https://arkade.computer',
372
+ // Enable settlement with defaults explicitly:
373
+ settlementConfig: {
374
+ // Seconds before VTXO expiry to trigger renewal
375
+ vtxoThreshold: 259200, // 3 days
376
+ // Whether to sweep expired boarding UTXOs back to a fresh boarding address
377
+ boardingUtxoSweep: true,
378
+ // Polling interval in milliseconds for checking boarding UTXOs
379
+ pollIntervalMs: 60000 // 1 minute
380
+ },
331
381
  })
332
382
  ```
333
383
 
@@ -335,7 +385,7 @@ const wallet = await Wallet.create({
335
385
  // Enable both VTXO renewal and boarding UTXO sweep
336
386
  const wallet = await Wallet.create({
337
387
  identity,
338
- arkServerUrl: 'https://mutinynet.arkade.sh',
388
+ arkServerUrl: 'https://arkade.computer',
339
389
  settlementConfig: {
340
390
  vtxoThreshold: 86400, // renew when 24 hours remain (in seconds)
341
391
  boardingUtxoSweep: true, // sweep expired boarding UTXOs
@@ -347,7 +397,7 @@ const wallet = await Wallet.create({
347
397
  // Explicitly disable all settlement
348
398
  const wallet = await Wallet.create({
349
399
  identity,
350
- arkServerUrl: 'https://mutinynet.arkade.sh',
400
+ arkServerUrl: 'https://arkade.computer',
351
401
  settlementConfig: false,
352
402
  })
353
403
  ```
@@ -359,7 +409,7 @@ import { VtxoManager } from '@arkade-os/sdk'
359
409
 
360
410
  const manager = new VtxoManager(
361
411
  wallet,
362
- undefined, // deprecated renewalConfig
412
+ undefined, // renewalConfig (deprecated)
363
413
  wallet.settlementConfig // new settlementConfig
364
414
  )
365
415
  ```
@@ -374,17 +424,15 @@ This settles expiring and recoverable VTXOs back to your wallet, refreshing thei
374
424
  ```typescript
375
425
  // Renew all VTXOs to prevent expiration
376
426
  const txid = await manager.renewVtxos()
377
- console.log('Renewed:', txid)
378
-
379
427
  // Check which VTXOs are expiring soon
380
428
  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)
429
+ // Override thresholdMs (e.g., get VTXOs expiring in the next 60 seconds)
430
+ const urgentlyExpiring = await manager.getExpiringVtxos(60_000)
383
431
  ```
384
432
 
385
433
  #### Boarding UTXO Sweep
386
434
 
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.
435
+ When a boarding UTXO's CSV timelock expires, it can no longer be onboarded into Arkade 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.
388
436
 
389
437
  - Multiple expired UTXOs are batched into a single transaction (many inputs, one output)
390
438
  - A dust check ensures the sweep is skipped if fees would consume the entire value
@@ -422,19 +470,19 @@ const balance = await manager.getRecoverableBalance()
422
470
 
423
471
  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.
424
472
 
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.
473
+ When a `delegatorProvider` is configured, the wallet address includes an extra tapscript path that authorizes the delegator to co-sign renewals alongside the Arkade server.
474
+
475
+ To run a delegator, 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
476
 
427
477
  #### Setting Up a Wallet with Delegation
428
478
 
429
479
  ```typescript
430
- import { Wallet, SingleKey, RestDelegatorProvider } from '@arkade-os/sdk'
431
-
432
- const identity = SingleKey.fromHex('your_private_key_hex')
480
+ import { Wallet, MnemonicIdentity, RestDelegatorProvider } from '@arkade-os/sdk'
433
481
 
434
482
  const wallet = await Wallet.create({
435
- identity,
436
- arkServerUrl: 'https://mutinynet.arkade.sh',
437
- delegatorProvider: new RestDelegatorProvider('https://delegator.example.com'),
483
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
484
+ arkServerUrl: 'https://arkade.computer',
485
+ delegatorProvider: new RestDelegatorProvider('http://localhost:7001'),
438
486
  })
439
487
  ```
440
488
 
@@ -445,13 +493,14 @@ const wallet = await Wallet.create({
445
493
  Once the wallet is configured with a delegator, use `wallet.delegatorManager` to delegate your VTXOs:
446
494
 
447
495
  ```typescript
448
- // Get spendable VTXOs
496
+ // Get spendable VTXOs (including recoverable)
449
497
  const vtxos = (await wallet.getVtxos({ withRecoverable: true }))
450
498
  .filter(v => v.virtualStatus.type === 'confirmed')
451
499
 
452
500
  // 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)
501
+ const arkadeAddress = await wallet.getAddress()
502
+ const delegatorManager = await wallet.getDelegatorManager();
503
+ const delegationResult = await delegatorManager.delegate(vtxos, arkadeAddress)
455
504
 
456
505
  console.log('Delegated:', result.delegated.length)
457
506
  console.log('Failed:', result.failed.length)
@@ -462,7 +511,7 @@ The `delegate` method groups VTXOs by expiry date and submits them to the delega
462
511
  ```typescript
463
512
  // Delegate with a specific renewal time
464
513
  const delegateAt = new Date(Date.now() + 12 * 60 * 60 * 1000) // 12 hours from now
465
- await wallet.delegatorManager.delegate(vtxos, myAddress, delegateAt)
514
+ await delegatorManager.delegate(vtxos, arkadeAddress, delegateAt)
466
515
  ```
467
516
 
468
517
  #### Service Worker Integration
@@ -470,13 +519,13 @@ await wallet.delegatorManager.delegate(vtxos, myAddress, delegateAt)
470
519
  When using a service worker wallet, pass the `delegatorUrl` option. The service worker will automatically delegate VTXOs after each VTXO update:
471
520
 
472
521
  ```typescript
473
- import { ServiceWorkerWallet, SingleKey } from '@arkade-os/sdk'
522
+ import { ServiceWorkerWallet, MnemonicIdentity } from '@arkade-os/sdk'
474
523
 
475
524
  const wallet = await ServiceWorkerWallet.setup({
476
525
  serviceWorkerPath: '/service-worker.js',
477
- arkServerUrl: 'https://mutinynet.arkade.sh',
478
- identity: SingleKey.fromHex('your_private_key_hex'),
479
- delegatorUrl: 'https://delegator.example.com',
526
+ arkServerUrl: 'https://arkade.computer',
527
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
528
+ delegatorUrl: 'http://localhost:7001',
480
529
  })
481
530
  ```
482
531
 
@@ -500,9 +549,9 @@ console.log('Fee address:', info.delegatorAddress)
500
549
  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
550
 
502
551
  ```typescript
503
- import { BIP322, SingleKey } from '@arkade-os/sdk'
552
+ import { BIP322, MnemonicIdentity } from '@arkade-os/sdk'
504
553
 
505
- const identity = SingleKey.fromHex('your_private_key_hex')
554
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
506
555
 
507
556
  // Sign a message (P2TR key-spend)
508
557
  const signature = await BIP322.sign('Hello Bitcoin!', identity)
@@ -520,6 +569,23 @@ BIP322.verify('Hello Bitcoin!', sig, '1A1zP1...') // legacy P2PKH
520
569
  ```typescript
521
570
  // Get transaction history
522
571
  const history = await wallet.getTransactionHistory()
572
+ /*
573
+ {
574
+ key: {
575
+ boardingTxid: string;
576
+ commitmentTxid: string;
577
+ arkTxid: string;
578
+ };
579
+ type: "SENT" | "RECEIVED";
580
+ amount: number;
581
+ settled: boolean;
582
+ createdAt: number;
583
+ assets?: Array<{
584
+ assetId: string,
585
+ amount: number
586
+ }>
587
+ }
588
+ */
523
589
  ```
524
590
 
525
591
  ### Offboarding
@@ -527,20 +593,25 @@ const history = await wallet.getTransactionHistory()
527
593
  Collaborative exit or "offboarding" allows you to withdraw your virtual funds to an on-chain address:
528
594
 
529
595
  ```typescript
530
- import { Ramps } from '@arkade-os/sdk'
596
+ import { Wallet, MnemonicIdentity, Ramps } from '@arkade-os/sdk'
597
+
598
+ const wallet = await Wallet.create({
599
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
600
+ arkServerUrl: 'https://arkade.computer'
601
+ })
531
602
 
532
603
  // Get fee information from the server
533
- const info = await wallet.arkProvider.getInfo();
604
+ const { fees } = await wallet.arkProvider.getInfo();
534
605
 
535
606
  const exitTxid = await new Ramps(wallet).offboard(
536
- onchainAddress,
537
- info.fees
607
+ 'bc1p...',
608
+ fees
538
609
  );
539
610
  ```
540
611
 
541
612
  ### Unilateral Exit
542
613
 
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:
614
+ 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
615
 
545
616
  1. **Unrolling**: Broadcasting the transaction chain from off-chain back to on-chain
546
617
  2. **Completing the exit**: Spending the unrolled VTXOs after the timelock expires
@@ -548,10 +619,10 @@ Unilateral exit allows you to withdraw your funds from the Ark protocol back to
548
619
  #### Step 1: Unrolling VTXOs
549
620
 
550
621
  ```typescript
551
- import { Unroll, OnchainWallet, SingleKey } from '@arkade-os/sdk'
622
+ import { MnemonicIdentity, OnchainWallet, Unroll } from '@arkade-os/sdk'
552
623
 
553
624
  // Create an identity for the onchain wallet
554
- const onchainIdentity = SingleKey.fromHex('your_onchain_private_key_hex');
625
+ const onchainIdentity = MnemonicIdentity.fromMnemonic('abandon abandon...')
555
626
 
556
627
  // Create an onchain wallet to pay for P2A outputs in VTXO branches
557
628
  // OnchainWallet implements the AnchorBumper interface
@@ -643,15 +714,13 @@ bus.start()
643
714
 
644
715
  ```typescript
645
716
  // app.ts
646
- import { ServiceWorkerWallet, SingleKey } from '@arkade-os/sdk'
647
-
648
- const identity = SingleKey.fromHex('your_private_key_hex')
717
+ import { ServiceWorkerWallet, MnemonicIdentity } from '@arkade-os/sdk'
649
718
 
650
719
  // One-liner: registers the SW, initializes the MessageBus, and creates the wallet
651
720
  const wallet = await ServiceWorkerWallet.setup({
652
721
  serviceWorkerPath: '/service-worker.js',
653
- arkServerUrl: 'https://mutinynet.arkade.sh',
654
- identity,
722
+ arkServerUrl: 'https://arkade.computer',
723
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
655
724
  })
656
725
 
657
726
  // Use like any other wallet — calls are proxied to the service worker
@@ -677,12 +746,9 @@ differ in orchestration and communication.
677
746
  See the platform READMEs for architecture details, runtime flow, and usage
678
747
  examples.
679
748
 
680
-
681
-
682
749
  ### Repositories (Storage)
683
750
 
684
- The `StorageAdapter` API is deprecated. Use repositories instead. If you omit
685
- `storage`, the SDK uses IndexedDB repositories with the default database name.
751
+ The `StorageAdapter` API is deprecated. Use repositories instead. If you omit `storage`, the SDK uses IndexedDB repositories with the default database name.
686
752
 
687
753
  #### Migration from v1 StorageAdapter
688
754
 
@@ -778,7 +844,7 @@ See [examples/node/multiple-wallets.ts](examples/node/multiple-wallets.ts) for
778
844
  a full working example using `better-sqlite3`.
779
845
 
780
846
  ```typescript
781
- import { SingleKey, Wallet } from '@arkade-os/sdk'
847
+ import { MnemonicIdentity, Wallet } from '@arkade-os/sdk'
782
848
  import { SQLiteWalletRepository, SQLiteContractRepository, SQLExecutor } from '@arkade-os/sdk/repositories/sqlite'
783
849
  import Database from 'better-sqlite3'
784
850
 
@@ -792,8 +858,8 @@ const executor: SQLExecutor = {
792
858
  }
793
859
 
794
860
  const wallet = await Wallet.create({
795
- identity: SingleKey.fromHex('your_private_key_hex'),
796
- arkServerUrl: 'https://mutinynet.arkade.sh',
861
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
862
+ arkServerUrl: 'https://arkade.computer',
797
863
  storage: {
798
864
  walletRepository: new SQLiteWalletRepository(executor),
799
865
  contractRepository: new SQLiteContractRepository(executor),
@@ -811,7 +877,7 @@ import { RealmWalletRepository, RealmContractRepository, ArkRealmSchemas } from
811
877
  const realm = await Realm.open({ schema: [...ArkRealmSchemas, ...yourSchemas] })
812
878
  const wallet = await Wallet.create({
813
879
  identity,
814
- arkServerUrl: 'https://mutinynet.arkade.sh',
880
+ arkServerUrl: 'https://arkade.computer',
815
881
  storage: {
816
882
  walletRepository: new RealmWalletRepository(realm),
817
883
  contractRepository: new RealmContractRepository(realm),
@@ -825,11 +891,11 @@ In the browser, the SDK defaults to IndexedDB repositories when no `storage`
825
891
  is provided:
826
892
 
827
893
  ```typescript
828
- import { SingleKey, Wallet } from '@arkade-os/sdk'
894
+ import { MnemonicIdentity, Wallet } from '@arkade-os/sdk'
829
895
 
830
896
  const wallet = await Wallet.create({
831
- identity: SingleKey.fromHex('your_private_key_hex'),
832
- arkServerUrl: 'https://mutinynet.arkade.sh',
897
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
898
+ arkServerUrl: 'https://arkade.computer',
833
899
  // Uses IndexedDB by default in the browser
834
900
  })
835
901
  ```
@@ -841,14 +907,15 @@ For ephemeral storage (no persistence), pass the in-memory repositories:
841
907
 
842
908
  ```typescript
843
909
  import {
910
+ MnemonicIdentity,
911
+ Wallet,
844
912
  InMemoryWalletRepository,
845
- InMemoryContractRepository,
846
- Wallet
913
+ InMemoryContractRepository
847
914
  } from '@arkade-os/sdk'
848
915
 
849
916
  const wallet = await Wallet.create({
850
- identity,
851
- arkServerUrl: 'https://mutinynet.arkade.sh',
917
+ identity: MnemonicIdentity.fromMnemonic('abandon abandon...'),
918
+ arkServerUrl: 'https://arkade.computer',
852
919
  storage: {
853
920
  walletRepository: new InMemoryWalletRepository(),
854
921
  contractRepository: new InMemoryContractRepository()
@@ -869,7 +936,7 @@ import { EventSource } from "eventsource";
869
936
  (globalThis as any).EventSource = EventSource;
870
937
 
871
938
  // Use dynamic import so the polyfill is set before the SDK evaluates
872
- const { Wallet, SingleKey, Ramps } = await import("@arkade-os/sdk");
939
+ const { Wallet } = await import("@arkade-os/sdk");
873
940
  ```
874
941
 
875
942
  If you also need IndexedDB persistence (e.g. for `WalletRepository`), set up the shim before any SDK import:
@@ -895,16 +962,15 @@ See [`examples/node/multiple-wallets.ts`](examples/node/multiple-wallets.ts) for
895
962
  For React Native and Expo applications where standard EventSource and fetch streaming may not work properly, use the Expo-compatible providers:
896
963
 
897
964
  ```typescript
898
- import { Wallet, SingleKey } from '@arkade-os/sdk'
965
+ import { Wallet, MnemonicIdentity } from '@arkade-os/sdk'
899
966
  import { ExpoArkProvider, ExpoIndexerProvider } from '@arkade-os/sdk/adapters/expo'
900
967
 
901
- const identity = SingleKey.fromHex('your_private_key_hex')
968
+ const identity = MnemonicIdentity.fromMnemonic('abandon abandon...')
902
969
 
903
970
  const wallet = await Wallet.create({
904
971
  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
972
+ arkProvider: new ExpoArkProvider('https://arkade.computer'), // For settlement events and transactions streaming
973
+ indexerProvider: new ExpoIndexerProvider('https://arkade.computer'), // For address subscriptions and VTXO updates
908
974
  })
909
975
 
910
976
  // use expo/fetch for streaming support (SSE)
@@ -933,9 +999,9 @@ const executor = {
933
999
 
934
1000
  const wallet = await Wallet.create({
935
1001
  identity,
936
- arkServerUrl: 'https://mutinynet.arkade.sh',
937
- arkProvider: new ExpoArkProvider('https://mutinynet.arkade.sh'),
938
- indexerProvider: new ExpoIndexerProvider('https://mutinynet.arkade.sh'),
1002
+ arkServerUrl: 'https://arkade.computer',
1003
+ arkProvider: new ExpoArkProvider('https://arkade.computer'),
1004
+ indexerProvider: new ExpoIndexerProvider('https://arkade.computer'),
939
1005
  storage: {
940
1006
  walletRepository: new SQLiteWalletRepository(executor),
941
1007
  contractRepository: new SQLiteContractRepository(executor),
@@ -958,7 +1024,7 @@ if (!global.crypto) global.crypto = {} as any;
958
1024
  global.crypto.getRandomValues = Crypto.getRandomValues;
959
1025
 
960
1026
  // Now import the SDK
961
- import { Wallet, SingleKey } from '@arkade-os/sdk';
1027
+ import { Wallet, MnemonicIdentity } from '@arkade-os/sdk';
962
1028
  import { ExpoArkProvider, ExpoIndexerProvider } from '@arkade-os/sdk/adapters/expo';
963
1029
  ```
964
1030
 
@@ -1069,7 +1135,7 @@ await wallet.contractRepository.saveToContractCollection(
1069
1135
  const swaps = await wallet.contractRepository.getContractCollection('swaps')
1070
1136
  ```
1071
1137
 
1072
- _For complete API documentation, visit our [TypeScript documentation](https://arkade-os.github.io/ts-sdk/)._
1138
+ _For complete API documentation, visit our [TypeDoc documentation](https://arkade-os.github.io/ts-sdk/)._
1073
1139
 
1074
1140
  ## Development
1075
1141