@utexo/rgb-lib-wasm 1.0.6-test → 1.0.6-test2
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 +356 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# rgb-lib-wasm
|
|
2
|
+
|
|
3
|
+
A WebAssembly port of [rgb-lib](https://github.com/UTEXO-Protocol/rgb-lib) for managing RGB protocol wallets in the browser.
|
|
4
|
+
|
|
5
|
+
> **Beta Software** — This library is under active development and has not been audited.
|
|
6
|
+
> APIs may change without notice between versions. Use at your own risk.
|
|
7
|
+
|
|
8
|
+
## What it does
|
|
9
|
+
|
|
10
|
+
rgb-lib-wasm lets you issue, send, and receive RGB assets from a web browser. It replaces the native Rust dependencies (filesystem, SQLite, TCP sockets) with browser-compatible alternatives:
|
|
11
|
+
|
|
12
|
+
- **In-memory database** with IndexedDB persistence
|
|
13
|
+
- **Esplora indexer** over HTTP
|
|
14
|
+
- **Encrypted backup** to a local file or a remote VSS server
|
|
15
|
+
|
|
16
|
+
Supported asset types:
|
|
17
|
+
- **NIA** (Non-Inflatable Asset)
|
|
18
|
+
- **IFA** (Inflatable Fungible Asset).
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- Rust 1.85.0+ with the `wasm32-unknown-unknown` target
|
|
23
|
+
- [wasm-pack](https://rustwasm.github.io/wasm-pack/) 0.14+
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
rustup target add wasm32-unknown-unknown
|
|
27
|
+
cargo install wasm-pack@0.14.0
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Building
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd bindings/wasm
|
|
34
|
+
./build.sh
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This produces the `pkg/` directory containing an npm-ready package (`rgb_lib_wasm.js`, `.d.ts` types, and the `.wasm` binary).
|
|
38
|
+
|
|
39
|
+
### Trying the examples
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd bindings/wasm
|
|
43
|
+
python3 -m http.server 8000
|
|
44
|
+
# Open http://localhost:8000/examples/index.html
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The `examples/` folder contains interactive pages that cover the full API, split by topic:
|
|
48
|
+
|
|
49
|
+
| Page | Description |
|
|
50
|
+
|------|-------------|
|
|
51
|
+
| [`index.html`](bindings/wasm/examples/index.html) | Quick start guide + automated "Run All" flow |
|
|
52
|
+
| [`wallet.html`](bindings/wasm/examples/wallet.html) | Key management, wallet creation, go online, fund, create UTXOs, wallet state queries, fee estimation |
|
|
53
|
+
| [`bitcoin.html`](bindings/wasm/examples/bitcoin.html) | Send BTC, drain wallet, PSBT sign/finalize utilities |
|
|
54
|
+
| [`rgb.html`](bindings/wasm/examples/rgb.html) | Issue NIA/IFA, blind/witness receive, send RGB, inflate IFA, refresh/fail/delete transfers |
|
|
55
|
+
| [`backup.html`](bindings/wasm/examples/backup.html) | Local encrypted backup, VSS cloud backup, check proxy URL, error handling tests |
|
|
56
|
+
|
|
57
|
+
All pages share `examples/lib/shared.js` (WASM init, helpers, regtest utilities). Each page is self-contained with its own wallet setup section. Online operations (funding, sending, etc.) require the regtest Docker services — see [DEV-ENVIRONMENT.md](DEV-ENVIRONMENT.md) for setup.
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
import init, { generate_keys, restore_keys, check_proxy_url, WasmWallet, WasmInvoice } from './pkg/rgb_lib_wasm.js';
|
|
63
|
+
|
|
64
|
+
await init();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Key generation
|
|
68
|
+
|
|
69
|
+
```javascript
|
|
70
|
+
const keys = generate_keys('Regtest');
|
|
71
|
+
// keys: { mnemonic, account_xpub_vanilla, account_xpub_colored, master_fingerprint }
|
|
72
|
+
|
|
73
|
+
const restored = restore_keys('Regtest', keys.mnemonic);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Creating a wallet
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const walletData = {
|
|
80
|
+
data_dir: ':memory:',
|
|
81
|
+
bitcoin_network: 'Regtest',
|
|
82
|
+
database_type: 'Sqlite',
|
|
83
|
+
max_allocations_per_utxo: 5,
|
|
84
|
+
account_xpub_vanilla: keys.account_xpub_vanilla,
|
|
85
|
+
account_xpub_colored: keys.account_xpub_colored,
|
|
86
|
+
mnemonic: keys.mnemonic,
|
|
87
|
+
master_fingerprint: keys.master_fingerprint,
|
|
88
|
+
vanilla_keychain: null,
|
|
89
|
+
supported_schemas: ['Nia', 'Ifa'],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// create() restores state from IndexedDB if available
|
|
93
|
+
const wallet = await WasmWallet.create(JSON.stringify(walletData));
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Going online
|
|
97
|
+
|
|
98
|
+
```javascript
|
|
99
|
+
const online = await wallet.go_online(true, 'http://localhost:8094/regtest/api');
|
|
100
|
+
await wallet.sync(online);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Creating UTXOs
|
|
104
|
+
|
|
105
|
+
RGB allocations live on UTXOs. Before issuing or receiving assets you need colored UTXOs:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
const unsignedPsbt = await wallet.create_utxos_begin(online, true, 5, 1000, 1n, false);
|
|
109
|
+
const signedPsbt = wallet.sign_psbt(unsignedPsbt);
|
|
110
|
+
const count = await wallet.create_utxos_end(online, signedPsbt, false);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Issuing assets
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
// NIA (fixed supply)
|
|
117
|
+
const nia = wallet.issue_asset_nia('TICK', 'My Token', 0, [1000]);
|
|
118
|
+
|
|
119
|
+
// IFA (inflatable supply)
|
|
120
|
+
const ifa = wallet.issue_asset_ifa('IFAT', 'Inflatable', 0, [1000], [500], 1, undefined);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Sending RGB assets
|
|
124
|
+
|
|
125
|
+
All send operations follow a three-step PSBT workflow: **begin** (build unsigned PSBT) → **sign** → **end** (broadcast).
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
const recipientMap = {
|
|
129
|
+
[assetId]: [{
|
|
130
|
+
recipient_id: invoiceString,
|
|
131
|
+
witness_data: { amount_sat: 1000, blinding: null },
|
|
132
|
+
amount: 100,
|
|
133
|
+
transport_endpoints: ['rpc://localhost:3000/json-rpc'],
|
|
134
|
+
}]
|
|
135
|
+
};
|
|
136
|
+
const psbt = await wallet.send_begin(online, recipientMap, false, 1n, 1);
|
|
137
|
+
const signed = wallet.sign_psbt(psbt);
|
|
138
|
+
const result = await wallet.send_end(online, signed, false);
|
|
139
|
+
// result: { txid, batch_transfer_idx }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Sending BTC
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
const psbt = await wallet.send_btc_begin(online, address, 50000n, 1n, false);
|
|
146
|
+
const signed = wallet.sign_psbt(psbt);
|
|
147
|
+
const txid = await wallet.send_btc_end(online, signed, false);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Receiving assets
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
// Blind receive (UTXO-based)
|
|
154
|
+
const blind = wallet.blind_receive(null, 'Any', null, ['rpc://localhost:3000/json-rpc'], 1);
|
|
155
|
+
// blind: { invoice, recipient_id, expiration_timestamp, ... }
|
|
156
|
+
|
|
157
|
+
// Witness receive (address-based)
|
|
158
|
+
const witness = wallet.witness_receive(null, { Fungible: 100 }, null, ['rpc://localhost:3000/json-rpc'], 1);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Parsing invoices
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const invoice = new WasmInvoice(invoiceString);
|
|
165
|
+
const data = invoice.invoiceData();
|
|
166
|
+
// data: { recipient_id, asset_schema, asset_id, assignment, network, expiration_timestamp, transport_endpoints }
|
|
167
|
+
const str = invoice.invoiceString(); // original string
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Querying wallet state
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
const btcBalance = wallet.get_btc_balance();
|
|
174
|
+
const assetBalance = wallet.get_asset_balance(assetId);
|
|
175
|
+
const metadata = wallet.get_asset_metadata(assetId);
|
|
176
|
+
// metadata: { asset_schema, name, ticker, precision, initial_supply, max_supply, known_circulating_supply, timestamp, ... }
|
|
177
|
+
const assets = wallet.list_assets([]); // all schemas
|
|
178
|
+
const transfers = wallet.list_transfers(null); // all assets
|
|
179
|
+
const unspents = wallet.list_unspents(false);
|
|
180
|
+
const transactions = wallet.list_transactions();
|
|
181
|
+
const address = wallet.get_address();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Fee estimation
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
const feeRate = await wallet.get_fee_estimation(online, 6); // target 6 blocks
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Draining the wallet
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const psbt = await wallet.drain_to_begin(online, destinationAddress, true, 1n);
|
|
194
|
+
const signed = wallet.sign_psbt(psbt);
|
|
195
|
+
const txid = await wallet.drain_to_end(online, signed);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Inflating an IFA asset
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const psbt = await wallet.inflate_begin(online, assetId, [200], 1n, 1);
|
|
202
|
+
const signed = wallet.sign_psbt(psbt);
|
|
203
|
+
const result = await wallet.inflate_end(online, signed);
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Local encrypted backup
|
|
207
|
+
|
|
208
|
+
Wallet state is encrypted with Scrypt + XChaCha20Poly1305 and returned as bytes:
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
// Backup
|
|
212
|
+
const bytes = wallet.backup('my-password');
|
|
213
|
+
// bytes is a Uint8Array — save it as a file download
|
|
214
|
+
|
|
215
|
+
// Check if backup is needed
|
|
216
|
+
const needed = wallet.backup_info(); // true if wallet changed since last backup
|
|
217
|
+
|
|
218
|
+
// Restore (wallet must be created first with the same mnemonic)
|
|
219
|
+
wallet.restore_backup(backupBytes, 'my-password');
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### VSS cloud backup
|
|
223
|
+
|
|
224
|
+
[VSS](https://github.com/lightningdevkit/vss-server) (Versioned Storage Service) provides cloud backup with optimistic locking:
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
// Configure (signing key is a 32-byte hex-encoded secp256k1 secret key)
|
|
228
|
+
wallet.configure_vss_backup('http://vss-server:8082/vss', 'my-store-id', signingKeyHex);
|
|
229
|
+
|
|
230
|
+
// Upload
|
|
231
|
+
const version = await wallet.vss_backup();
|
|
232
|
+
|
|
233
|
+
// Check status
|
|
234
|
+
const info = await wallet.vss_backup_info();
|
|
235
|
+
// info: { backup_exists, server_version, backup_required }
|
|
236
|
+
|
|
237
|
+
// Restore
|
|
238
|
+
await wallet.vss_restore_backup();
|
|
239
|
+
|
|
240
|
+
// Disable
|
|
241
|
+
wallet.disable_vss_backup();
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Transfer management
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
const refreshResult = await wallet.refresh(online, null, [], false);
|
|
248
|
+
const failed = await wallet.fail_transfers(online, null, false, false);
|
|
249
|
+
const deleted = wallet.delete_transfers(null, false);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Utilities
|
|
253
|
+
|
|
254
|
+
```javascript
|
|
255
|
+
// Validate an RGB proxy server
|
|
256
|
+
await check_proxy_url('http://localhost:3000/json-rpc');
|
|
257
|
+
|
|
258
|
+
// PSBT signing and finalization (standalone)
|
|
259
|
+
const signed = wallet.sign_psbt(unsignedPsbtBase64);
|
|
260
|
+
const finalized = wallet.finalize_psbt(signedPsbtBase64);
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## API reference
|
|
264
|
+
|
|
265
|
+
### Standalone functions
|
|
266
|
+
|
|
267
|
+
| Function | Description |
|
|
268
|
+
|----------|-------------|
|
|
269
|
+
| `generate_keys(network)` | Generate a new BIP39 mnemonic and derive xpubs |
|
|
270
|
+
| `restore_keys(network, mnemonic)` | Restore xpubs from a mnemonic |
|
|
271
|
+
| `check_proxy_url(url)` | Validate an RGB proxy server URL |
|
|
272
|
+
|
|
273
|
+
### `WasmInvoice`
|
|
274
|
+
|
|
275
|
+
| Method | Description |
|
|
276
|
+
|--------|-------------|
|
|
277
|
+
| `new(invoiceString)` | Parse and validate an RGB invoice string |
|
|
278
|
+
| `invoiceData()` | Return parsed `InvoiceData` as a JS object |
|
|
279
|
+
| `invoiceString()` | Return the original invoice string |
|
|
280
|
+
|
|
281
|
+
### `WasmWallet` methods
|
|
282
|
+
|
|
283
|
+
| Method | Async | Description |
|
|
284
|
+
|--------|-------|-------------|
|
|
285
|
+
| `new(walletDataJson)` | no | Create wallet (no IndexedDB restore) |
|
|
286
|
+
| `create(walletDataJson)` | yes | Create wallet with IndexedDB restore |
|
|
287
|
+
| `get_wallet_data()` | no | Return WalletData as JS object |
|
|
288
|
+
| `get_address()` | no | Get a new Bitcoin address |
|
|
289
|
+
| `get_btc_balance()` | no | Get BTC balance |
|
|
290
|
+
| `get_asset_balance(assetId)` | no | Get balance for an RGB asset |
|
|
291
|
+
| `get_asset_metadata(assetId)` | no | Get metadata for an RGB asset (name, ticker, precision, supply, etc.) |
|
|
292
|
+
| `list_assets(schemas)` | no | List known RGB assets |
|
|
293
|
+
| `list_transfers(assetId?)` | no | List RGB transfers |
|
|
294
|
+
| `list_unspents(settledOnly)` | no | List unspent outputs with RGB allocations |
|
|
295
|
+
| `list_transactions()` | no | List Bitcoin transactions |
|
|
296
|
+
| `go_online(skipCheck, indexerUrl)` | yes | Connect to an Esplora indexer |
|
|
297
|
+
| `sync(online)` | yes | Sync wallet with indexer |
|
|
298
|
+
| `create_utxos_begin(...)` | yes | Prepare PSBT to create colored UTXOs |
|
|
299
|
+
| `create_utxos_end(online, psbt, skipSync)` | yes | Broadcast UTXO creation PSBT |
|
|
300
|
+
| `issue_asset_nia(ticker, name, precision, amounts)` | no | Issue a Non-Inflatable Asset |
|
|
301
|
+
| `issue_asset_ifa(...)` | no | Issue an Inflatable Fungible Asset |
|
|
302
|
+
| `blind_receive(...)` | no | Create a blind receive invoice |
|
|
303
|
+
| `witness_receive(...)` | no | Create a witness receive invoice |
|
|
304
|
+
| `send_begin(...)` | yes | Prepare RGB send PSBT |
|
|
305
|
+
| `send_end(online, psbt, skipSync)` | yes | Broadcast RGB send PSBT |
|
|
306
|
+
| `send_btc_begin(...)` | yes | Prepare BTC send PSBT |
|
|
307
|
+
| `send_btc_end(online, psbt, skipSync)` | yes | Broadcast BTC send PSBT |
|
|
308
|
+
| `get_fee_estimation(online, blocks)` | yes | Estimate fee rate for target blocks |
|
|
309
|
+
| `drain_to_begin(online, addr, destroyAssets, feeRate)` | yes | Prepare drain PSBT |
|
|
310
|
+
| `drain_to_end(online, psbt)` | yes | Broadcast drain PSBT |
|
|
311
|
+
| `inflate_begin(...)` | yes | Prepare IFA inflation PSBT |
|
|
312
|
+
| `inflate_end(online, psbt)` | yes | Broadcast IFA inflation PSBT |
|
|
313
|
+
| `list_unspents_vanilla(online, minConf, skipSync)` | yes | List non-colored UTXOs |
|
|
314
|
+
| `refresh(online, assetId?, filter, skipSync)` | yes | Refresh pending transfers |
|
|
315
|
+
| `fail_transfers(online, batchIdx?, noAssetOnly, skipSync)` | yes | Fail pending transfers |
|
|
316
|
+
| `delete_transfers(batchIdx?, noAssetOnly)` | no | Delete failed transfers |
|
|
317
|
+
| `sign_psbt(psbt)` | no | Sign a PSBT |
|
|
318
|
+
| `finalize_psbt(psbt)` | no | Finalize a signed PSBT |
|
|
319
|
+
| `backup(password)` | no | Create encrypted backup (returns bytes) |
|
|
320
|
+
| `restore_backup(bytes, password)` | no | Restore from encrypted backup |
|
|
321
|
+
| `backup_info()` | no | Check if backup is needed |
|
|
322
|
+
| `configure_vss_backup(url, storeId, keyHex)` | no | Configure VSS cloud backup |
|
|
323
|
+
| `disable_vss_backup()` | no | Disable VSS cloud backup |
|
|
324
|
+
| `vss_backup()` | yes | Upload backup to VSS server |
|
|
325
|
+
| `vss_restore_backup()` | yes | Restore from VSS server |
|
|
326
|
+
| `vss_backup_info()` | yes | Query VSS backup status |
|
|
327
|
+
|
|
328
|
+
## Cargo features
|
|
329
|
+
|
|
330
|
+
| Feature | Default | Description |
|
|
331
|
+
|---------|---------|-------------|
|
|
332
|
+
| `esplora` | yes | Online operations via Esplora HTTP indexer |
|
|
333
|
+
| `camel_case` | no | camelCase JSON serialization for all types |
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
## Running tests
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Native unit tests (94 tests)
|
|
340
|
+
cargo test --lib
|
|
341
|
+
|
|
342
|
+
# WASM unit tests (headless Firefox)
|
|
343
|
+
wasm-pack test --headless --firefox --release -- --test keys_wasm
|
|
344
|
+
wasm-pack test --headless --firefox --release -- --test wallet_wasm
|
|
345
|
+
|
|
346
|
+
# Integration tests (requires regtest Docker services)
|
|
347
|
+
cd tests && bash regtest.sh start
|
|
348
|
+
cd .. && wasm-pack test --headless --firefox --release -- --test integration_wasm
|
|
349
|
+
cd tests && bash regtest.sh stop
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
See [DEV-ENVIRONMENT.md](DEV-ENVIRONMENT.md) for the full regtest infrastructure setup, CI configuration, Docker Compose details, and troubleshooting.
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT
|
package/package.json
CHANGED