@utexo/rgb-sdk 1.0.1

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 ADDED
@@ -0,0 +1,521 @@
1
+
2
+ # RGB SDK v2 Overview
3
+
4
+ This is the underlying SDK used by RGB client applications. It provides a complete set of TypeScript/Node.js bindings for managing RGB-based transfers using **rgb-protocol libraries**
5
+
6
+ > **RGB Protocol**: This SDK uses the [`rgb-lib`](https://github.com/RGB-Tools/rgb-lib) binding library to interact with the RGB protocol. All operations are performed locally, providing full control over wallet data and operations.
7
+ >
8
+ > **Migrating from v1?** If you're upgrading from RGB SDK v1 (using RGB Node server), see the [Migration Guide](./MIGRATION.md) for step-by-step instructions on moving your wallet state to local storage.
9
+
10
+ ---
11
+
12
+ ## 🧰 What You Can Do with This Library
13
+
14
+ With this SDK, developers can:
15
+
16
+ - Generate RGB invoices
17
+ - Create and manage UTXOs
18
+ - Sign PSBTs using local private keys or hardware signing flows
19
+ - Fetch asset balances, transfer status, and other RGB-related state
20
+
21
+ ---
22
+
23
+ ## ⚙️ Capabilities of `@utexo/rgb-sdk` (via `WalletManager`)
24
+
25
+ | Method | Description |
26
+ |--------|-------------|
27
+ | `generateKeys(network?)` | Generate new wallet keys (mnemonic, xpubs, master fingerprint) - top-level function |
28
+ | `restoreFromBackup(params)` | High-level function to restore wallet from backup - top-level function |
29
+ | `deriveKeysFromMnemonic(network, mnemonic)` | Derive wallet keys (xpub/xpriv) from existing mnemonic |
30
+ | `deriveKeysFromSeed(network, seed)` | Derive wallet keys (xpub/xpriv) directly from a BIP39 seed |
31
+ | `registerWallet()` | Register wallet (synchronous) |
32
+ | `getBtcBalance()` | Get on-chain BTC balance (synchronous) |
33
+ | `getAddress()` | Get a derived deposit address (synchronous) |
34
+ | `listUnspents()` | List unspent UTXOs |
35
+ | `listAssets()` | List RGB assets held (synchronous) |
36
+ | `getAssetBalance(assetId)` | Get balance for a specific asset |
37
+ | `createUtxosBegin({ upTo, num, size, feeRate })` | Start creating new UTXOs |
38
+ | `createUtxosEnd({ signedPsbt, skipSync? })` | Finalize UTXO creation with a signed PSBT |
39
+ | `blindReceive({ assetId, amount, minConfirmations?, durationSeconds? })` | Generate blinded UTXO for receiving |
40
+ | `witnessReceive({ assetId, amount, minConfirmations?, durationSeconds? })` | Generate witness UTXO for receiving |
41
+ | `issueAssetNia({...})` | Issue a new Non-Inflationary Asset |
42
+ | `signPsbt(psbt, mnemonic?)` | Sign PSBT using mnemonic and BDK (async) |
43
+ | `signMessage(message, options?)` | Produce a Schnorr signature for an arbitrary message |
44
+ | `verifyMessage(message, signature, options?)` | Verify Schnorr message signatures using wallet keys or provided public key |
45
+ | `refreshWallet()` | Sync and refresh wallet state |
46
+ | `syncWallet()` | Trigger wallet sync without additional refresh logic |
47
+ | `listTransactions()` | List BTC-level transactions (synchronous) |
48
+ | `listTransfers(assetId?)` | List RGB transfer history for asset (synchronous) |
49
+ | `failTransfers(params)` | Mark waiting transfers as failed |
50
+ | `deleteTransfers(params)` | Delete transfers from wallet |
51
+ | `sendBegin(...)` | Prepare a transfer (build unsigned PSBT) |
52
+ | `sendEnd({ signedPsbt, skipSync? })` | Submit signed PSBT to complete transfer |
53
+ | `sendBtcBegin(params)` | Begin Bitcoin send operation (returns PSBT) |
54
+ | `sendBtcEnd(params)` | Complete Bitcoin send operation with signed PSBT |
55
+ | `send(...)` | Complete send operation: begin → sign → end |
56
+ | `createBackup({ backupPath, password })` | Create an encrypted wallet backup (backupPath required, filename includes master fingerprint) |
57
+ | `restoreFromBackup({ backupFilePath, password, dataDir })` | Restore wallet state from a backup file (top-level function, call before creating wallet) |
58
+
59
+ ---
60
+
61
+ ## 🧩 Notes for Custom Integration
62
+
63
+ - All RGB operations are handled locally using the `RGBLibClient` class, which wraps the native `rgb-lib` library.
64
+ - The `signPsbt` method demonstrates how to integrate a signing flow using `bdk-wasm`. This can be replaced with your own HSM or hardware wallet integration if needed.
65
+ - By using this SDK, developers have full control over:
66
+ - Transfer orchestration
67
+ - UTXO selection
68
+ - Invoice lifecycle
69
+ - Signing policy
70
+ - Wallet data storage (via `dataDir` parameter)
71
+
72
+ This pattern enables advanced use cases, such as:
73
+
74
+ - Integrating with third-party identity/auth layers
75
+ - Applying custom fee logic or batching
76
+ - Implementing compliance and audit tracking
77
+ - Full local wallet management without external server dependencies
78
+
79
+ ---
80
+
81
+ ## Getting Started
82
+
83
+ ### Prerequisites
84
+
85
+ This SDK uses `rgb-protocol libraries`. All operations are performed locally.
86
+
87
+ ### Default Endpoints
88
+
89
+ The SDK uses default endpoints for RGB transport and Bitcoin indexing. These are automatically used if not specified:
90
+
91
+ **Transport Endpoint** (RGB protocol communication):
92
+
93
+ - Default: `rpcs://proxy.iriswallet.com/0.2/json-rpc`
94
+
95
+ **Indexer URLs** (Bitcoin blockchain data):
96
+
97
+ - **Mainnet**: `ssl://electrum.iriswallet.com:50003`
98
+ - **Testnet**: `ssl://electrum.iriswallet.com:50013`
99
+ - **Testnet4**: `ssl://electrum.iriswallet.com:50053`
100
+ - **Signet**: `tcp://46.224.75.237:50001`
101
+ - **Regtest**: `tcp://regtest.thunderstack.org:50001`
102
+
103
+ These defaults can be overridden by providing `transportEndpoint` and `indexerUrl` parameters when initializing `WalletManager`.
104
+
105
+ ### Installation
106
+
107
+ ```bash
108
+ npm install @utexo/rgb-sdk
109
+ ```
110
+
111
+ ### Browser Compatibility
112
+
113
+ This SDK is browser-compatible but requires polyfills for Node.js built-in modules. The SDK uses WebAssembly modules and dynamically loads dependencies based on the environment.
114
+
115
+ #### Required Polyfills
116
+
117
+ For React/Next.js applications, you'll need to configure webpack to polyfill Node.js modules. Install the required polyfills:
118
+
119
+ ```bash
120
+ npm install --save-dev crypto-browserify stream-browserify buffer process path-browserify
121
+ ```
122
+
123
+ #### CRACO Configuration (React with Create React App)
124
+
125
+ If you're using Create React App with CRACO, create a `craco.config.js` file:
126
+
127
+ ```javascript
128
+ const path = require('path');
129
+ const webpack = require('webpack');
130
+
131
+ module.exports = {
132
+ webpack: {
133
+ alias: {
134
+ "@": path.resolve(__dirname, "src/"),
135
+ },
136
+ configure: (webpackConfig) => {
137
+ webpackConfig.resolve = webpackConfig.resolve || {};
138
+ webpackConfig.resolve.fallback = {
139
+ ...(webpackConfig.resolve.fallback || {}),
140
+ crypto: require.resolve('crypto-browserify'),
141
+ 'node:crypto': require.resolve('crypto-browserify'),
142
+ stream: require.resolve('stream-browserify'),
143
+ buffer: require.resolve('buffer'),
144
+ process: require.resolve('process/browser'),
145
+ path: require.resolve('path-browserify'),
146
+ 'node:path': require.resolve('path-browserify'),
147
+ fs: false,
148
+ module: false,
149
+ };
150
+
151
+ // WASM rule for .wasm files
152
+ const wasmRule = { test: /\.wasm$/, type: 'webassembly/sync' };
153
+ const oneOf = webpackConfig.module?.rules?.find(r => Array.isArray(r.oneOf))?.oneOf;
154
+ if (oneOf) {
155
+ const assetIdx = oneOf.findIndex(r => r.type === 'asset/resource');
156
+ if (assetIdx >= 0) oneOf.splice(assetIdx, 0, wasmRule);
157
+ else oneOf.unshift(wasmRule);
158
+ } else {
159
+ webpackConfig.module = webpackConfig.module || {};
160
+ webpackConfig.module.rules = [wasmRule, ...(webpackConfig.module.rules || [])];
161
+ }
162
+
163
+ webpackConfig.experiments = {
164
+ ...webpackConfig.experiments,
165
+ asyncWebAssembly: true,
166
+ topLevelAwait: true,
167
+ syncWebAssembly: true,
168
+ layers: true,
169
+ };
170
+
171
+ webpackConfig.plugins = (webpackConfig.plugins || []).concat([
172
+ new webpack.ProvidePlugin({
173
+ Buffer: ['buffer', 'Buffer'],
174
+ process: ['process'],
175
+ }),
176
+ ]);
177
+
178
+ return webpackConfig;
179
+ },
180
+ },
181
+ };
182
+ ```
183
+
184
+ #### Dynamic Import in Browser
185
+
186
+ Use dynamic import to ensure WASM modules load correctly in browser environments:
187
+
188
+ ```javascript
189
+ // Dynamic import ensures the WASM/glue load together
190
+ const sdk = await import('@utexo/rgb-sdk');
191
+
192
+ const { WalletManager, generateKeys } = sdk;
193
+
194
+ // Use the SDK normally
195
+ const keys = generateKeys('testnet');
196
+ const wallet = new WalletManager({
197
+ xpubVan: keys.accountXpubVanilla,
198
+ xpubCol: keys.accountXpubColored,
199
+ masterFingerprint: keys.masterFingerprint,
200
+ mnemonic: keys.mnemonic,
201
+ network: 'testnet',
202
+ transportEndpoint: 'rpcs://proxy.iriswallet.com/0.2/json-rpc',
203
+ indexerUrl: 'ssl://electrum.iriswallet.com:50013'
204
+ });
205
+ ```
206
+
207
+ ### Important: WASM Module Support
208
+
209
+ This SDK uses WebAssembly modules for cryptographic operations. When running scripts, you may need to use the `--experimental-wasm-modules` flag:
210
+
211
+ ```bash
212
+ node --experimental-wasm-modules your-script.js
213
+ ```
214
+
215
+ **Note**: All npm scripts in this project already include this flag automatically. For browser environments, see the Browser Compatibility section above.
216
+
217
+ ### Basic Usage
218
+
219
+ ```javascript
220
+ const { WalletManager, generateKeys } = require('@utexo/rgb-sdk');
221
+
222
+ // 1. Generate wallet keys (synchronous)
223
+ const keys = generateKeys('testnet');
224
+ console.log('Master Fingerprint:', keys.masterFingerprint);
225
+ console.log('Mnemonic:', keys.mnemonic); // Store securely!
226
+
227
+ // 2. Initialize wallet (constructor-based)
228
+ const wallet = new WalletManager({
229
+ xpubVan: keys.accountXpubVanilla,
230
+ xpubCol: keys.accountXpubColored,
231
+ masterFingerprint: keys.masterFingerprint,
232
+ mnemonic: keys.mnemonic,
233
+ network: 'testnet',
234
+ transportEndpoint: 'rpcs://proxy.iriswallet.com/0.2/json-rpc',
235
+ indexerUrl: 'ssl://electrum.iriswallet.com:50013',
236
+ dataDir: './wallet-data' // Optional: defaults to temp directory
237
+ });
238
+
239
+ // 3. Register wallet (synchronous)
240
+ const { address } = wallet.registerWallet();
241
+ console.log('Wallet address:', address);
242
+
243
+ // 4. Check balance (synchronous)
244
+ const balance = wallet.getBtcBalance();
245
+ console.log('BTC Balance:', balance);
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Core Workflows
251
+
252
+ ### Wallet Initialization
253
+
254
+ ```javascript
255
+ const { WalletManager, generateKeys, restoreFromBackup } = require('@utexo/rgb-sdk');
256
+
257
+ // Generate new wallet keys (synchronous)
258
+ const keys = generateKeys('testnet');
259
+
260
+ // Initialize wallet with keys (constructor-based - recommended)
261
+ const wallet = new WalletManager({
262
+ xpubVan: keys.accountXpubVanilla,
263
+ xpubCol: keys.accountXpubColored,
264
+ masterFingerprint: keys.masterFingerprint,
265
+ mnemonic: keys.mnemonic,
266
+ network: 'testnet', // 'mainnet', 'testnet', 'signet', or 'regtest'
267
+ transportEndpoint: 'rpcs://proxy.iriswallet.com/0.2/json-rpc',
268
+ indexerUrl: 'ssl://electrum.iriswallet.com:50013',
269
+ dataDir: './wallet-data' // Optional: defaults to temp directory
270
+ });
271
+
272
+ // Register wallet (synchronous)
273
+ wallet.registerWallet();
274
+
275
+ // Alternative: Restore wallet from backup (must be called before creating wallet)
276
+ restoreFromBackup({
277
+ backupFilePath: './backup/abc123.backup',
278
+ password: 'your-password',
279
+ dataDir: './restored-wallet-data'
280
+ });
281
+
282
+ // Then create wallet pointing to restored directory
283
+ const restoredWallet = new WalletManager({
284
+ xpubVan: keys.accountXpubVanilla,
285
+ xpubCol: keys.accountXpubColored,
286
+ masterFingerprint: keys.masterFingerprint,
287
+ mnemonic: keys.mnemonic,
288
+ network: 'testnet',
289
+ dataDir: './restored-wallet-data' // Point to restored directory
290
+ });
291
+ ```
292
+
293
+ ### UTXO Management
294
+
295
+ ```javascript
296
+ // Step 1: Begin UTXO creation
297
+ const psbt = wallet.createUtxosBegin({
298
+ upTo: true,
299
+ num: 5,
300
+ size: 1000,
301
+ feeRate: 1
302
+ });
303
+
304
+ // Step 2: Sign the PSBT (async operation)
305
+ const signedPsbt = await wallet.signPsbt(psbt);
306
+
307
+ // Step 3: Finalize UTXO creation
308
+ const utxosCreated = wallet.createUtxosEnd({ signedPsbt });
309
+ console.log(`Created ${utxosCreated} UTXOs`);
310
+ ```
311
+
312
+ ### Asset Issuance
313
+
314
+ ```javascript
315
+ // Issue a new NIA
316
+ const asset = await wallet.issueAssetNia({
317
+ ticker: "USDT",
318
+ name: "Tether USD",
319
+ amounts: [1000, 500],
320
+ precision: 6
321
+ });
322
+
323
+ console.log('Asset issued:', asset.asset?.assetId);
324
+ ```
325
+
326
+ ### Asset Transfers
327
+
328
+ ```javascript
329
+ // Create blind receive for receiving wallet
330
+ const receiveData = receiverWallet.blindReceive({
331
+ assetId: assetId,
332
+ amount: 100,
333
+ minConfirmations: 3, // Optional, default: 3
334
+ durationSeconds: 2000 // Optional, default: 2000
335
+ });
336
+
337
+ // Step 1: Begin asset transfer
338
+ const sendPsbt = senderWallet.sendBegin({
339
+ invoice: receiveData.invoice,
340
+ feeRate: 1,
341
+ minConfirmations: 1
342
+ });
343
+
344
+ // Step 2: Sign the PSBT (async operation)
345
+ const signedSendPsbt = await senderWallet.signPsbt(sendPsbt);
346
+
347
+ // Step 3: Finalize transfer
348
+ const sendResult = senderWallet.sendEnd({
349
+ signedPsbt: signedSendPsbt,
350
+ skipSync: false // Optional, default: false
351
+ });
352
+
353
+ // Alternative: Complete send in one call
354
+ const sendResult2 = await senderWallet.send({
355
+ invoice: receiveData.invoice,
356
+ feeRate: 1,
357
+ minConfirmations: 1
358
+ });
359
+
360
+ // Refresh both wallets to sync the transfer
361
+ senderWallet.refreshWallet();
362
+ receiverWallet.refreshWallet();
363
+ ```
364
+
365
+ ### Balance and Asset Management
366
+
367
+ ```javascript
368
+ // Get BTC balance (synchronous)
369
+ const btcBalance = wallet.getBtcBalance();
370
+
371
+ // List all assets (synchronous)
372
+ const assets = wallet.listAssets();
373
+
374
+ // Get specific asset balance
375
+ const assetBalance = wallet.getAssetBalance(assetId);
376
+
377
+ // List unspent UTXOs
378
+ const unspents = wallet.listUnspents();
379
+
380
+ // List transactions (synchronous)
381
+ const transactions = wallet.listTransactions();
382
+
383
+ // List transfers for specific asset (synchronous)
384
+ const transfers = wallet.listTransfers(assetId);
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Setup wallet and issue asset
390
+
391
+ ```javascript
392
+ const { WalletManager, generateKeys } = require('@utexo/rgb-sdk');
393
+
394
+ async function demo() {
395
+ // 1. Generate and initialize wallet
396
+ const keys = generateKeys('testnet');
397
+ const wallet = new WalletManager({
398
+ xpubVan: keys.accountXpubVanilla,
399
+ xpubCol: keys.accountXpubColored,
400
+ masterFingerprint: keys.masterFingerprint,
401
+ mnemonic: keys.mnemonic,
402
+ network: 'testnet',
403
+ transportEndpoint: 'rpcs://proxy.iriswallet.com/0.2/json-rpc',
404
+ indexerUrl: 'ssl://electrum.iriswallet.com:50013'
405
+ });
406
+
407
+ // 2. Register wallet (synchronous)
408
+ const { address } = wallet.registerWallet();
409
+
410
+ // TODO: Send some BTC to this address for fees and UTXO creation
411
+ const balance = wallet.getBtcBalance();
412
+
413
+ // 4. Create UTXOs
414
+ const psbt = wallet.createUtxosBegin({
415
+ upTo: true,
416
+ num: 5,
417
+ size: 1000,
418
+ feeRate: 1
419
+ });
420
+ const signedPsbt = await wallet.signPsbt(psbt); // Async operation
421
+ const utxosCreated = wallet.createUtxosEnd({ signedPsbt });
422
+
423
+ // 5. Issue asset
424
+ const asset = await wallet.issueAssetNia({
425
+ ticker: "DEMO",
426
+ name: "Demo Token",
427
+ amounts: [1000],
428
+ precision: 2
429
+ });
430
+
431
+ // 6. List assets and balances (synchronous)
432
+ const assets = wallet.listAssets();
433
+ const assetBalance = wallet.getAssetBalance(asset.asset?.assetId);
434
+
435
+ // Wallet is ready to send/receive RGB assets
436
+ }
437
+ ```
438
+
439
+ ---
440
+
441
+ ## Security
442
+
443
+ ### Key Management
444
+
445
+ ```javascript
446
+ const { generateKeys, deriveKeysFromMnemonic } = require('@utexo/rgb-sdk');
447
+
448
+ // Generate new wallet keys (synchronous)
449
+ const keys = generateKeys('testnet');
450
+ const mnemonic = keys.mnemonic; // Sensitive - protect at rest
451
+
452
+ // Store mnemonic securely for later restoration
453
+ // Use environment variables for production
454
+ const storedMnemonic = process.env.WALLET_MNEMONIC;
455
+
456
+ // Restore keys from mnemonic
457
+ const restoredKeys = await deriveKeysFromMnemonic('testnet', storedMnemonic);
458
+
459
+ // Sign and verify arbitrary messages (Schnorr signatures)
460
+ const seedHex = process.env.WALLET_SEED_HEX; // 64-byte hex string
461
+ const { signature, accountXpub } = await signMessage({
462
+ message: 'Hello RGB!',
463
+ seed: seedHex,
464
+ network: 'testnet',
465
+ });
466
+ const isValid = await verifyMessage({
467
+ message: 'Hello RGB!',
468
+ signature,
469
+ accountXpub,
470
+ network: 'testnet',
471
+ });
472
+ ```
473
+
474
+ ### Backup and Restore
475
+
476
+ ```javascript
477
+ const { WalletManager, restoreFromBackup, generateKeys } = require('@utexo/rgb-sdk');
478
+
479
+ // Create backup
480
+ const keys = generateKeys('testnet');
481
+ const wallet = new WalletManager({
482
+ xpubVan: keys.accountXpubVanilla,
483
+ xpubCol: keys.accountXpubColored,
484
+ masterFingerprint: keys.masterFingerprint,
485
+ mnemonic: keys.mnemonic,
486
+ network: 'testnet'
487
+ });
488
+
489
+ // Create backup (filename will be <masterFingerprint>.backup)
490
+ const backup = wallet.createBackup({
491
+ backupPath: './backups', // Directory must exist
492
+ password: 'secure-password'
493
+ });
494
+ console.log('Backup created at:', backup.backupPath);
495
+
496
+ // Restore wallet from backup (must be called before creating wallet)
497
+ restoreFromBackup({
498
+ backupFilePath: './backups/abc123.backup',
499
+ password: 'secure-password',
500
+ dataDir: './restored-wallet'
501
+ });
502
+
503
+ // Create wallet pointing to restored directory
504
+ const restoredWallet = new WalletManager({
505
+ xpubVan: keys.accountXpubVanilla,
506
+ xpubCol: keys.accountXpubColored,
507
+ masterFingerprint: keys.masterFingerprint,
508
+ mnemonic: keys.mnemonic,
509
+ network: 'testnet',
510
+ dataDir: './restored-wallet'
511
+ });
512
+ ```
513
+
514
+ ---
515
+
516
+ ## Full Examples
517
+
518
+ For complete working examples demonstrating all features, see:
519
+
520
+ - `example-flow.js` - Complete RGB wallet workflow with two wallets, asset issuance, and transfers
521
+ - `example-basic-usage.js` - Basic wallet operations and asset management