bip-321 0.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/CLAUDE.md ADDED
@@ -0,0 +1,107 @@
1
+ ---
2
+
3
+ Default to using Bun instead of Node.js.
4
+
5
+ - Use `bun <file>` instead of `node <file>` or `ts-node <file>`
6
+ - Use `bun test` instead of `jest` or `vitest`
7
+ - Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
8
+ - Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
9
+ - Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
10
+ - Bun automatically loads .env, so don't use dotenv.
11
+
12
+ ## APIs
13
+
14
+ - `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
15
+ - `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
16
+ - `Bun.redis` for Redis. Don't use `ioredis`.
17
+ - `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
18
+ - `WebSocket` is built-in. Don't use `ws`.
19
+ - Prefer `Bun.file` over `node:fs`'s readFile/writeFile
20
+ - Bun.$`ls` instead of execa.
21
+
22
+ ## Testing
23
+
24
+ Use `bun test` to run tests.
25
+
26
+ ```ts#index.test.ts
27
+ import { test, expect } from "bun:test";
28
+
29
+ test("hello world", () => {
30
+ expect(1).toBe(1);
31
+ });
32
+ ```
33
+
34
+ ## Frontend
35
+
36
+ Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
37
+
38
+ Server:
39
+
40
+ ```ts#index.ts
41
+ import index from "./index.html"
42
+
43
+ Bun.serve({
44
+ routes: {
45
+ "/": index,
46
+ "/api/users/:id": {
47
+ GET: (req) => {
48
+ return new Response(JSON.stringify({ id: req.params.id }));
49
+ },
50
+ },
51
+ },
52
+ // optional websocket support
53
+ websocket: {
54
+ open: (ws) => {
55
+ ws.send("Hello, world!");
56
+ },
57
+ message: (ws, message) => {
58
+ ws.send(message);
59
+ },
60
+ close: (ws) => {
61
+ // handle close
62
+ }
63
+ },
64
+ development: {
65
+ hmr: true,
66
+ console: true,
67
+ }
68
+ })
69
+ ```
70
+
71
+ HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
72
+
73
+ ```html#index.html
74
+ <html>
75
+ <body>
76
+ <h1>Hello, world!</h1>
77
+ <script type="module" src="./frontend.tsx"></script>
78
+ </body>
79
+ </html>
80
+ ```
81
+
82
+ With the following `frontend.tsx`:
83
+
84
+ ```tsx#frontend.tsx
85
+ import React from "react";
86
+
87
+ // import .css files directly and it works
88
+ import './index.css';
89
+
90
+ import { createRoot } from "react-dom/client";
91
+
92
+ const root = createRoot(document.body);
93
+
94
+ export default function Frontend() {
95
+ return <h1>Hello, world!</h1>;
96
+ }
97
+
98
+ root.render(<Frontend />);
99
+ ```
100
+
101
+ Then, run index.ts
102
+
103
+ ```sh
104
+ bun --hot ./index.ts
105
+ ```
106
+
107
+ For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
package/README.md ADDED
@@ -0,0 +1,336 @@
1
+ # BIP-321 Parser
2
+
3
+ A TypeScript/JavaScript library for parsing BIP-321 Bitcoin URI scheme. This library validates and extracts payment information from Bitcoin URIs, supporting multiple payment methods including on-chain addresses, Lightning invoices, BOLT12 offers, and silent payments.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Complete BIP-321 compliance** - Implements the full BIP-321 specification
8
+ - ✅ **Multiple payment methods** - Supports on-chain, Lightning (BOLT11), BOLT12 offers, silent payments, and private payments
9
+ - ✅ **Network detection** - Automatically detects mainnet, testnet, regtest, and signet networks
10
+ - ✅ **Address validation** - Validates Bitcoin addresses (P2PKH, P2SH, Segwit v0, Taproot)
11
+ - ✅ **Lightning invoice validation** - Validates BOLT11 Lightning invoices
12
+ - ✅ **Cross-platform** - Works in Node.js, browsers, and React Native
13
+ - ✅ **TypeScript support** - Fully typed with TypeScript definitions
14
+ - ✅ **Proof of payment** - Supports pop/req-pop parameters for payment callbacks
15
+ - ✅ **Comprehensive error handling** - Clear error messages for invalid URIs
16
+ - ✅ **Full type safety** - Passes strict TypeScript type checking with no errors
17
+
18
+ ## TypeScript Type Safety
19
+
20
+ This library is built with full TypeScript support and passes strict type checking (`tsc --noEmit`) with zero errors. All functions return fully-typed objects, providing excellent IDE autocomplete and compile-time safety.
21
+
22
+ ```typescript
23
+ import { parseBIP321, type BIP321ParseResult, type PaymentMethod } from "bip-321";
24
+
25
+ // Fully typed result with autocomplete support
26
+ const result: BIP321ParseResult = parseBIP321("bitcoin:...");
27
+
28
+ // TypeScript knows all available properties
29
+ result.valid; // boolean
30
+ result.network; // "mainnet" | "testnet" | "regtest" | "signet" | undefined
31
+ result.paymentMethods; // PaymentMethod[]
32
+ result.errors; // string[]
33
+
34
+ // Payment methods are also fully typed
35
+ result.paymentMethods.forEach((method: PaymentMethod) => {
36
+ method.type; // "onchain" | "lightning" | "lno" | "silent-payment" | "private-payment" | "other"
37
+ method.network; // "mainnet" | "testnet" | "regtest" | "signet" | undefined
38
+ method.valid; // boolean
39
+ });
40
+ ```
41
+
42
+ ## Installation
43
+ </text>
44
+
45
+
46
+ ```bash
47
+ bun add bip-321
48
+ ```
49
+
50
+ Or with npm:
51
+
52
+ ```bash
53
+ npm install bip-321
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```typescript
59
+ import { parseBIP321 } from "bip-321";
60
+
61
+ // Parse a simple Bitcoin address
62
+ const result = parseBIP321("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
63
+
64
+ console.log(result.valid); // true
65
+ console.log(result.network); // "mainnet"
66
+ console.log(result.address); // "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
67
+ console.log(result.paymentMethods); // Array of payment methods
68
+ ```
69
+
70
+ ## Usage Examples
71
+
72
+ ### Basic On-Chain Payment
73
+
74
+ ```typescript
75
+ import { parseBIP321 } from "bip-321";
76
+
77
+ const result = parseBIP321("bitcoin:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq");
78
+
79
+ if (result.valid) {
80
+ console.log(`Network: ${result.network}`); // mainnet
81
+ console.log(`Address: ${result.address}`);
82
+ console.log(`Payment methods: ${result.paymentMethods.length}`);
83
+ }
84
+ ```
85
+
86
+ ### Payment with Amount and Label
87
+
88
+ ```typescript
89
+ const result = parseBIP321(
90
+ "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=0.5&label=Donation&message=Thank%20you"
91
+ );
92
+
93
+ console.log(`Amount: ${result.amount} BTC`); // 0.5 BTC
94
+ console.log(`Label: ${result.label}`); // "Donation"
95
+ console.log(`Message: ${result.message}`); // "Thank you"
96
+ ```
97
+
98
+ ### Lightning Invoice with On-Chain Fallback
99
+
100
+ ```typescript
101
+ const result = parseBIP321(
102
+ "bitcoin:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq?lightning=lnbc15u1p3xnhl2pp5..."
103
+ );
104
+
105
+ // Returns 2 payment methods: onchain and lightning
106
+ result.paymentMethods.forEach((method) => {
107
+ console.log(`Type: ${method.type}, Network: ${method.network}, Valid: ${method.valid}`);
108
+ });
109
+ ```
110
+
111
+ ### Lightning-Only Payment
112
+
113
+ ```typescript
114
+ const result = parseBIP321(
115
+ "bitcoin:?lightning=lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3s..."
116
+ );
117
+
118
+ console.log(result.paymentMethods[0].type); // "lightning"
119
+ console.log(result.paymentMethods[0].network); // "mainnet"
120
+ ```
121
+
122
+ ### Multiple Payment Methods
123
+
124
+ ```typescript
125
+ const result = parseBIP321(
126
+ "bitcoin:?lightning=lnbc...&lno=lno1bogusoffer&sp=sp1qsilentpayment"
127
+ );
128
+
129
+ // Returns 3 payment methods: lightning, lno (BOLT12), and silent-payment
130
+ console.log(`Total payment methods: ${result.paymentMethods.length}`);
131
+ ```
132
+
133
+ ### Network-Specific Parameters
134
+
135
+ ```typescript
136
+ // Mainnet and testnet addresses in one URI
137
+ const result = parseBIP321(
138
+ "bitcoin:?bc=bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq&tb=tb1qghfhmd4zh7ncpmxl3qzhmq566jk8ckq4gafnmg"
139
+ );
140
+
141
+ const byNetwork = getPaymentMethodsByNetwork(result);
142
+ console.log(`Mainnet methods: ${byNetwork.mainnet.length}`);
143
+ console.log(`Testnet methods: ${byNetwork.testnet.length}`);
144
+ ```
145
+
146
+ ### Error Handling
147
+
148
+ ```typescript
149
+ const result = parseBIP321("bitcoin:invalidaddress");
150
+
151
+ if (!result.valid) {
152
+ console.log("Errors:");
153
+ result.errors.forEach((error) => console.log(` - ${error}`));
154
+ }
155
+ ```
156
+
157
+ ## API Reference
158
+
159
+ ### `parseBIP321(uri: string): BIP321ParseResult`
160
+
161
+ Parses a BIP-321 URI and returns detailed information about the payment request.
162
+
163
+ **Parameters:**
164
+ - `uri` - The Bitcoin URI string to parse
165
+
166
+ **Returns:** `BIP321ParseResult` object containing:
167
+
168
+ ```typescript
169
+ interface BIP321ParseResult {
170
+ // Basic information
171
+ address?: string; // Main Bitcoin address from URI path
172
+ network?: "mainnet" | "testnet" | "regtest" | "signet";
173
+ amount?: number; // Amount in BTC
174
+ label?: string; // Label for the recipient
175
+ message?: string; // Message describing the transaction
176
+
177
+ // Proof of payment
178
+ pop?: string; // Proof of payment callback URI
179
+ popRequired?: boolean; // Whether pop callback is required
180
+
181
+ // Payment methods
182
+ paymentMethods: PaymentMethod[]; // All available payment methods
183
+
184
+ // Parameters
185
+ requiredParams: string[]; // Unknown required parameters (req-*)
186
+ optionalParams: Record<string, string[]>; // Unknown optional parameters
187
+
188
+ // Validation
189
+ valid: boolean; // Whether the URI is valid
190
+ errors: string[]; // Array of error messages
191
+ }
192
+ ```
193
+
194
+ ### `PaymentMethod` Interface
195
+
196
+ ```typescript
197
+ interface PaymentMethod {
198
+ type: "onchain" | "lightning" | "lno" | "silent-payment" | "private-payment" | "other";
199
+ value: string; // The actual address/invoice value
200
+ network?: "mainnet" | "testnet" | "regtest" | "signet";
201
+ valid: boolean; // Whether this payment method is valid
202
+ error?: string; // Error message if invalid
203
+ }
204
+ ```
205
+
206
+ ### Helper Functions
207
+
208
+ #### `getPaymentMethodsByNetwork(result: BIP321ParseResult)`
209
+
210
+ Groups payment methods by network.
211
+
212
+ ```typescript
213
+ const byNetwork = getPaymentMethodsByNetwork(result);
214
+ // Returns: { mainnet: [], testnet: [], regtest: [], signet: [], unknown: [] }
215
+ ```
216
+
217
+ #### `getValidPaymentMethods(result: BIP321ParseResult)`
218
+
219
+ Returns only valid payment methods.
220
+
221
+ ```typescript
222
+ const valid = getValidPaymentMethods(result);
223
+ // Returns: PaymentMethod[]
224
+ ```
225
+
226
+ #### `formatPaymentMethodsSummary(result: BIP321ParseResult)`
227
+
228
+ Generates a human-readable summary of the parsed URI.
229
+
230
+ ```typescript
231
+ const summary = formatPaymentMethodsSummary(result);
232
+ console.log(summary);
233
+ // Outputs:
234
+ // Valid: true
235
+ // Amount: 0.5 BTC
236
+ // Label: Donation
237
+ // Payment Methods: 2
238
+ // ✓ onchain (mainnet)
239
+ // ✓ lightning (mainnet)
240
+ ```
241
+
242
+ ## Supported Payment Methods
243
+
244
+ | Method | Parameter Key | Description |
245
+ |--------|--------------|-------------|
246
+ | On-chain | `address` or `bc`/`tb`/`bcrt`/`tbs` | Bitcoin addresses (P2PKH, P2SH, Segwit, Taproot) |
247
+ | Lightning | `lightning` | BOLT11 Lightning invoices |
248
+ | BOLT12 | `lno` | Lightning BOLT12 offers |
249
+ | Silent Payments | `sp` | BIP352 Silent Payment addresses |
250
+ | Private Payments | `pay` | BIP351 Private Payment addresses |
251
+
252
+ ## Network Detection
253
+
254
+ The library automatically detects the network from:
255
+
256
+ ### Bitcoin Addresses
257
+ - **Mainnet**: `1...`, `3...`, `bc1...`
258
+ - **Testnet**: `m...`, `n...`, `2...`, `tb1...`
259
+ - **Regtest**: `bcrt1...`
260
+
261
+ ### Lightning Invoices
262
+ - **Mainnet**: `lnbc...`
263
+ - **Testnet**: `lntb...`
264
+ - **Regtest**: `lnbcrt...`
265
+ - **Signet**: `lntbs...`
266
+
267
+ ## Validation Rules
268
+
269
+ The parser enforces BIP-321 validation rules:
270
+
271
+ 1. ✅ URI must start with `bitcoin:` (case-insensitive)
272
+ 2. ✅ Address in URI path must be valid or empty
273
+ 3. ✅ `amount` must be decimal BTC (no commas)
274
+ 4. ✅ `label`, `message`, and `amount` cannot appear multiple times
275
+ 5. ✅ `pop` and `req-pop` cannot both be present
276
+ 6. ✅ Required parameters (`req-*`) must be understood or URI is invalid
277
+ 7. ✅ Network-specific parameters (`bc`, `tb`, etc.) must match address network
278
+ 8. ✅ `pop` URI scheme must not be forbidden (http, https, file, javascript, mailto)
279
+
280
+ ## Browser Usage
281
+
282
+ ```html
283
+ <!DOCTYPE html>
284
+ <html>
285
+ <head>
286
+ <script type="module">
287
+ import { parseBIP321 } from './index.js';
288
+
289
+ const uri = prompt("Enter Bitcoin URI:");
290
+ const result = parseBIP321(uri);
291
+
292
+ if (result.valid) {
293
+ alert(`Valid payment request!\nNetwork: ${result.network}\nMethods: ${result.paymentMethods.length}`);
294
+ } else {
295
+ alert(`Invalid URI:\n${result.errors.join('\n')}`);
296
+ }
297
+ </script>
298
+ </head>
299
+ <body>
300
+ <h1>BIP-321 Parser Demo</h1>
301
+ </body>
302
+ </html>
303
+ ```
304
+
305
+ ## React Native Usage
306
+
307
+ ```typescript
308
+ import { parseBIP321 } from "bip-321";
309
+ import { Alert } from "react-native";
310
+
311
+ function parseQRCode(data: string) {
312
+ const result = parseBIP321(data);
313
+
314
+ if (result.valid) {
315
+ Alert.alert(
316
+ "Payment Request",
317
+ `Network: ${result.network}\nAmount: ${result.amount || 'Not specified'} BTC`
318
+ );
319
+ } else {
320
+ Alert.alert("Invalid QR Code", result.errors.join("\n"));
321
+ }
322
+ }
323
+ ```
324
+
325
+ ## Contributing
326
+
327
+ Contributions are welcome! Please feel free to submit a Pull Request.
328
+
329
+ ## License
330
+
331
+ BSD-2-Clause (same as BIP-321)
332
+
333
+ ## Related
334
+
335
+ - [BIP-321 Specification](https://bips.dev/321/)
336
+ - [BIP-21 (Original)](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki)
package/bun.lock ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "bip-321",
6
+ "dependencies": {
7
+ "@scure/base": "^2.0.0",
8
+ "bitcoinjs-lib": "^7.0.0",
9
+ "bs58check": "^4.0.0",
10
+ "light-bolt11-decoder": "^3.2.0",
11
+ },
12
+ "devDependencies": {
13
+ "@types/bun": "latest",
14
+ },
15
+ "peerDependencies": {
16
+ "typescript": "^5",
17
+ },
18
+ },
19
+ },
20
+ "packages": {
21
+ "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
22
+
23
+ "@scure/base": ["@scure/base@2.0.0", "", {}, "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w=="],
24
+
25
+ "@types/bun": ["@types/bun@1.3.1", "", { "dependencies": { "bun-types": "1.3.1" } }, "sha512-4jNMk2/K9YJtfqwoAa28c8wK+T7nvJFOjxI4h/7sORWcypRNxBpr+TPNaCfVWq70tLCJsqoFwcf0oI0JU/fvMQ=="],
26
+
27
+ "@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="],
28
+
29
+ "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="],
30
+
31
+ "base-x": ["base-x@5.0.1", "", {}, "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg=="],
32
+
33
+ "bech32": ["bech32@2.0.0", "", {}, "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="],
34
+
35
+ "bip174": ["bip174@3.0.0", "", { "dependencies": { "uint8array-tools": "^0.0.9", "varuint-bitcoin": "^2.0.0" } }, "sha512-N3vz3rqikLEu0d6yQL8GTrSkpYb35NQKWMR7Hlza0lOj6ZOlvQ3Xr7N9Y+JPebaCVoEUHdBeBSuLxcHr71r+Lw=="],
36
+
37
+ "bitcoinjs-lib": ["bitcoinjs-lib@7.0.0", "", { "dependencies": { "@noble/hashes": "^1.2.0", "bech32": "^2.0.0", "bip174": "^3.0.0", "bs58check": "^4.0.0", "uint8array-tools": "^0.0.9", "valibot": "^0.38.0", "varuint-bitcoin": "^2.0.0" } }, "sha512-2W6dGXFd1KG3Bs90Bzb5+ViCeSKNIYkCUWZ4cvUzUgwnneiNNZ6Sk8twGNcjlesmxC0JyLc/958QycfpvXLg7A=="],
38
+
39
+ "bs58": ["bs58@6.0.0", "", { "dependencies": { "base-x": "^5.0.0" } }, "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw=="],
40
+
41
+ "bs58check": ["bs58check@4.0.0", "", { "dependencies": { "@noble/hashes": "^1.2.0", "bs58": "^6.0.0" } }, "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g=="],
42
+
43
+ "bun-types": ["bun-types@1.3.1", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-NMrcy7smratanWJ2mMXdpatalovtxVggkj11bScuWuiOoXTiKIu2eVS1/7qbyI/4yHedtsn175n4Sm4JcdHLXw=="],
44
+
45
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
46
+
47
+ "light-bolt11-decoder": ["light-bolt11-decoder@3.2.0", "", { "dependencies": { "@scure/base": "1.1.1" } }, "sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ=="],
48
+
49
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
50
+
51
+ "uint8array-tools": ["uint8array-tools@0.0.9", "", {}, "sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A=="],
52
+
53
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
54
+
55
+ "valibot": ["valibot@0.38.0", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-RCJa0fetnzp+h+KN9BdgYOgtsMAG9bfoJ9JSjIhFHobKWVWyzM3jjaeNTdpFK9tQtf3q1sguXeERJ/LcmdFE7w=="],
56
+
57
+ "varuint-bitcoin": ["varuint-bitcoin@2.0.0", "", { "dependencies": { "uint8array-tools": "^0.0.8" } }, "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog=="],
58
+
59
+ "light-bolt11-decoder/@scure/base": ["@scure/base@1.1.1", "", {}, "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="],
60
+
61
+ "varuint-bitcoin/uint8array-tools": ["uint8array-tools@0.0.8", "", {}, "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g=="],
62
+ }
63
+ }
package/example.ts ADDED
@@ -0,0 +1,161 @@
1
+ import {
2
+ parseBIP321,
3
+ getPaymentMethodsByNetwork,
4
+ getValidPaymentMethods,
5
+ formatPaymentMethodsSummary,
6
+ } from "./index";
7
+
8
+ console.log("=== BIP-321 Parser Examples ===\n");
9
+
10
+ // Example 1: Simple mainnet address
11
+ console.log("1. Simple Mainnet Address");
12
+ console.log("URI: bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
13
+ const example1 = parseBIP321("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
14
+ console.log(`Valid: ${example1.valid}`);
15
+ console.log(`Network: ${example1.network}`);
16
+ console.log(`Address: ${example1.address}`);
17
+ console.log();
18
+
19
+ // Example 2: Payment with amount and label
20
+ console.log("2. Payment with Amount and Label");
21
+ const example2 = parseBIP321(
22
+ "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=0.5&label=Donation&message=Thank%20you%20for%20your%20support",
23
+ );
24
+ console.log(`Valid: ${example2.valid}`);
25
+ console.log(`Amount: ${example2.amount} BTC`);
26
+ console.log(`Label: ${example2.label}`);
27
+ console.log(`Message: ${example2.message}`);
28
+ console.log();
29
+
30
+ // Example 3: Lightning invoice with fallback
31
+ console.log("3. Lightning Invoice with On-Chain Fallback");
32
+ const example3 = parseBIP321(
33
+ "bitcoin:bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq?lightning=lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs",
34
+ );
35
+ console.log(`Valid: ${example3.valid}`);
36
+ console.log(`Payment methods: ${example3.paymentMethods.length}`);
37
+ example3.paymentMethods.forEach((method, i) => {
38
+ console.log(
39
+ ` ${i + 1}. ${method.type} (${method.network}) - Valid: ${method.valid}`,
40
+ );
41
+ });
42
+ console.log();
43
+
44
+ // Example 4: Lightning-only payment
45
+ console.log("4. Lightning-Only Payment");
46
+ const example4 = parseBIP321(
47
+ "bitcoin:?lightning=lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs",
48
+ );
49
+ console.log(`Valid: ${example4.valid}`);
50
+ console.log(`Address in path: ${example4.address || "none"}`);
51
+ console.log(`Payment type: ${example4.paymentMethods[0]?.type}`);
52
+ console.log(`Network: ${example4.paymentMethods[0]?.network}`);
53
+ console.log();
54
+
55
+ // Example 5: Multiple payment methods
56
+ console.log("5. Multiple Payment Methods");
57
+ const example5 = parseBIP321(
58
+ "bitcoin:?lightning=lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs&lno=lno1bogusoffer&sp=sp1qsilentpayment",
59
+ );
60
+ console.log(`Valid: ${example5.valid}`);
61
+ console.log(`Total payment methods: ${example5.paymentMethods.length}`);
62
+ example5.paymentMethods.forEach((method) => {
63
+ console.log(` - ${method.type}: ${method.valid ? "valid" : "invalid"}`);
64
+ });
65
+ console.log();
66
+
67
+ // Example 6: Network-specific parameters
68
+ console.log("6. Network-Specific Parameters");
69
+ const example6 = parseBIP321(
70
+ "bitcoin:?bc=bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq&tb=tb1qghfhmd4zh7ncpmxl3qzhmq566jk8ckq4gafnmg",
71
+ );
72
+ const byNetwork = getPaymentMethodsByNetwork(example6);
73
+ console.log(`Valid: ${example6.valid}`);
74
+ console.log(`Mainnet methods: ${byNetwork.mainnet?.length || 0}`);
75
+ console.log(`Testnet methods: ${byNetwork.testnet?.length || 0}`);
76
+ console.log();
77
+
78
+ // Example 7: Testnet lightning invoice
79
+ console.log("7. Testnet Lightning Invoice");
80
+ const example7 = parseBIP321(
81
+ "bitcoin:?lightning=lntb2500n1pwxlkl5pp5g8hz28tlf950ps942lu3dknfete8yax2ctywpwjs872x9kngvvuqdqage5hyum5yp6x2um5yp5kuan0d93k2cqzyskdc5s2ltgm9kklz42x3e4tggdd9lcep2s9t2yk54gnfxg48wxushayrt52zjmua43gdnxmuc5s0c8g29ja9vnxs6x3kxgsha07htcacpmdyl64",
82
+ );
83
+ console.log(`Valid: ${example7.valid}`);
84
+ console.log(`Network: ${example7.paymentMethods[0]?.network}`);
85
+ console.log();
86
+
87
+ // Example 8: Taproot address
88
+ console.log("8. Taproot Address (bc1p...)");
89
+ const example8 = parseBIP321(
90
+ "bitcoin:?bc=bc1pdyp8m5mhurxa9mf822jegnhu49g2zcchgcq8jzrjxg58u2lvudyqftt43a",
91
+ );
92
+ console.log(`Valid: ${example8.valid}`);
93
+ console.log(`Network: ${example8.paymentMethods[0]?.network}`);
94
+ console.log(
95
+ `Address: ${example8.paymentMethods[0]?.value.substring(0, 20)}...`,
96
+ );
97
+ console.log();
98
+
99
+ // Example 9: Error handling - invalid address
100
+ console.log("9. Error Handling - Invalid Address");
101
+ const example9 = parseBIP321("bitcoin:invalidaddress123");
102
+ console.log(`Valid: ${example9.valid}`);
103
+ console.log("Errors:");
104
+ example9.errors.forEach((error) => console.log(` - ${error}`));
105
+ console.log();
106
+
107
+ // Example 10: Error handling - network mismatch
108
+ console.log("10. Error Handling - Network Mismatch");
109
+ const example10 = parseBIP321(
110
+ "bitcoin:?bc=tb1qghfhmd4zh7ncpmxl3qzhmq566jk8ckq4gafnmg",
111
+ );
112
+ console.log(`Valid: ${example10.valid}`);
113
+ console.log("Errors:");
114
+ example10.errors.forEach((error) => console.log(` - ${error}`));
115
+ console.log();
116
+
117
+ // Example 11: Using helper functions
118
+ console.log("11. Helper Functions");
119
+ const example11 = parseBIP321(
120
+ "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=1.5&label=Test%20Payment&lightning=lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs",
121
+ );
122
+
123
+ console.log("Valid payment methods:");
124
+ const validMethods = getValidPaymentMethods(example11);
125
+ validMethods.forEach((method) => {
126
+ console.log(` - ${method.type} (${method.network})`);
127
+ });
128
+
129
+ console.log("\nPayment methods by network:");
130
+ const grouped = getPaymentMethodsByNetwork(example11);
131
+ Object.entries(grouped).forEach(([network, methods]) => {
132
+ if (methods.length > 0) {
133
+ console.log(` ${network}: ${methods.length} method(s)`);
134
+ }
135
+ });
136
+
137
+ console.log("\nFormatted summary:");
138
+ console.log(formatPaymentMethodsSummary(example11));
139
+ console.log();
140
+
141
+ // Example 12: Proof of payment
142
+ console.log("12. Proof of Payment Callback");
143
+ const example12 = parseBIP321(
144
+ "bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?pop=myapp%3acallback",
145
+ );
146
+ console.log(`Valid: ${example12.valid}`);
147
+ console.log(`Pop URI: ${example12.pop}`);
148
+ console.log(`Pop required: ${example12.popRequired}`);
149
+ console.log();
150
+
151
+ // Example 13: Case insensitivity
152
+ console.log("13. Case Insensitivity");
153
+ const example13 = parseBIP321(
154
+ "BITCOIN:BC1QAR0SRRR7XFKVY5L643LYDNW9RE59GTZZWF5MDQ?AMOUNT=1.0&LABEL=Test",
155
+ );
156
+ console.log(`Valid: ${example13.valid}`);
157
+ console.log(`Amount: ${example13.amount}`);
158
+ console.log(`Label: ${example13.label}`);
159
+ console.log();
160
+
161
+ console.log("=== All examples completed ===");