satoshi-proof-sdk 1.0.0

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,363 @@
1
+ # @satoshi-proof/sdk
2
+
3
+ **Bitcoin signature verification and proof generation SDK for Starknet**
4
+
5
+ This SDK implements BIP-137 Bitcoin signed message verification with Poseidon hashing, enabling trustless Bitcoin balance proofs on Starknet.
6
+
7
+ ---
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @satoshi-proof/sdk
13
+ ```
14
+
15
+ ```bash
16
+ yarn add @satoshi-proof/sdk
17
+ ```
18
+
19
+ ```bash
20
+ pnpm add @satoshi-proof/sdk
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Quick Start
26
+
27
+ ```typescript
28
+ import { generateProof } from '@satoshi-proof/sdk';
29
+
30
+ // User signs a message with their Bitcoin wallet
31
+ const message = "I own this Bitcoin address";
32
+ const signature = "H8k3..."; // Base64 signature from wallet
33
+ const btcBalance = 25.5; // BTC
34
+
35
+ // Generate cryptographic proof
36
+ const proof = generateProof(message, signature, btcBalance);
37
+
38
+ console.log(proof.btcAddress); // "1A1zP1..."
39
+ console.log(proof.bracketName); // "fish" (10-50 BTC)
40
+ console.log(proof.pubkeyHash); // Poseidon hash for on-chain verification
41
+ ```
42
+
43
+ ---
44
+
45
+ ## API Reference
46
+
47
+ ### `generateProof(message, signature, btcBalance)`
48
+
49
+ Generate a complete cryptographic proof from a Bitcoin signed message.
50
+
51
+ **Parameters:**
52
+ - `message` (string): The message that was signed
53
+ - `signature` (string): Base64-encoded Bitcoin signature (BIP-137 format)
54
+ - `btcBalance` (number): Bitcoin balance in BTC
55
+
56
+ **Returns:** `ProofData`
57
+
58
+ ```typescript
59
+ interface ProofData {
60
+ message: string; // Original message
61
+ msgHash: string; // SHA256(SHA256(Bitcoin message format))
62
+ sigR: string; // ECDSA signature r component (hex)
63
+ sigS: string; // ECDSA signature s component (hex)
64
+ yParity: boolean; // Public key y-coordinate parity
65
+ pubkeyX: string; // Recovered public key x-coordinate (hex)
66
+ pubkeyY: string; // Recovered public key y-coordinate (hex)
67
+ pubkeyHash: string; // Poseidon hash of pubkey (for Starknet)
68
+ btcAddress: string; // Derived P2PKH Bitcoin address
69
+ bracket: number; // Bracket ID (0-4)
70
+ bracketName: string; // 'shrimp' | 'crab' | 'fish' | 'shark' | 'whale'
71
+ bracketEmoji: string; // 🦐 | 🦀 | 🐟 | 🦈 | 🐋
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ### `getBracket(btcBalance)`
78
+
79
+ Determine the balance bracket based on BTC amount.
80
+
81
+ **Parameters:**
82
+ - `btcBalance` (number): Bitcoin balance in BTC
83
+
84
+ **Returns:** Bracket object
85
+
86
+ ```typescript
87
+ type Bracket = {
88
+ name: 'shrimp' | 'crab' | 'fish' | 'shark' | 'whale';
89
+ min: number;
90
+ max: number;
91
+ id: number;
92
+ emoji: string;
93
+ };
94
+
95
+ // Bracket ranges:
96
+ // 🦐 shrimp: 0-1 BTC
97
+ // 🦀 crab: 1-10 BTC
98
+ // 🐟 fish: 10-50 BTC
99
+ // 🦈 shark: 50-100 BTC
100
+ // 🐋 whale: 100+ BTC
101
+ ```
102
+
103
+ ---
104
+
105
+ ### `parseSignature(base64Sig)`
106
+
107
+ Parse a base64 Bitcoin signature into its cryptographic components.
108
+
109
+ **Parameters:**
110
+ - `base64Sig` (string): Base64-encoded signature
111
+
112
+ **Returns:** `ParsedSignature`
113
+
114
+ ```typescript
115
+ interface ParsedSignature {
116
+ r: bigint; // ECDSA r component
117
+ s: bigint; // ECDSA s component
118
+ recoveryFlag: number; // 0 or 1 (for pubkey recovery)
119
+ yParity: boolean; // true if y-coordinate is odd
120
+ }
121
+ ```
122
+
123
+ ---
124
+
125
+ ### `recoverPublicKey(msgHash, sig)`
126
+
127
+ Recover the secp256k1 public key from a message hash and signature.
128
+
129
+ **Parameters:**
130
+ - `msgHash` (Uint8Array): Bitcoin message hash (from `bitcoinMessageHash()`)
131
+ - `sig` (ParsedSignature): Parsed signature
132
+
133
+ **Returns:**
134
+
135
+ ```typescript
136
+ {
137
+ x: bigint; // Public key x-coordinate
138
+ y: bigint; // Public key y-coordinate
139
+ compressed: Uint8Array; // Compressed pubkey (33 bytes)
140
+ uncompressed: Uint8Array; // Uncompressed pubkey (65 bytes)
141
+ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ### `pubkeyToPoseidonHash(x, y)`
147
+
148
+ Compute the Poseidon hash of a public key for Starknet on-chain verification.
149
+
150
+ **Parameters:**
151
+ - `x` (bigint): Public key x-coordinate
152
+ - `y` (bigint): Public key y-coordinate
153
+
154
+ **Returns:** Poseidon hash (hex string)
155
+
156
+ This matches the Cairo contract implementation:
157
+ ```cairo
158
+ PoseidonTrait::new()
159
+ .update(x.low).update(x.high)
160
+ .update(y.low).update(y.high)
161
+ .finalize()
162
+ ```
163
+
164
+ ---
165
+
166
+ ### `bitcoinMessageHash(message)`
167
+
168
+ Compute the Bitcoin message hash following BIP-137 format.
169
+
170
+ **Parameters:**
171
+ - `message` (string): The message to hash
172
+
173
+ **Returns:** `Uint8Array` (32 bytes)
174
+
175
+ **Format:**
176
+ ```
177
+ SHA256(SHA256("\x18Bitcoin Signed Message:\n" + varint(len) + message))
178
+ ```
179
+
180
+ ---
181
+
182
+ ### `pubkeyToP2PKH(compressedPubkey, testnet?)`
183
+
184
+ Derive a P2PKH Bitcoin address from a compressed public key.
185
+
186
+ **Parameters:**
187
+ - `compressedPubkey` (Uint8Array): 33-byte compressed public key
188
+ - `testnet` (boolean, optional): Use testnet version byte (default: false)
189
+
190
+ **Returns:** Bitcoin address (string)
191
+
192
+ ---
193
+
194
+ ## Code Examples
195
+
196
+ ### Example 1: Verify a Bitcoin signature
197
+
198
+ ```typescript
199
+ import {
200
+ bitcoinMessageHash,
201
+ parseSignature,
202
+ recoverPublicKey,
203
+ pubkeyToP2PKH
204
+ } from '@satoshi-proof/sdk';
205
+
206
+ const message = "Prove I own this address";
207
+ const signature = "H8k3Qn..."; // From Bitcoin wallet
208
+
209
+ // Step 1: Hash the message
210
+ const msgHash = bitcoinMessageHash(message);
211
+
212
+ // Step 2: Parse the signature
213
+ const sig = parseSignature(signature);
214
+
215
+ // Step 3: Recover the public key
216
+ const pubkey = recoverPublicKey(msgHash, sig);
217
+
218
+ // Step 4: Derive the Bitcoin address
219
+ const address = pubkeyToP2PKH(pubkey.compressed);
220
+
221
+ console.log(`Signer address: ${address}`);
222
+ ```
223
+
224
+ ---
225
+
226
+ ### Example 2: Generate proof for Starknet contract
227
+
228
+ ```typescript
229
+ import { generateProof } from '@satoshi-proof/sdk';
230
+
231
+ async function submitProof(message: string, signature: string, btcBalance: number) {
232
+ // Generate proof
233
+ const proof = generateProof(message, signature, btcBalance);
234
+
235
+ // Call Starknet contract
236
+ const tx = await contract.verify_signature({
237
+ msg_hash: proof.msgHash,
238
+ r: proof.sigR,
239
+ s: proof.sigS,
240
+ y_parity: proof.yParity,
241
+ expected_pubkey_hash: proof.pubkeyHash,
242
+ bracket: proof.bracket
243
+ });
244
+
245
+ console.log(`Proof submitted for ${proof.btcAddress}`);
246
+ console.log(`Bracket: ${proof.bracketEmoji} ${proof.bracketName}`);
247
+
248
+ return tx;
249
+ }
250
+ ```
251
+
252
+ ---
253
+
254
+ ### Example 3: Batch verify multiple signatures
255
+
256
+ ```typescript
257
+ import { generateProof, getBracket, BRACKETS } from '@satoshi-proof/sdk';
258
+
259
+ interface User {
260
+ message: string;
261
+ signature: string;
262
+ balance: number;
263
+ }
264
+
265
+ function processBatch(users: User[]) {
266
+ const results = users.map(user => {
267
+ try {
268
+ const proof = generateProof(user.message, user.signature, user.balance);
269
+
270
+ return {
271
+ address: proof.btcAddress,
272
+ bracket: proof.bracketName,
273
+ pubkeyHash: proof.pubkeyHash,
274
+ valid: true
275
+ };
276
+ } catch (error) {
277
+ return {
278
+ address: null,
279
+ bracket: null,
280
+ pubkeyHash: null,
281
+ valid: false,
282
+ error: error.message
283
+ };
284
+ }
285
+ });
286
+
287
+ // Group by bracket
288
+ const byBracket = BRACKETS.map(bracket => ({
289
+ ...bracket,
290
+ count: results.filter(r => r.bracket === bracket.name).length
291
+ }));
292
+
293
+ console.log('Distribution:', byBracket);
294
+
295
+ return results;
296
+ }
297
+ ```
298
+
299
+ ---
300
+
301
+ ## Technical Details
302
+
303
+ ### BIP-137 Bitcoin Signed Message Format
304
+
305
+ The SDK implements the standard Bitcoin message signing format:
306
+
307
+ 1. **Message prefix**: `\x18Bitcoin Signed Message:\n`
308
+ 2. **Length encoding**: Compact size varint
309
+ 3. **Double SHA-256**: Hash the concatenated data twice
310
+ 4. **Signature format**: 65 bytes (1 header byte + 32 bytes r + 32 bytes s)
311
+
312
+ ### Signature Header Bytes
313
+
314
+ - **27-30**: Uncompressed public key
315
+ - **31-34**: Compressed public key
316
+ - **35-38**: Segwit P2SH-P2WPKH
317
+ - **39-42**: Segwit Bech32
318
+
319
+ Recovery flag = `(header - base) % 4`, where `base` is 27, 31, 35, or 39.
320
+
321
+ ### Poseidon Hashing for Starknet
322
+
323
+ Public keys are hashed using Poseidon (Starknet's native hash function) by splitting each coordinate into 128-bit low/high components:
324
+
325
+ ```
326
+ hash = Poseidon(x_low, x_high, y_low, y_high)
327
+ ```
328
+
329
+ This allows efficient on-chain verification without storing full public keys.
330
+
331
+ ---
332
+
333
+ ## Dependencies
334
+
335
+ - `@noble/curves` - secp256k1 cryptography
336
+ - `@noble/hashes` - SHA-256, RIPEMD-160
337
+ - `starknet` - Poseidon hashing
338
+
339
+ All dependencies are audited and widely used in production crypto applications.
340
+
341
+ ---
342
+
343
+ ## License
344
+
345
+ MIT
346
+
347
+ ---
348
+
349
+ ## Contributing
350
+
351
+ Issues and PRs welcome at [github.com/yourusername/satoshi-proof](https://github.com/yourusername/satoshi-proof)
352
+
353
+ ---
354
+
355
+ ## Security
356
+
357
+ This SDK handles cryptographic operations. Always:
358
+ - ✅ Verify signatures client-side before submitting to chain
359
+ - ✅ Use official Bitcoin wallets for signing
360
+ - ✅ Never share private keys
361
+ - ✅ Audit contract code before mainnet deployment
362
+
363
+ For security issues, please email: security@yourproject.com
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Bitcoin Message Signing utilities
3
+ *
4
+ * Handles BIP-137 Bitcoin signed message format:
5
+ * 1. Message hash: SHA256(SHA256("\x18Bitcoin Signed Message:\n" + varint(len) + message))
6
+ * 2. Signature parsing: base64 → (r, s, recovery_flag)
7
+ * 3. Public key recovery from signature
8
+ * 4. Public key → Bitcoin address derivation
9
+ */
10
+ /**
11
+ * Compute Bitcoin message hash (double SHA-256)
12
+ * Format: SHA256(SHA256("\x18Bitcoin Signed Message:\n" + varint(len) + message))
13
+ */
14
+ export declare function bitcoinMessageHash(message: string): Uint8Array;
15
+ /**
16
+ * Convert message hash bytes to u256 hex string (for Starknet contract)
17
+ */
18
+ export declare function hashToU256Hex(hash: Uint8Array): string;
19
+ export interface ParsedSignature {
20
+ r: bigint;
21
+ s: bigint;
22
+ recoveryFlag: number;
23
+ yParity: boolean;
24
+ }
25
+ /**
26
+ * Parse a base64 Bitcoin signature (BIP-137 format)
27
+ * First byte is the header: 27-30 (uncompressed), 31-34 (compressed)
28
+ * recovery_flag = (header - 27) % 4 for uncompressed
29
+ * recovery_flag = (header - 31) % 4 for compressed
30
+ */
31
+ export declare function parseSignature(base64Sig: string): ParsedSignature;
32
+ /**
33
+ * Recover the public key from a Bitcoin signed message
34
+ * Uses @noble/curves/secp256k1 Signature class with proper recovery
35
+ */
36
+ export declare function recoverPublicKey(msgHash: Uint8Array, sig: ParsedSignature): {
37
+ x: bigint;
38
+ y: bigint;
39
+ compressed: Uint8Array;
40
+ uncompressed: Uint8Array;
41
+ };
42
+ /**
43
+ * Derive P2PKH Bitcoin address from compressed public key
44
+ */
45
+ export declare function pubkeyToP2PKH(compressedPubkey: Uint8Array, testnet?: boolean): string;
46
+ export declare function pubkeyToHash160(compressedPubkey: Uint8Array): Uint8Array;
47
+ /**
48
+ * Derive P2WPKH (SegWit) address from compressed public key (bc1q...)
49
+ */
50
+ export declare function pubkeyToP2WPKH(compressedPubkey: Uint8Array, testnet?: boolean): string;
51
+ /**
52
+ * Derive all address formats from a compressed public key
53
+ */
54
+ export declare function pubkeyToAllAddresses(compressedPubkey: Uint8Array): {
55
+ p2pkh: string;
56
+ p2wpkh: string;
57
+ p2shP2wpkh: string;
58
+ };
59
+ /**
60
+ * Compute Poseidon hash of public key coordinates (for on-chain comparison)
61
+ * Matches the Cairo contract: PoseidonTrait::new().update(x.low).update(x.high).update(y.low).update(y.high).finalize()
62
+ */
63
+ export declare function pubkeyToPoseidonHash(x: bigint, y: bigint): string;
64
+ export type Bracket = 'shrimp' | 'crab' | 'fish' | 'shark' | 'whale';
65
+ export declare const BRACKETS: {
66
+ name: Bracket;
67
+ min: number;
68
+ max: number;
69
+ id: number;
70
+ emoji: string;
71
+ }[];
72
+ export declare function getBracket(btcBalance: number): typeof BRACKETS[0];
73
+ /**
74
+ * Generate proof message with nonce for replay protection
75
+ */
76
+ export declare function createProofMessage(contractAddress: string, nonce: number, chain?: string): string;
77
+ export interface ProofData {
78
+ message: string;
79
+ msgHash: string;
80
+ sigR: string;
81
+ sigS: string;
82
+ yParity: boolean;
83
+ pubkeyX: string;
84
+ pubkeyY: string;
85
+ pubkeyHash: string;
86
+ btcAddress: string;
87
+ bracket: number;
88
+ bracketName: string;
89
+ bracketEmoji: string;
90
+ }
91
+ /**
92
+ * Generate a complete proof from a Bitcoin signed message
93
+ */
94
+ export declare function generateProof(message: string, base64Signature: string, btcBalance: number): ProofData;
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Bitcoin Message Signing utilities
3
+ *
4
+ * Handles BIP-137 Bitcoin signed message format:
5
+ * 1. Message hash: SHA256(SHA256("\x18Bitcoin Signed Message:\n" + varint(len) + message))
6
+ * 2. Signature parsing: base64 → (r, s, recovery_flag)
7
+ * 3. Public key recovery from signature
8
+ * 4. Public key → Bitcoin address derivation
9
+ */
10
+ import { secp256k1 } from '@noble/curves/secp256k1';
11
+ import { sha256 } from '@noble/hashes/sha2.js';
12
+ import { ripemd160 } from '@noble/hashes/legacy.js';
13
+ import { hash as starkHash } from 'starknet';
14
+ // ─── Bitcoin Message Hash ───
15
+ function varintBuf(n) {
16
+ if (n < 0xfd)
17
+ return new Uint8Array([n]);
18
+ if (n <= 0xffff) {
19
+ const buf = new Uint8Array(3);
20
+ buf[0] = 0xfd;
21
+ buf[1] = n & 0xff;
22
+ buf[2] = (n >> 8) & 0xff;
23
+ return buf;
24
+ }
25
+ throw new Error('Message too long');
26
+ }
27
+ /**
28
+ * Compute Bitcoin message hash (double SHA-256)
29
+ * Format: SHA256(SHA256("\x18Bitcoin Signed Message:\n" + varint(len) + message))
30
+ */
31
+ export function bitcoinMessageHash(message) {
32
+ const prefix = '\x18Bitcoin Signed Message:\n';
33
+ const prefixBuf = new TextEncoder().encode(prefix);
34
+ const msgBuf = new TextEncoder().encode(message);
35
+ const lenBuf = varintBuf(msgBuf.length);
36
+ const combined = new Uint8Array(prefixBuf.length + lenBuf.length + msgBuf.length);
37
+ combined.set(prefixBuf, 0);
38
+ combined.set(lenBuf, prefixBuf.length);
39
+ combined.set(msgBuf, prefixBuf.length + lenBuf.length);
40
+ return sha256(sha256(combined));
41
+ }
42
+ /**
43
+ * Convert message hash bytes to u256 hex string (for Starknet contract)
44
+ */
45
+ export function hashToU256Hex(hash) {
46
+ return '0x' + Array.from(hash).map(b => b.toString(16).padStart(2, '0')).join('');
47
+ }
48
+ /**
49
+ * Parse a base64 Bitcoin signature (BIP-137 format)
50
+ * First byte is the header: 27-30 (uncompressed), 31-34 (compressed)
51
+ * recovery_flag = (header - 27) % 4 for uncompressed
52
+ * recovery_flag = (header - 31) % 4 for compressed
53
+ */
54
+ export function parseSignature(base64Sig) {
55
+ const raw = Uint8Array.from(atob(base64Sig), c => c.charCodeAt(0));
56
+ if (raw.length !== 65)
57
+ throw new Error(`Invalid signature length: ${raw.length}`);
58
+ const header = raw[0];
59
+ let recoveryFlag;
60
+ if (header >= 27 && header <= 30) {
61
+ recoveryFlag = header - 27;
62
+ }
63
+ else if (header >= 31 && header <= 34) {
64
+ recoveryFlag = header - 31;
65
+ }
66
+ else if (header >= 35 && header <= 38) {
67
+ recoveryFlag = header - 35;
68
+ }
69
+ else if (header >= 39 && header <= 42) {
70
+ recoveryFlag = header - 39;
71
+ }
72
+ else {
73
+ throw new Error(`Unknown signature header: ${header}`);
74
+ }
75
+ const r = BigInt('0x' + toHex(raw.slice(1, 33)));
76
+ const s = BigInt('0x' + toHex(raw.slice(33, 65)));
77
+ return {
78
+ r,
79
+ s,
80
+ recoveryFlag: recoveryFlag % 2,
81
+ yParity: (recoveryFlag % 2) === 1,
82
+ };
83
+ }
84
+ // ─── Public Key Recovery ───
85
+ /**
86
+ * Recover the public key from a Bitcoin signed message
87
+ * Uses @noble/curves/secp256k1 Signature class with proper recovery
88
+ */
89
+ export function recoverPublicKey(msgHash, sig) {
90
+ // Create Signature object with recovery bit
91
+ const signature = new secp256k1.Signature(sig.r, sig.s).addRecoveryBit(sig.recoveryFlag);
92
+ // Recover public key point
93
+ const point = signature.recoverPublicKey(msgHash);
94
+ const compressed = point.toRawBytes(true); // 33 bytes
95
+ const uncompressed = point.toRawBytes(false); // 65 bytes
96
+ return { x: point.x, y: point.y, compressed, uncompressed };
97
+ }
98
+ // ─── Helpers ───
99
+ function toHex(arr) {
100
+ return Array.from(arr).map(b => b.toString(16).padStart(2, '0')).join('');
101
+ }
102
+ // ─── Bitcoin Address Derivation ───
103
+ /**
104
+ * Derive P2PKH Bitcoin address from compressed public key
105
+ */
106
+ export function pubkeyToP2PKH(compressedPubkey, testnet = false) {
107
+ const hash1 = sha256(compressedPubkey);
108
+ const hash160 = ripemd160(hash1);
109
+ const version = testnet ? 0x6f : 0x00;
110
+ const payload = new Uint8Array(21);
111
+ payload[0] = version;
112
+ payload.set(hash160, 1);
113
+ return base58Check(payload);
114
+ }
115
+ export function pubkeyToHash160(compressedPubkey) {
116
+ return ripemd160(sha256(compressedPubkey));
117
+ }
118
+ /**
119
+ * Derive P2WPKH (SegWit) address from compressed public key (bc1q...)
120
+ */
121
+ export function pubkeyToP2WPKH(compressedPubkey, testnet = false) {
122
+ const hash160 = ripemd160(sha256(compressedPubkey));
123
+ const hrp = testnet ? 'tb' : 'bc';
124
+ return bech32Encode(hrp, 0, hash160);
125
+ }
126
+ /**
127
+ * Derive all address formats from a compressed public key
128
+ */
129
+ export function pubkeyToAllAddresses(compressedPubkey) {
130
+ const hash160Val = ripemd160(sha256(compressedPubkey));
131
+ const p2pkhPayload = new Uint8Array(21);
132
+ p2pkhPayload[0] = 0x00;
133
+ p2pkhPayload.set(hash160Val, 1);
134
+ const p2pkh = base58Check(p2pkhPayload);
135
+ const p2wpkh = bech32Encode('bc', 0, hash160Val);
136
+ const redeemScript = new Uint8Array(22);
137
+ redeemScript[0] = 0x00;
138
+ redeemScript[1] = 0x14;
139
+ redeemScript.set(hash160Val, 2);
140
+ const scriptHash = ripemd160(sha256(redeemScript));
141
+ const p2shPayload = new Uint8Array(21);
142
+ p2shPayload[0] = 0x05;
143
+ p2shPayload.set(scriptHash, 1);
144
+ const p2shP2wpkh = base58Check(p2shPayload);
145
+ return { p2pkh, p2wpkh, p2shP2wpkh };
146
+ }
147
+ function bech32Encode(hrp, witnessVersion, data) {
148
+ const CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
149
+ const converted = convertBits(data, 8, 5, true);
150
+ const values = [witnessVersion, ...converted];
151
+ const polymod = bech32Polymod(hrpExpand(hrp).concat(values).concat([0, 0, 0, 0, 0, 0])) ^ 1;
152
+ const checksum = [];
153
+ for (let i = 0; i < 6; i++)
154
+ checksum.push((polymod >> (5 * (5 - i))) & 31);
155
+ return hrp + '1' + values.concat(checksum).map(v => CHARSET[v]).join('');
156
+ }
157
+ function convertBits(data, fromBits, toBits, pad) {
158
+ let acc = 0, bits = 0;
159
+ const ret = [];
160
+ const maxv = (1 << toBits) - 1;
161
+ for (const value of data) {
162
+ acc = (acc << fromBits) | value;
163
+ bits += fromBits;
164
+ while (bits >= toBits) {
165
+ bits -= toBits;
166
+ ret.push((acc >> bits) & maxv);
167
+ }
168
+ }
169
+ if (pad && bits > 0)
170
+ ret.push((acc << (toBits - bits)) & maxv);
171
+ return ret;
172
+ }
173
+ function hrpExpand(hrp) {
174
+ const ret = [];
175
+ for (let i = 0; i < hrp.length; i++)
176
+ ret.push(hrp.charCodeAt(i) >> 5);
177
+ ret.push(0);
178
+ for (let i = 0; i < hrp.length; i++)
179
+ ret.push(hrp.charCodeAt(i) & 31);
180
+ return ret;
181
+ }
182
+ function bech32Polymod(values) {
183
+ const GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];
184
+ let chk = 1;
185
+ for (const v of values) {
186
+ const b = chk >> 25;
187
+ chk = ((chk & 0x1ffffff) << 5) ^ v;
188
+ for (let i = 0; i < 5; i++)
189
+ if ((b >> i) & 1)
190
+ chk ^= GEN[i];
191
+ }
192
+ return chk;
193
+ }
194
+ // Base58Check encoding
195
+ const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
196
+ function base58Check(payload) {
197
+ const checksum = sha256(sha256(payload)).slice(0, 4);
198
+ const data = new Uint8Array(payload.length + 4);
199
+ data.set(payload, 0);
200
+ data.set(checksum, payload.length);
201
+ let num = 0n;
202
+ for (const byte of data)
203
+ num = num * 256n + BigInt(byte);
204
+ let result = '';
205
+ while (num > 0n) {
206
+ const rem = Number(num % 58n);
207
+ result = BASE58_ALPHABET[rem] + result;
208
+ num = num / 58n;
209
+ }
210
+ for (const byte of data) {
211
+ if (byte !== 0)
212
+ break;
213
+ result = '1' + result;
214
+ }
215
+ return result;
216
+ }
217
+ // ─── Starknet Integration ───
218
+ /**
219
+ * Compute Poseidon hash of public key coordinates (for on-chain comparison)
220
+ * Matches the Cairo contract: PoseidonTrait::new().update(x.low).update(x.high).update(y.low).update(y.high).finalize()
221
+ */
222
+ export function pubkeyToPoseidonHash(x, y) {
223
+ const xLow = x & ((1n << 128n) - 1n);
224
+ const xHigh = x >> 128n;
225
+ const yLow = y & ((1n << 128n) - 1n);
226
+ const yHigh = y >> 128n;
227
+ return starkHash.computePoseidonHashOnElements([
228
+ '0x' + xLow.toString(16),
229
+ '0x' + xHigh.toString(16),
230
+ '0x' + yLow.toString(16),
231
+ '0x' + yHigh.toString(16),
232
+ ]);
233
+ }
234
+ export const BRACKETS = [
235
+ { name: 'shrimp', min: 0, max: 1, id: 0, emoji: '🦐' },
236
+ { name: 'crab', min: 1, max: 10, id: 1, emoji: '🦀' },
237
+ { name: 'fish', min: 10, max: 50, id: 2, emoji: '🐟' },
238
+ { name: 'shark', min: 50, max: 100, id: 3, emoji: '🦈' },
239
+ { name: 'whale', min: 100, max: Infinity, id: 4, emoji: '🐋' },
240
+ ];
241
+ export function getBracket(btcBalance) {
242
+ for (let i = BRACKETS.length - 1; i >= 0; i--) {
243
+ if (btcBalance >= BRACKETS[i].min)
244
+ return BRACKETS[i];
245
+ }
246
+ return BRACKETS[0];
247
+ }
248
+ // ─── Proof Message Format ───
249
+ /**
250
+ * Generate proof message with nonce for replay protection
251
+ */
252
+ export function createProofMessage(contractAddress, nonce, chain = 'SN_SEPOLIA') {
253
+ return `Satoshi Proof v1 | Chain: ${chain} | Contract: ${contractAddress} | Nonce: ${nonce} | `;
254
+ }
255
+ /**
256
+ * Generate a complete proof from a Bitcoin signed message
257
+ */
258
+ export function generateProof(message, base64Signature, btcBalance) {
259
+ const msgHash = bitcoinMessageHash(message);
260
+ const sig = parseSignature(base64Signature);
261
+ const pubkey = recoverPublicKey(msgHash, sig);
262
+ const btcAddress = pubkeyToP2PKH(pubkey.compressed);
263
+ const pubkeyHash = pubkeyToPoseidonHash(pubkey.x, pubkey.y);
264
+ const bracket = getBracket(btcBalance);
265
+ return {
266
+ message,
267
+ msgHash: hashToU256Hex(msgHash),
268
+ sigR: '0x' + sig.r.toString(16),
269
+ sigS: '0x' + sig.s.toString(16),
270
+ yParity: sig.yParity,
271
+ pubkeyX: '0x' + pubkey.x.toString(16),
272
+ pubkeyY: '0x' + pubkey.y.toString(16),
273
+ pubkeyHash,
274
+ btcAddress,
275
+ bracket: bracket.id,
276
+ bracketName: bracket.name,
277
+ bracketEmoji: bracket.emoji,
278
+ };
279
+ }
280
+ //# sourceMappingURL=bitcoin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitcoin.js","sourceRoot":"","sources":["../src/bitcoin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @satoshi-proof/sdk
3
+ *
4
+ * Bitcoin signature verification and proof generation for Starknet
5
+ * Implements BIP-137 Bitcoin signed message verification with Poseidon hashing
6
+ */
7
+ export { generateProof, getBracket, bitcoinMessageHash, hashToU256Hex, parseSignature, recoverPublicKey, pubkeyToP2PKH, pubkeyToP2WPKH, pubkeyToAllAddresses, pubkeyToHash160, pubkeyToPoseidonHash, type ParsedSignature, type ProofData, type Bracket, BRACKETS, } from './bitcoin.js';
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @satoshi-proof/sdk
3
+ *
4
+ * Bitcoin signature verification and proof generation for Starknet
5
+ * Implements BIP-137 Bitcoin signed message verification with Poseidon hashing
6
+ */
7
+ export {
8
+ // Core functions
9
+ generateProof, getBracket,
10
+ // Bitcoin utilities
11
+ bitcoinMessageHash, hashToU256Hex, parseSignature, recoverPublicKey, pubkeyToP2PKH, pubkeyToP2WPKH, pubkeyToAllAddresses, pubkeyToHash160, pubkeyToPoseidonHash,
12
+ // Constants
13
+ BRACKETS, } from './bitcoin.js';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO;AACL,iBAAiB;AACjB,aAAa,EACb,UAAU;AAEV,oBAAoB;AACpB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,oBAAoB;AAOpB,YAAY;AACZ,QAAQ,GACT,MAAM,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "satoshi-proof-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Bitcoin signature verification and proof generation SDK for Starknet - implements BIP-137 message signing with Poseidon hashing",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "test": "vitest run"
21
+ },
22
+ "keywords": [
23
+ "bitcoin",
24
+ "signature",
25
+ "bip137",
26
+ "starknet",
27
+ "poseidon",
28
+ "proof",
29
+ "secp256k1",
30
+ "verification"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "@noble/hashes": "^2.0.1",
36
+ "@noble/secp256k1": "^3.0.0",
37
+ "starknet": "^7.6.4"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.3.3",
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.0.18"
43
+ },
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/yourusername/satoshi-proof"
47
+ },
48
+ "bugs": {
49
+ "url": "https://github.com/yourusername/satoshi-proof/issues"
50
+ },
51
+ "homepage": "https://github.com/yourusername/satoshi-proof#readme"
52
+ }