bip-321 0.0.1 → 0.0.2

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.
@@ -0,0 +1,31 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: ["**"]
6
+ pull_request:
7
+ branches: ["**"]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Setup Bun
17
+ uses: oven-sh/setup-bun@v1
18
+ with:
19
+ bun-version: latest
20
+
21
+ - name: Install dependencies
22
+ run: bun install
23
+
24
+ - name: Run lint
25
+ run: bun run lint
26
+
27
+ - name: Run type check
28
+ run: bun run check
29
+
30
+ - name: Run tests
31
+ run: bun test
package/README.md CHANGED
@@ -13,11 +13,6 @@ A TypeScript/JavaScript library for parsing BIP-321 Bitcoin URI scheme. This lib
13
13
  - ✅ **TypeScript support** - Fully typed with TypeScript definitions
14
14
  - ✅ **Proof of payment** - Supports pop/req-pop parameters for payment callbacks
15
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
16
 
22
17
  ```typescript
23
18
  import { parseBIP321, type BIP321ParseResult, type PaymentMethod } from "bip-321";
@@ -40,8 +35,6 @@ result.paymentMethods.forEach((method: PaymentMethod) => {
40
35
  ```
41
36
 
42
37
  ## Installation
43
- </text>
44
-
45
38
 
46
39
  ```bash
47
40
  bun add bip-321
@@ -53,6 +46,16 @@ Or with npm:
53
46
  npm install bip-321
54
47
  ```
55
48
 
49
+ ### Note on Dependencies
50
+
51
+ This library uses modern, browser-native dependencies:
52
+ - **`@scure/base`** - Pure JavaScript base58, bech32, and bech32m encoding (no browserify needed)
53
+ - **`@noble/hashes`** - Pure JavaScript cryptographic hashing
54
+ - **`bitcoinjs-lib`** - Bitcoin address validation
55
+ - **`light-bolt11-decoder`** - Lightning invoice parsing
56
+
57
+ All dependencies work natively in Node.js, browsers, and React Native without any build tools or polyfills required.
58
+
56
59
  ## Quick Start
57
60
 
