bip-321 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +139 -14
  2. package/index.ts +25 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -53,6 +53,49 @@ console.log(result.address); // "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
53
53
  console.log(result.paymentMethods); // Array of payment methods
54
54
  ```
55
55
 
56
+ ## Validation Functions
57
+
58
+ The library also exports standalone validation functions that can be used independently:
59
+
60
+ ```typescript
61
+ import {
62
+ validateBitcoinAddress,
63
+ validateLightningInvoice,
64
+ validateBolt12Offer,
65
+ validateSilentPaymentAddress,
66
+ validateArkAddress,
67
+ validatePopUri,
68
+ } from "bip-321";
69
+
70
+ // Validate a Bitcoin address
71
+ const btcResult = validateBitcoinAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
72
+ console.log(btcResult.valid); // true
73
+ console.log(btcResult.network); // "mainnet"
74
+
75
+ // Validate a Lightning invoice
76
+ const lnResult = validateLightningInvoice("lnbc15u1p3xnhl2pp5...");
77
+ console.log(lnResult.valid); // true
78
+ console.log(lnResult.network); // "mainnet"
79
+
80
+ // Validate a BOLT12 offer
81
+ const offerResult = validateBolt12Offer("lno1qqqq02k20d");
82
+ console.log(offerResult.valid); // true
83
+
84
+ // Validate a Silent Payment address
85
+ const spResult = validateSilentPaymentAddress("sp1qq...");
86
+ console.log(spResult.valid); // true
87
+ console.log(spResult.network); // "mainnet"
88
+
89
+ // Validate an Ark address
90
+ const arkResult = validateArkAddress("ark1p...");
91
+ console.log(arkResult.valid); // true
92
+ console.log(arkResult.network); // "mainnet"
93
+
94
+ // Validate a pop URI
95
+ const popResult = validatePopUri("myapp://callback");
96
+ console.log(popResult.valid); // true
97
+ ```
98
+
56
99
  ## Usage Examples
57
100
 
58
101
  ### Basic On-Chain Payment
@@ -192,23 +235,98 @@ Parses a BIP-321 URI and returns detailed information about the payment request.
192
235
  **Parameters:**
193
236
  - `uri` - The Bitcoin URI string to parse
194
237
  - `expectedNetwork` (optional) - Expected network for all payment methods. If specified, all payment methods must match this network or the URI will be marked invalid.
195
- </text>
196
238
 
197
- <old_text line=240>
198
- ## Validation Rules
239
+ **Returns:** `BIP321ParseResult` object
199
240
 
200
- The parser enforces BIP-321 validation rules:
241
+ ### Validation Functions
201
242
 
202
- 1. URI must start with `bitcoin:` (case-insensitive)
203
- 2. ✅ Address in URI path must be valid or empty
204
- 3. `amount` must be decimal BTC (no commas)
205
- 4. ✅ `label`, `message`, and `amount` cannot appear multiple times
206
- 5. `pop` and `req-pop` cannot both be present
207
- 6. ✅ Required parameters (`req-*`) must be understood or URI is invalid
208
- 7. ✅ Network-specific parameters (`bc`, `tb`, etc.) must match address network
209
- 8. ✅ `pop` URI scheme must not be forbidden (http, https, file, javascript, mailto)
243
+ The library exports individual validation functions for each payment method type:
244
+
245
+ #### `validateBitcoinAddress(address: string)`
246
+
247
+ Validates a Bitcoin address and returns network information.
248
+
249
+ **Returns:**
250
+ ```typescript
251
+ {
252
+ valid: boolean;
253
+ network?: "mainnet" | "testnet" | "regtest" | "signet";
254
+ error?: string;
255
+ }
256
+ ```
257
+
258
+ #### `validateLightningInvoice(invoice: string)`
259
+
260
+ Validates a BOLT11 Lightning invoice and detects the network.
261
+
262
+ **Returns:**
263
+ ```typescript
264
+ {
265
+ valid: boolean;
266
+ network?: "mainnet" | "testnet" | "regtest" | "signet";
267
+ error?: string;
268
+ }
269
+ ```
210
270
 
211
- **Returns:** `BIP321ParseResult` object containing:
271
+ #### `validateBolt12Offer(offer: string)`
272
+
273
+ Validates a BOLT12 offer. Note: BOLT12 offers are network-agnostic.
274
+
275
+ **Returns:**
276
+ ```typescript
277
+ {
278
+ valid: boolean;
279
+ error?: string;
280
+ }
281
+ ```
282
+
283
+ #### `validateSilentPaymentAddress(address: string)`
284
+
285
+ Validates a BIP-352 Silent Payment address.
286
+
287
+ **Returns:**
288
+ ```typescript
289
+ {
290
+ valid: boolean;
291
+ network?: "mainnet" | "testnet";
292
+ error?: string;
293
+ }
294
+ ```
295
+
296
+ **Note:** For Silent Payments, `testnet` covers testnet, signet, and regtest.
297
+
298
+ #### `validateArkAddress(address: string)`
299
+
300
+ Validates an Ark address (BOAT-0001).
301
+
302
+ **Returns:**
303
+ ```typescript
304
+ {
305
+ valid: boolean;
306
+ network?: "mainnet" | "testnet";
307
+ error?: string;
308
+ }
309
+ ```
310
+
311
+ **Note:** For Ark, `testnet` covers testnet, signet, and regtest.
312
+
313
+ #### `validatePopUri(uri: string)`
314
+
315
+ Validates a proof-of-payment URI and checks for forbidden schemes.
316
+
317
+ **Returns:**
318
+ ```typescript
319
+ {
320
+ valid: boolean;
321
+ error?: string;
322
+ }
323
+ ```
324
+ </text>
325
+
326
+ <old_text line=240>
327
+ ### BIP321ParseResult
328
+
329
+ The `parseBIP321` function returns a `BIP321ParseResult` object containing:
212
330
 
213
331
  ```typescript
