otx-btc-wallet-core 0.1.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.
@@ -0,0 +1,185 @@
1
+ /**
2
+ * PSBT (Partially Signed Bitcoin Transaction) utilities
3
+ */
4
+
5
+ /**
6
+ * Convert PSBT hex to base64
7
+ */
8
+ export function psbtHexToBase64(hex: string): string {
9
+ // Remove any whitespace
10
+ const cleanHex = hex.replace(/\s/g, '');
11
+
12
+ // Validate hex string
13
+ if (!/^[0-9a-fA-F]*$/.test(cleanHex)) {
14
+ throw new Error('Invalid hex string');
15
+ }
16
+
17
+ if (cleanHex.length % 2 !== 0) {
18
+ throw new Error('Hex string must have even length');
19
+ }
20
+
21
+ // Convert hex to bytes then to base64
22
+ const bytes = new Uint8Array(cleanHex.length / 2);
23
+ for (let i = 0; i < cleanHex.length; i += 2) {
24
+ bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16);
25
+ }
26
+
27
+ // Use Buffer in Node.js or btoa in browser
28
+ if (typeof Buffer !== 'undefined') {
29
+ return Buffer.from(bytes).toString('base64');
30
+ }
31
+
32
+ // Browser fallback
33
+ let binary = '';
34
+ for (let i = 0; i < bytes.length; i++) {
35
+ binary += String.fromCharCode(bytes[i]!);
36
+ }
37
+ return btoa(binary);
38
+ }
39
+
40
+ /**
41
+ * Convert PSBT base64 to hex
42
+ */
43
+ export function psbtBase64ToHex(base64: string): string {
44
+ // Decode base64 to bytes
45
+ let bytes: Uint8Array;
46
+
47
+ if (typeof Buffer !== 'undefined') {
48
+ bytes = Buffer.from(base64, 'base64');
49
+ } else {
50
+ // Browser fallback
51
+ const binary = atob(base64);
52
+ bytes = new Uint8Array(binary.length);
53
+ for (let i = 0; i < binary.length; i++) {
54
+ bytes[i] = binary.charCodeAt(i);
55
+ }
56
+ }
57
+
58
+ // Convert bytes to hex
59
+ return Array.from(bytes)
60
+ .map((b) => b.toString(16).padStart(2, '0'))
61
+ .join('');
62
+ }
63
+
64
+ /**
65
+ * Validate PSBT hex format
66
+ * PSBT magic bytes: 0x70736274ff (psbt\xff)
67
+ */
68
+ export function isValidPsbtHex(hex: string): boolean {
69
+ const cleanHex = hex.replace(/\s/g, '').toLowerCase();
70
+
71
+ // Check minimum length (magic bytes = 5 bytes = 10 hex chars)
72
+ if (cleanHex.length < 10) {
73
+ return false;
74
+ }
75
+
76
+ // Check magic bytes
77
+ return cleanHex.startsWith('70736274ff');
78
+ }
79
+
80
+ /**
81
+ * Validate PSBT base64 format
82
+ */
83
+ export function isValidPsbtBase64(base64: string): boolean {
84
+ try {
85
+ const hex = psbtBase64ToHex(base64);
86
+ return isValidPsbtHex(hex);
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Extract basic info from PSBT hex (without full parsing)
94
+ * This is a lightweight check - for full parsing use a library like bitcoinjs-lib
95
+ */
96
+ export function getPsbtInfo(psbtHex: string): {
97
+ isValid: boolean;
98
+ version: number | null;
99
+ inputCount: number | null;
100
+ outputCount: number | null;
101
+ } {
102
+ if (!isValidPsbtHex(psbtHex)) {
103
+ return {
104
+ isValid: false,
105
+ version: null,
106
+ inputCount: null,
107
+ outputCount: null,
108
+ };
109
+ }
110
+
111
+ // PSBT structure is complex, return basic validation only
112
+ // For full parsing, use bitcoinjs-lib or similar
113
+ return {
114
+ isValid: true,
115
+ version: null, // Would need full parsing
116
+ inputCount: null, // Would need full parsing
117
+ outputCount: null, // Would need full parsing
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Combine multiple signed PSBTs into one
123
+ * Note: This is a basic implementation. For complex cases, use bitcoinjs-lib.
124
+ *
125
+ * @param psbts - Array of PSBT hex strings to combine
126
+ * @returns Combined PSBT hex
127
+ */
128
+ export function combinePsbts(psbts: string[]): string {
129
+ if (psbts.length === 0) {
130
+ throw new Error('No PSBTs provided');
131
+ }
132
+
133
+ if (psbts.length === 1) {
134
+ return psbts[0]!;
135
+ }
136
+
137
+ // For proper PSBT combination, you need bitcoinjs-lib
138
+ // This is just a placeholder that returns the first PSBT
139
+ // In production, use: bitcoin.Psbt.combine([psbt1, psbt2, ...])
140
+ console.warn(
141
+ 'combinePsbts: For proper PSBT combination, use bitcoinjs-lib. ' +
142
+ 'This function returns the first PSBT as a fallback.'
143
+ );
144
+
145
+ return psbts[0]!;
146
+ }
147
+
148
+ /**
149
+ * Sighash types for Bitcoin transactions
150
+ */
151
+ export const SighashType = {
152
+ ALL: 0x01,
153
+ NONE: 0x02,
154
+ SINGLE: 0x03,
155
+ ANYONECANPAY: 0x80,
156
+ ALL_ANYONECANPAY: 0x81,
157
+ NONE_ANYONECANPAY: 0x82,
158
+ SINGLE_ANYONECANPAY: 0x83,
159
+ } as const;
160
+
161
+ export type SighashType = (typeof SighashType)[keyof typeof SighashType];
162
+
163
+ /**
164
+ * Get human-readable name for sighash type
165
+ */
166
+ export function getSighashTypeName(sighash: number): string {
167
+ switch (sighash) {
168
+ case SighashType.ALL:
169
+ return 'SIGHASH_ALL';
170
+ case SighashType.NONE:
171
+ return 'SIGHASH_NONE';
172
+ case SighashType.SINGLE:
173
+ return 'SIGHASH_SINGLE';
174
+ case SighashType.ANYONECANPAY:
175
+ return 'SIGHASH_ANYONECANPAY';
176
+ case SighashType.ALL_ANYONECANPAY:
177
+ return 'SIGHASH_ALL|ANYONECANPAY';
178
+ case SighashType.NONE_ANYONECANPAY:
179
+ return 'SIGHASH_NONE|ANYONECANPAY';
180
+ case SighashType.SINGLE_ANYONECANPAY:
181
+ return 'SIGHASH_SINGLE|ANYONECANPAY';
182
+ default:
183
+ return `UNKNOWN(${sighash})`;
184
+ }
185
+ }