58
61
  ```typescript
@@ -333,4 +336,4 @@ BSD-2-Clause (same as BIP-321)
333
336
  ## Related
334
337
 
335
338
  - [BIP-321 Specification](https://bips.dev/321/)
336
- - [BIP-21 (Original)](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki)
339
+ - [BIP-21 (Original)](https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki)
package/bun.lock CHANGED
@@ -4,13 +4,14 @@
4
4
  "": {
5
5
  "name": "bip-321",
6
6
  "dependencies": {
7
+ "@noble/hashes": "^2.0.1",
7
8
  "@scure/base": "^2.0.0",
8
9
  "bitcoinjs-lib": "^7.0.0",
9
- "bs58check": "^4.0.0",
10
10
  "light-bolt11-decoder": "^3.2.0",
11
11
  },
12
12
  "devDependencies": {
13
13
  "@types/bun": "latest",
14
+ "oxlint": "^1.26.0",
14
15
  },
15
16
  "peerDependencies": {
16
17
  "typescript": "^5",
@@ -18,7 +19,23 @@
18
19
  },
19
20
  },
20
21
  "packages": {
21
- "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
22
+ "@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],
23
+
24
+ "@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.26.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-kTmm1opqyn7iZopWHO3Ml4D/44pA5eknZBepgxCnTaPrW8XgCEUI85Q5AvOOvoNve8NziTYb8ax+CyuGJIgn/Q=="],
25
+
26
+ "@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.26.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-/hMfZ9j7ZzVPRmMm02PHNc6MIMk0QYv5VowZJRIp40YLqLPvFfGNGZBj8e1fDVgZMFEGWDQK3yrt1uBKxXAK4Q=="],
27
+
28
+ "@oxlint/linux-arm64-gnu": ["@oxlint/linux-arm64-gnu@1.26.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-iv4wdrwdCa8bhJxOpKlvfxqTs0LgW5tKBUMvH9B13zREHm1xT9JRZ8cQbbKiyC6LNdggwu5S6TSvODgAu7/DlA=="],
29
+
30
+ "@oxlint/linux-arm64-musl": ["@oxlint/linux-arm64-musl@1.26.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-a3gTbnN1JzedxqYeGTkg38BAs/r3Krd2DPNs/MF7nnHthT3RzkPUk47isMePLuNc4e/Weljn7m2m/Onx22tiNg=="],
31
+
32
+ "@oxlint/linux-x64-gnu": ["@oxlint/linux-x64-gnu@1.26.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cCAyqyuKpFImjlgiBuuwSF+aDBW2h19/aCmHMTMSp6KXwhoQK7/Xx7/EhZKP5wiQJzVUYq5fXr0D8WmpLGsjRg=="],
33
+
34
+ "@oxlint/linux-x64-musl": ["@oxlint/linux-x64-musl@1.26.0", "", { "os": "linux", "cpu": "x64" }, "sha512-8VOJ4vQo0G1tNdaghxrWKjKZGg73tv+FoMDrtNYuUesqBHZN68FkYCsgPwEsacLhCmtoZrkF3ePDWDuWEpDyAg=="],
35
+
36
+ "@oxlint/win32-arm64": ["@oxlint/win32-arm64@1.26.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-N8KUtzP6gfEHKvaIBZCS9g8wRfqV5v55a/B8iJjIEhtMehcEM+UX+aYRsQ4dy5oBCrK3FEp4Yy/jHgb0moLm3Q=="],
37
+
38
+ "@oxlint/win32-x64": ["@oxlint/win32-x64@1.26.0", "", { "os": "win32", "cpu": "x64" }, "sha512-7tCyG0laduNQ45vzB9blVEGq/6DOvh7AFmiUAana8mTp0zIKQQmwJ21RqhazH0Rk7O6lL7JYzKcu+zaJHGpRLA=="],
22
39
 
23
40
  "@scure/base": ["@scure/base@2.0.0", "", {}, "sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w=="],
24
41
 
@@ -46,6 +63,8 @@
46
63
 
47
64
  "light-bolt11-decoder": ["light-bolt11-decoder@3.2.0", "", { "dependencies": { "@scure/base": "1.1.1" } }, "sha512-3QEofgiBOP4Ehs9BI+RkZdXZNtSys0nsJ6fyGeSiAGCBsMwHGUDS/JQlY/sTnWs91A2Nh0S9XXfA8Sy9g6QpuQ=="],
48
65
 
66
+ "oxlint": ["oxlint@1.26.0", "", { "optionalDependencies": { "@oxlint/darwin-arm64": "1.26.0", "@oxlint/darwin-x64": "1.26.0", "@oxlint/linux-arm64-gnu": "1.26.0", "@oxlint/linux-arm64-musl": "1.26.0", "@oxlint/linux-x64-gnu": "1.26.0", "@oxlint/linux-x64-musl": "1.26.0", "@oxlint/win32-arm64": "1.26.0", "@oxlint/win32-x64": "1.26.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.4.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint", "oxc_language_server": "bin/oxc_language_server" } }, "sha512-KRpL+SMi07JQyggv5ldIF+wt2pnrKm8NLW0B+8bK+0HZsLmH9/qGA+qMWie5Vf7lnlMBllJmsuzHaKFEGY3rIA=="],
67
+
49
68
  "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
50
69
 
51
70
  "uint8array-tools": ["uint8array-tools@0.0.9", "", {}, "sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A=="],
@@ -56,6 +75,10 @@
56
75
 
57
76
  "varuint-bitcoin": ["varuint-bitcoin@2.0.0", "", { "dependencies": { "uint8array-tools": "^0.0.8" } }, "sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog=="],
58
77
 
78
+ "bitcoinjs-lib/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
79
+
80
+ "bs58check/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
81
+
59
82
  "light-bolt11-decoder/@scure/base": ["@scure/base@1.1.1", "", {}, "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA=="],
60
83
 
61
84
  "varuint-bitcoin/uint8array-tools": ["uint8array-tools@0.0.8", "", {}, "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g=="],
package/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as bitcoin from "bitcoinjs-lib";
2
2
  import { decode as decodeLightning } from "light-bolt11-decoder";
3
- import bs58check from "bs58check";
4
- import { bech32, bech32m } from "@scure/base";
3
+ import { sha256 } from "@noble/hashes/sha2.js";
4
+ import { base58, bech32, bech32m } from "@scure/base";
5
5
 
6
6
  export interface PaymentMethod {
7
7
  type:
@@ -46,7 +46,7 @@ function detectAddressNetwork(
46
46
  // Try using bitcoinjs-lib first (works for non-taproot)
47
47
  bitcoin.address.toOutputScript(address, bitcoin.networks.bitcoin);
48
48
  return "mainnet";
49
- } catch (e) {
49
+ } catch {
50
50
  // Fallback to manual bech32/bech32m validation for taproot
51
51
  try {
52
52
  const decoded = lowerAddress.startsWith("bc1p")
@@ -63,7 +63,7 @@ function detectAddressNetwork(
63
63
  try {
64
64
  bitcoin.address.toOutputScript(address, bitcoin.networks.testnet);
65
65
  return "testnet";
66
- } catch (e) {
66
+ } catch {
67
67
  try {
68
68
  const decoded = lowerAddress.startsWith("tb1p")
69
69
  ? bech32m.decode(address as `${string}1${string}`, 90)
@@ -79,7 +79,7 @@ function detectAddressNetwork(
79
79
  try {
80
80
  bitcoin.address.toOutputScript(address, bitcoin.networks.regtest);
81
81
  return "regtest";
82
- } catch (e) {
82
+ } catch {
83
83
  try {
84
84
  const decoded = lowerAddress.startsWith("bcrt1p")
85
85
  ? bech32m.decode(address as `${string}1${string}`, 90)
@@ -93,19 +93,38 @@ function detectAddressNetwork(
93
93
  }
94
94
  }
95
95
 
96
- // Base58 addresses (P2PKH, P2SH)
97
- const decoded = bs58check.decode(address);
98
- const version = decoded[0];
96
+ // Base58 addresses (P2PKH, P2SH) - manual validation with checksum
97
+ try {
98
+ const decoded = base58.decode(address);
99
+ if (decoded.length < 25) {
100
+ return undefined;
101
+ }
99
102
 
100
- // Mainnet: P2PKH (0x00), P2SH (0x05)
101
- if (version === 0x00 || version === 0x05) {
102
- return "mainnet";
103
- }
104
- // Testnet: P2PKH (0x6f), P2SH (0xc4)
105
- else if (version === 0x6f || version === 0xc4) {
106
- return "testnet";
103
+ // Verify checksum
104
+ const payload = decoded.slice(0, -4);
105
+ const checksum = decoded.slice(-4);
106
+ const hash = sha256(sha256(payload));
107
+
108
+ for (let i = 0; i < 4; i++) {
109
+ if (checksum[i] !== hash[i]) {
110
+ return undefined;
111
+ }
112
+ }
113
+
114
+ const version = payload[0];
115
+
116
+ // Mainnet: P2PKH (0x00), P2SH (0x05)
117
+ if (version === 0x00 || version === 0x05) {
118
+ return "mainnet";
119
+ }
120
+ // Testnet: P2PKH (0x6f), P2SH (0xc4)
121
+ else if (version === 0x6f || version === 0xc4) {
122
+ return "testnet";
123
+ }
124
+ } catch (e) {
125
+ return undefined;
107
126
  }
108
- } catch (e) {
127
+ } catch {
109
128
  return undefined;
110
129
  }
111
130
  return undefined;
@@ -134,7 +153,7 @@ function validateLightningInvoice(invoice: string): {
134
153
  error?: string;
135
154
  } {
136
155
  try {
137
- const decoded = decodeLightning(invoice);
156
+ const _decoded = decodeLightning(invoice);
138
157
  let network: "mainnet" | "testnet" | "regtest" | "signet" | undefined;
139
158
 
140
159
  const lowerInvoice = invoice.toLowerCase();
@@ -174,7 +193,7 @@ function validatePopUri(popUri: string): { valid: boolean; error?: string } {
174
193
  }
175
194
 
176
195
  return { valid: true };
177
- } catch (e) {
196
+ } catch {
178
197
  return { valid: false, error: "Invalid pop URI encoding" };
179
198
  }
180
199
  }
@@ -284,7 +303,7 @@ export function parseBIP321(uri: string): BIP321ParseResult {
284
303
  }
285
304
  }
286
305
  } else if (lowerKey === "pop" || lowerKey === "req-pop") {
287
- const popKey = lowerKey === "req-pop" ? "req-pop" : "pop";
306
+ const _popKey = lowerKey === "req-pop" ? "req-pop" : "pop";
288
307
  if (result.pop !== undefined || result.popRequired !== undefined) {
289
308
  result.errors.push("Multiple pop/req-pop parameters not allowed");
290
309
  result.valid = false;
package/oxlintrc.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "categories": {
3
+ "correctness": "warn",
4
+ "suspicious": "warn",
5
+ "pedantic": "warn",
6
+ "perf": "warn",
7
+ "style": "warn",
8
+ "restriction": "warn"
9
+ },
10
+ "rules": {
11
+ "typescript/no-explicit-any": "error",
12
+ "typescript/no-non-null-assertion": "error",
13
+ "no-console": "warn",
14
+ "no-debugger": "error",
15
+ "eqeqeq": "error"
16
+ },
17
+ "ignorePatterns": [
18
+ "**/node_modules/**",
19
+ "**/dist/**",
20
+ "**/build/**",
21
+ "**/*.min.js"
22
+ ]
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bip-321",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
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",
@@ -14,7 +14,9 @@
14
14
  },
15
15
  "scripts": {
16
16
  "test": "bun test",
17
- "example": "bun example.ts"
17
+ "example": "bun example.ts",
18
+ "check": "tsc --noEmit",
19
+ "lint": "oxlint"
18
20
  },
19
21
  "keywords": [
20
22
  "bitcoin",
@@ -40,25 +42,26 @@
40
42
  "author": "",
41
43
  "license": "BSD-2-Clause",
42
44
  "dependencies": {
45
+ "@noble/hashes": "^2.0.1",
43
46
  "@scure/base": "^2.0.0",
44
47
  "bitcoinjs-lib": "^7.0.0",
45
- "bs58check": "^4.0.0",
46
48
  "light-bolt11-decoder": "^3.2.0"
47
49
  },
48
50
  "devDependencies": {
49
- "@types/bun": "latest"
51
+ "@types/bun": "latest",
52
+ "oxlint": "^1.26.0"
50
53
  },
51
54
  "peerDependencies": {
52
55
  "typescript": "^5"
53
56
  },
54
57
  "repository": {
55
58
  "type": "git",
56
- "url": "https://github.com/yourusername/bip-321.git"
59
+ "url": "https://github.com/niteshbalusu11/bip-321.git"
57
60
  },
58
61
  "bugs": {
59
- "url": "https://github.com/yourusername/bip-321/issues"
62
+ "url": "https://github.com/niteshbalusu11/bip-321/issues"
60
63
  },
61
- "homepage": "https://github.com/yourusername/bip-321#readme",
64
+ "homepage": "https://github.com/niteshbalusu11/bip-321#readme",
62
65
  "engines": {
63
66
  "node": ">=16.0.0"
64
67
  }