214
332
  interface BIP321ParseResult {
@@ -309,9 +427,16 @@ The library automatically detects the network from:
309
427
  - **Regtest**: `lnbcrt...`
310
428
  - **Signet**: `lntbs...`
311
429
 
430
+ ### Silent Payment Addresses
431
+ - **Mainnet**: `sp1q...`
432
+ - **Testnet**: `tsp1q...` (covers testnet, signet, and regtest)
433
+
312
434
  ### Ark Addresses
313
435
  - **Mainnet**: `ark1...`
314
- - **Testnet**: `tark1...`
436
+ - **Testnet**: `tark1...` (covers testnet, signet, and regtest)
437
+
438
+ ### BOLT12 Offers
439
+ - **Network-agnostic**: `lno...` (no network-specific prefix)
315
440
 
316
441
  ## Validation Rules
317
442
 
package/index.ts CHANGED
@@ -7,6 +7,16 @@ import {
7
7
  validatePopUri,
8
8
  } from "./validators";
9
9
 
10
+ // Re-export validation functions for public API
11
+ export {
12
+ validateBitcoinAddress,
13
+ validateLightningInvoice,
14
+ validateBolt12Offer,
15
+ validateSilentPaymentAddress,
16
+ validateArkAddress,
17
+ validatePopUri,
18
+ };
19
+
10
20
  export interface PaymentMethod {
11
21
  type: "onchain" | "lightning" | "offer" | "silent-payment" | "ark";
12
22
  value: string;
@@ -222,7 +232,12 @@ export function parseBIP321(
222
232
  const decodedValue = decodeURIComponent(value);
223
233
  const validation = validateBitcoinAddress(decodedValue);
224
234
  const networkMatches =
225
- validation.valid && validation.network === expectedNetwork;
235
+ validation.valid &&
236
+ (validation.network === expectedNetwork ||
237
+ // Testnet and signet are interchangeable for onchain
238
+ (validation.network === "testnet" &&
239
+ expectedNetwork === "signet") ||
240
+ (validation.network === "signet" && expectedNetwork === "testnet"));
226
241
 
227
242
  result.paymentMethods.push({
228
243
  type: "onchain",
@@ -264,12 +279,16 @@ export function parseBIP321(
264
279
  for (const method of result.paymentMethods) {
265
280
  if (method.network && method.network !== expectedNetwork) {
266
281
  // For Ark and Silent Payments, testnet covers testnet/signet/regtest
282
+ // For onchain, testnet and signet are interchangeable
267
283
  const isTestnetCompatible =
268
- (method.type === "ark" || method.type === "silent-payment") &&
269
- method.network === "testnet" &&
270
- (expectedNetwork === "testnet" ||
271
- expectedNetwork === "signet" ||
272
- expectedNetwork === "regtest");
284
+ ((method.type === "ark" || method.type === "silent-payment") &&
285
+ method.network === "testnet" &&
286
+ (expectedNetwork === "testnet" ||
287
+ expectedNetwork === "signet" ||
288
+ expectedNetwork === "regtest")) ||
289
+ (method.type === "onchain" &&
290
+ ((method.network === "testnet" && expectedNetwork === "signet") ||
291
+ (method.network === "signet" && expectedNetwork === "testnet")));
273
292
 
274
293
  if (!isTestnetCompatible) {
275
294
  result.errors.push(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bip-321",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "A TypeScript/JavaScript library for parsing BIP-321 Bitcoin URI scheme with support for multiple payment methods",
5
5
  "type": "module",
6
6
  "main": "./index.ts",