@talismn/crypto 0.1.2 → 0.1.3

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.
@@ -1,2 +1,3 @@
1
1
  import type { AddressEncoding, KeypairCurve } from "../../types";
2
+ /** NOTE: Try not to use this too much, it will need to change */
2
3
  export declare const addressEncodingFromCurve: (curve: KeypairCurve) => AddressEncoding;
@@ -0,0 +1,37 @@
1
+ export declare const isBitcoinAddress: (address: string) => boolean;
2
+ export declare function isBech32mAddress(address: string): boolean;
3
+ export declare function isBech32Address(address: string): boolean;
4
+ export declare function isBase58CheckAddress(address: string): boolean;
5
+ /**
6
+ * Converts a Bech32m encoded address to its corresponding data representation.
7
+ * @param address - The Bech32m encoded address.
8
+ * @returns An object containing the version, prefix, and data of the address.
9
+ * @throws {TypeError} If the address uses the wrong encoding.
10
+ */
11
+ export declare function fromBech32m(address: string): {
12
+ version: number;
13
+ prefix: string;
14
+ data: Uint8Array<ArrayBuffer>;
15
+ };
16
+ /**
17
+ * Converts a Bech32 encoded address to its corresponding data representation.
18
+ * @param address - The Bech32 encoded address.
19
+ * @returns An object containing the version, prefix, and data of the address.
20
+ * @throws {TypeError} If the address uses the wrong encoding.
21
+ */
22
+ export declare function fromBech32(address: string): {
23
+ version: number;
24
+ prefix: string;
25
+ data: Uint8Array<ArrayBuffer>;
26
+ };
27
+ /**
28
+ * Decodes a base58check encoded Bitcoin address and returns the version and hash.
29
+ *
30
+ * @param address - The base58check encoded Bitcoin address to decode.
31
+ * @returns An object containing the version and hash of the decoded address.
32
+ * @throws {TypeError} If the address is too short or too long.
33
+ */
34
+ export declare function fromBase58Check(address: string): {
35
+ version: number;
36
+ hash: Uint8Array<ArrayBuffer>;
37
+ };
@@ -1,5 +1,6 @@
1
+ export * from "./addressEncodingFromCurve";
1
2
  export * from "./base58";
3
+ export * from "./bitcoin";
4
+ export * from "./detectAddressEncoding";
2
5
  export * from "./ethereum";
3
6
  export * from "./ss58";
4
- export * from "./addressEncodingFromCurve";
5
- export * from "./detectAddressEncoding";
@@ -1,9 +1,9 @@
1
- export type KeypairCurve = "ecdsa" | "ed25519" | "sr25519" | "ethereum" | "solana";
2
- export type AddressEncoding = "ss58" | "ethereum" | "base58";
1
+ export type KeypairCurve = "ecdsa" | "ed25519" | "sr25519" | "ethereum" | "bitcoin-ed25519" | "bitcoin-ecdsa" | "solana";
2
+ export type AddressEncoding = "ss58" | "ethereum" | "bech32m" | "bech32" | "base58check" | "base58";
3
3
  export type Keypair = {
4
4
  type: KeypairCurve;
5
5
  secretKey: Uint8Array;
6
6
  publicKey: Uint8Array;
7
7
  address: string;
8
8
  };
9
- export type Platform = "ethereum" | "polkadot" | "solana";
9
+ export type Platform = "ethereum" | "polkadot" | "bitcoin" | "solana";
@@ -3,6 +3,8 @@
3
3
  var bip39 = require('@scure/bip39');
4
4
  var english = require('@scure/bip39/wordlists/english');
5
5
  var base = require('@scure/base');
6
+ var bech32 = require('bech32');
7
+ var bs58check = require('bs58check');
6
8
  var sha3 = require('@noble/hashes/sha3');
7
9
  var utils = require('@noble/hashes/utils');
8
10
  var blake2b = require('@noble/hashes/blake2b');
@@ -15,6 +17,10 @@ var hmac = require('@noble/hashes/hmac');
15
17
  var sha512 = require('@noble/hashes/sha512');
16
18
  var microSr25519 = require('micro-sr25519');
17
19
 
20
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
+
22
+ var bs58check__default = /*#__PURE__*/_interopDefault(bs58check);
23
+
18
24
  const pbkdf2 = async (hash, entropy, salt, iterations, outputLenBytes) => {
19
25
  // NOTE: react-native-quick-crypto (our `global.crypto` polyfill on Talisman Mobile) doesn't support `crypto.subtle.deriveKey`.
20
26
  // But, we can work around this by using `crypto.subtle.deriveBits` and `crypto.subtle.importKey`, which when used together
@@ -56,6 +62,9 @@ const getSeedDerivationType = curve => {
56
62
  case "ethereum":
57
63
  case "solana":
58
64
  return "classic";
65
+ case "bitcoin-ecdsa":
66
+ case "bitcoin-ed25519":
67
+ throw new Error("seed derivation is not implemented for Bitcoin");
59
68
  }
60
69
  };
61
70
 
@@ -115,6 +124,26 @@ const getDevSeed = async curve => {
115
124
  return DEV_SEED_CACHE.get(type);
116
125
  };
117
126
 
127
+ /** NOTE: Try not to use this too much, it will need to change */
128
+ const addressEncodingFromCurve = curve => {
129
+ switch (curve) {
130
+ case "sr25519":
131
+ case "ed25519":
132
+ case "ecdsa":
133
+ return "ss58";
134
+ case "bitcoin-ecdsa":
135
+ case "bitcoin-ed25519":
136
+ // NOTE: Bitcoin has multiple address formats, so this isn't necessarily correct
137
+ // The format MAY be bech32m, but it might also be bech32 or base58check.
138
+ // bech32m is the most recent format.
139
+ return "bech32m";
140
+ case "ethereum":
141
+ return "ethereum";
142
+ case "solana":
143
+ return "base58";
144
+ }
145
+ };
146
+
118
147
  const encodeAddressBase58 = publicKey => {
119
148
  return base.base58.encode(publicKey);
120
149
  };
@@ -128,6 +157,94 @@ function isBase58Address(address) {
128
157
  }
129
158
  }
130
159
 
160
+ const isBitcoinAddress = address => isBech32mAddress(address) || isBech32Address(address) || isBase58CheckAddress(address);
161
+ function isBech32mAddress(address) {
162
+ try {
163
+ fromBech32m(address);
164
+ } catch {
165
+ return false;
166
+ }
167
+ return true;
168
+ }
169
+ function isBech32Address(address) {
170
+ try {
171
+ fromBech32(address);
172
+ } catch {
173
+ return false;
174
+ }
175
+ return true;
176
+ }
177
+ function isBase58CheckAddress(address) {
178
+ try {
179
+ fromBase58Check(address);
180
+ } catch {
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+
186
+ /**
187
+ * Converts a Bech32m encoded address to its corresponding data representation.
188
+ * @param address - The Bech32m encoded address.
189
+ * @returns An object containing the version, prefix, and data of the address.
190
+ * @throws {TypeError} If the address uses the wrong encoding.
191
+ */
192
+ function fromBech32m(address) {
193
+ const result = bech32.bech32m.decode(address);
194
+ const version = result.words[0];
195
+ if (version === 0) throw new TypeError(address + " uses wrong encoding");
196
+ const data = bech32.bech32m.fromWords(result.words.slice(1));
197
+ return {
198
+ version,
199
+ prefix: result.prefix,
200
+ data: Uint8Array.from(data)
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Converts a Bech32 encoded address to its corresponding data representation.
206
+ * @param address - The Bech32 encoded address.
207
+ * @returns An object containing the version, prefix, and data of the address.
208
+ * @throws {TypeError} If the address uses the wrong encoding.
209
+ */
210
+ function fromBech32(address) {
211
+ const result = bech32.bech32.decode(address);
212
+ const version = result.words[0];
213
+ if (version !== 0) throw new TypeError(address + " uses wrong encoding");
214
+ const data = bech32.bech32.fromWords(result.words.slice(1));
215
+ return {
216
+ version,
217
+ prefix: result.prefix,
218
+ data: Uint8Array.from(data)
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Decodes a base58check encoded Bitcoin address and returns the version and hash.
224
+ *
225
+ * @param address - The base58check encoded Bitcoin address to decode.
226
+ * @returns An object containing the version and hash of the decoded address.
227
+ * @throws {TypeError} If the address is too short or too long.
228
+ */
229
+ function fromBase58Check(address) {
230
+ const payload = bs58check__default.default.decode(address);
231
+ if (payload.length < 21) throw new TypeError(address + " is too short");
232
+ if (payload.length > 21) throw new TypeError(address + " is too long");
233
+ function readUInt8(buffer, offset) {
234
+ if (offset + 1 > buffer.length) {
235
+ throw new Error("Offset is outside the bounds of Uint8Array");
236
+ }
237
+ const buf = Buffer.from(buffer);
238
+ return buf.readUInt8(offset);
239
+ }
240
+ const version = readUInt8(payload, 0);
241
+ const hash = payload.slice(1);
242
+ return {
243
+ version,
244
+ hash
245
+ };
246
+ }
247
+
131
248
  /**
132
249
  * Encodes a public key using H160 encoding with Ethereum checksum.
133
250
  */
@@ -215,23 +332,13 @@ function isSs58Address(address) {
215
332
  }
216
333
  }
217
334
 
218
- const addressEncodingFromCurve = curve => {
219
- switch (curve) {
220
- case "sr25519":
221
- case "ed25519":
222
- case "ecdsa":
223
- return "ss58";
224
- case "ethereum":
225
- return "ethereum";
226
- case "solana":
227
- return "base58";
228
- }
229
- };
230
-
231
335
  const CACHE$1 = new Map();
232
336
  const detectAddressEncodingInner = address => {
233
337
  if (isEthereumAddress(address)) return "ethereum";
234
338
  if (isSs58Address(address)) return "ss58";
339
+ if (isBech32mAddress(address)) return "bech32m";
340
+ if (isBech32Address(address)) return "bech32";
341
+ if (isBase58CheckAddress(address)) return "base58check";
235
342
  if (isBase58Address(address)) return "base58";
236
343
  throw new Error(`Unknown address encoding`);
237
344
  };
@@ -246,6 +353,10 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
246
353
  return encodeAddressSs58(publicKey, options?.ss58Prefix);
247
354
  case "ethereum":
248
355
  return encodeAddressEthereum(publicKey);
356
+ case "bech32m":
357
+ case "bech32":
358
+ case "base58check":
359
+ throw new Error("addressFromPublicKey is not implemented for Bitcoin");
249
360
  case "base58":
250
361
  return encodeAddressBase58(publicKey);
251
362
  }
@@ -268,6 +379,9 @@ const normalizeAnyAddress = address => {
268
379
  switch (detectAddressEncoding(address)) {
269
380
  case "ethereum":
270
381
  return checksumEthereumAddress(address);
382
+ case "bech32m":
383
+ case "bech32":
384
+ case "base58check":
271
385
  case "base58":
272
386
  return address;
273
387
  case "ss58":
@@ -448,6 +562,9 @@ const deriveKeypair = (seed, derivationPath, curve) => {
448
562
  return deriveEd25519(seed, derivationPath);
449
563
  case "ecdsa":
450
564
  return deriveEcdsa(seed, derivationPath);
565
+ case "bitcoin-ecdsa":
566
+ case "bitcoin-ed25519":
567
+ throw new Error("deriveKeypair is not implemented for Bitcoin");
451
568
  case "ethereum":
452
569
  return deriveEthereum(seed, derivationPath);
453
570
  case "solana":
@@ -464,6 +581,9 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
464
581
  return getPublicKeySr25519(secretKey);
465
582
  case "ed25519":
466
583
  return getPublicKeyEd25519(secretKey);
584
+ case "bitcoin-ecdsa":
585
+ case "bitcoin-ed25519":
586
+ throw new Error("getPublicKeyFromSecret is not implemented for Bitcoin");
467
587
  case "solana":
468
588
  return getPublicKeySolana(secretKey);
469
589
  }
@@ -519,6 +639,8 @@ const parseSecretKey = (secretKey, curve) => {
519
639
  case "ed25519":
520
640
  case "sr25519":
521
641
  case "ecdsa":
642
+ case "bitcoin-ecdsa":
643
+ case "bitcoin-ed25519":
522
644
  case "solana":
523
645
  throw new Error("Not implemented");
524
646
  }
@@ -542,6 +664,9 @@ const platformFromCurve = curve => {
542
664
  return "polkadot";
543
665
  case "ethereum":
544
666
  return "ethereum";
667
+ case "bitcoin-ecdsa":
668
+ case "bitcoin-ed25519":
669
+ return "bitcoin";
545
670
  case "solana":
546
671
  return "solana";
547
672
  }
@@ -552,6 +677,10 @@ const platformFromEncoding = encoding => {
552
677
  return "polkadot";
553
678
  case "ethereum":
554
679
  return "ethereum";
680
+ case "bech32m":
681
+ case "bech32":
682
+ case "base58check":
683
+ return "bitcoin";
555
684
  case "base58":
556
685
  return "solana";
557
686
  }
@@ -586,12 +715,19 @@ exports.encodeAddressEthereum = encodeAddressEthereum;
586
715
  exports.encodeAddressSs58 = encodeAddressSs58;
587
716
  exports.entropyToMnemonic = entropyToMnemonic;
588
717
  exports.entropyToSeed = entropyToSeed;
718
+ exports.fromBase58Check = fromBase58Check;
719
+ exports.fromBech32 = fromBech32;
720
+ exports.fromBech32m = fromBech32m;
589
721
  exports.generateMnemonic = generateMnemonic;
590
722
  exports.getDevSeed = getDevSeed;
591
723
  exports.getPublicKeyFromSecret = getPublicKeyFromSecret;
592
724
  exports.getSafeHash = getSafeHash;
593
725
  exports.isAddressEqual = isAddressEqual;
594
726
  exports.isBase58Address = isBase58Address;
727
+ exports.isBase58CheckAddress = isBase58CheckAddress;
728
+ exports.isBech32Address = isBech32Address;
729
+ exports.isBech32mAddress = isBech32mAddress;
730
+ exports.isBitcoinAddress = isBitcoinAddress;
595
731
  exports.isEthereumAddress = isEthereumAddress;
596
732
  exports.isSs58Address = isSs58Address;
597
733
  exports.isValidDerivationPath = isValidDerivationPath;
@@ -3,6 +3,8 @@
3
3
  var bip39 = require('@scure/bip39');
4
4
  var english = require('@scure/bip39/wordlists/english');
5
5
  var base = require('@scure/base');
6
+ var bech32 = require('bech32');
7
+ var bs58check = require('bs58check');
6
8
  var sha3 = require('@noble/hashes/sha3');
7
9
  var utils = require('@noble/hashes/utils');
8
10
  var blake2b = require('@noble/hashes/blake2b');
@@ -15,6 +17,10 @@ var hmac = require('@noble/hashes/hmac');
15
17
  var sha512 = require('@noble/hashes/sha512');
16
18
  var microSr25519 = require('micro-sr25519');
17
19
 
20
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
+
22
+ var bs58check__default = /*#__PURE__*/_interopDefault(bs58check);
23
+
18
24
  const pbkdf2 = async (hash, entropy, salt, iterations, outputLenBytes) => {
19
25
  // NOTE: react-native-quick-crypto (our `global.crypto` polyfill on Talisman Mobile) doesn't support `crypto.subtle.deriveKey`.
20
26
  // But, we can work around this by using `crypto.subtle.deriveBits` and `crypto.subtle.importKey`, which when used together
@@ -56,6 +62,9 @@ const getSeedDerivationType = curve => {
56
62
  case "ethereum":
57
63
  case "solana":
58
64
  return "classic";
65
+ case "bitcoin-ecdsa":
66
+ case "bitcoin-ed25519":
67
+ throw new Error("seed derivation is not implemented for Bitcoin");
59
68
  }
60
69
  };
61
70
 
@@ -115,6 +124,26 @@ const getDevSeed = async curve => {
115
124
  return DEV_SEED_CACHE.get(type);
116
125
  };
117
126
 
127
+ /** NOTE: Try not to use this too much, it will need to change */
128
+ const addressEncodingFromCurve = curve => {
129
+ switch (curve) {
130
+ case "sr25519":
131
+ case "ed25519":
132
+ case "ecdsa":
133
+ return "ss58";
134
+ case "bitcoin-ecdsa":
135
+ case "bitcoin-ed25519":
136
+ // NOTE: Bitcoin has multiple address formats, so this isn't necessarily correct
137
+ // The format MAY be bech32m, but it might also be bech32 or base58check.
138
+ // bech32m is the most recent format.
139
+ return "bech32m";
140
+ case "ethereum":
141
+ return "ethereum";
142
+ case "solana":
143
+ return "base58";
144
+ }
145
+ };
146
+
118
147
  const encodeAddressBase58 = publicKey => {
119
148
  return base.base58.encode(publicKey);
120
149
  };
@@ -128,6 +157,94 @@ function isBase58Address(address) {
128
157
  }
129
158
  }
130
159
 
160
+ const isBitcoinAddress = address => isBech32mAddress(address) || isBech32Address(address) || isBase58CheckAddress(address);
161
+ function isBech32mAddress(address) {
162
+ try {
163
+ fromBech32m(address);
164
+ } catch {
165
+ return false;
166
+ }
167
+ return true;
168
+ }
169
+ function isBech32Address(address) {
170
+ try {
171
+ fromBech32(address);
172
+ } catch {
173
+ return false;
174
+ }
175
+ return true;
176
+ }
177
+ function isBase58CheckAddress(address) {
178
+ try {
179
+ fromBase58Check(address);
180
+ } catch {
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+
186
+ /**
187
+ * Converts a Bech32m encoded address to its corresponding data representation.
188
+ * @param address - The Bech32m encoded address.
189
+ * @returns An object containing the version, prefix, and data of the address.
190
+ * @throws {TypeError} If the address uses the wrong encoding.
191
+ */
192
+ function fromBech32m(address) {
193
+ const result = bech32.bech32m.decode(address);
194
+ const version = result.words[0];
195
+ if (version === 0) throw new TypeError(address + " uses wrong encoding");
196
+ const data = bech32.bech32m.fromWords(result.words.slice(1));
197
+ return {
198
+ version,
199
+ prefix: result.prefix,
200
+ data: Uint8Array.from(data)
201
+ };
202
+ }
203
+
204
+ /**
205
+ * Converts a Bech32 encoded address to its corresponding data representation.
206
+ * @param address - The Bech32 encoded address.
207
+ * @returns An object containing the version, prefix, and data of the address.
208
+ * @throws {TypeError} If the address uses the wrong encoding.
209
+ */
210
+ function fromBech32(address) {
211
+ const result = bech32.bech32.decode(address);
212
+ const version = result.words[0];
213
+ if (version !== 0) throw new TypeError(address + " uses wrong encoding");
214
+ const data = bech32.bech32.fromWords(result.words.slice(1));
215
+ return {
216
+ version,
217
+ prefix: result.prefix,
218
+ data: Uint8Array.from(data)
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Decodes a base58check encoded Bitcoin address and returns the version and hash.
224
+ *
225
+ * @param address - The base58check encoded Bitcoin address to decode.
226
+ * @returns An object containing the version and hash of the decoded address.
227
+ * @throws {TypeError} If the address is too short or too long.
228
+ */
229
+ function fromBase58Check(address) {
230
+ const payload = bs58check__default.default.decode(address);
231
+ if (payload.length < 21) throw new TypeError(address + " is too short");
232
+ if (payload.length > 21) throw new TypeError(address + " is too long");
233
+ function readUInt8(buffer, offset) {
234
+ if (offset + 1 > buffer.length) {
235
+ throw new Error("Offset is outside the bounds of Uint8Array");
236
+ }
237
+ const buf = Buffer.from(buffer);
238
+ return buf.readUInt8(offset);
239
+ }
240
+ const version = readUInt8(payload, 0);
241
+ const hash = payload.slice(1);
242
+ return {
243
+ version,
244
+ hash
245
+ };
246
+ }
247
+
131
248
  /**
132
249
  * Encodes a public key using H160 encoding with Ethereum checksum.
133
250
  */
@@ -215,23 +332,13 @@ function isSs58Address(address) {
215
332
  }
216
333
  }
217
334
 
218
- const addressEncodingFromCurve = curve => {
219
- switch (curve) {
220
- case "sr25519":
221
- case "ed25519":
222
- case "ecdsa":
223
- return "ss58";
224
- case "ethereum":
225
- return "ethereum";
226
- case "solana":
227
- return "base58";
228
- }
229
- };
230
-
231
335
  const CACHE$1 = new Map();
232
336
  const detectAddressEncodingInner = address => {
233
337
  if (isEthereumAddress(address)) return "ethereum";
234
338
  if (isSs58Address(address)) return "ss58";
339
+ if (isBech32mAddress(address)) return "bech32m";
340
+ if (isBech32Address(address)) return "bech32";
341
+ if (isBase58CheckAddress(address)) return "base58check";
235
342
  if (isBase58Address(address)) return "base58";
236
343
  throw new Error(`Unknown address encoding`);
237
344
  };
@@ -246,6 +353,10 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
246
353
  return encodeAddressSs58(publicKey, options?.ss58Prefix);
247
354
  case "ethereum":
248
355
  return encodeAddressEthereum(publicKey);
356
+ case "bech32m":
357
+ case "bech32":
358
+ case "base58check":
359
+ throw new Error("addressFromPublicKey is not implemented for Bitcoin");
249
360
  case "base58":
250
361
  return encodeAddressBase58(publicKey);
251
362
  }
@@ -268,6 +379,9 @@ const normalizeAnyAddress = address => {
268
379
  switch (detectAddressEncoding(address)) {
269
380
  case "ethereum":
270
381
  return checksumEthereumAddress(address);
382
+ case "bech32m":
383
+ case "bech32":
384
+ case "base58check":
271
385
  case "base58":
272
386
  return address;
273
387
  case "ss58":
@@ -448,6 +562,9 @@ const deriveKeypair = (seed, derivationPath, curve) => {
448
562
  return deriveEd25519(seed, derivationPath);
449
563
  case "ecdsa":
450
564
  return deriveEcdsa(seed, derivationPath);
565
+ case "bitcoin-ecdsa":
566
+ case "bitcoin-ed25519":
567
+ throw new Error("deriveKeypair is not implemented for Bitcoin");
451
568
  case "ethereum":
452
569
  return deriveEthereum(seed, derivationPath);
453
570
  case "solana":
@@ -464,6 +581,9 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
464
581
  return getPublicKeySr25519(secretKey);
465
582
  case "ed25519":
466
583
  return getPublicKeyEd25519(secretKey);
584
+ case "bitcoin-ecdsa":
585
+ case "bitcoin-ed25519":
586
+ throw new Error("getPublicKeyFromSecret is not implemented for Bitcoin");
467
587
  case "solana":
468
588
  return getPublicKeySolana(secretKey);
469
589
  }
@@ -519,6 +639,8 @@ const parseSecretKey = (secretKey, curve) => {
519
639
  case "ed25519":
520
640
  case "sr25519":
521
641
  case "ecdsa":
642
+ case "bitcoin-ecdsa":
643
+ case "bitcoin-ed25519":
522
644
  case "solana":
523
645
  throw new Error("Not implemented");
524
646
  }
@@ -542,6 +664,9 @@ const platformFromCurve = curve => {
542
664
  return "polkadot";
543
665
  case "ethereum":
544
666
  return "ethereum";
667
+ case "bitcoin-ecdsa":
668
+ case "bitcoin-ed25519":
669
+ return "bitcoin";
545
670
  case "solana":
546
671
  return "solana";
547
672
  }
@@ -552,6 +677,10 @@ const platformFromEncoding = encoding => {
552
677
  return "polkadot";
553
678
  case "ethereum":
554
679
  return "ethereum";
680
+ case "bech32m":
681
+ case "bech32":
682
+ case "base58check":
683
+ return "bitcoin";
555
684
  case "base58":
556
685
  return "solana";
557
686
  }
@@ -586,12 +715,19 @@ exports.encodeAddressEthereum = encodeAddressEthereum;
586
715
  exports.encodeAddressSs58 = encodeAddressSs58;
587
716
  exports.entropyToMnemonic = entropyToMnemonic;
588
717
  exports.entropyToSeed = entropyToSeed;
718
+ exports.fromBase58Check = fromBase58Check;
719
+ exports.fromBech32 = fromBech32;
720
+ exports.fromBech32m = fromBech32m;
589
721
  exports.generateMnemonic = generateMnemonic;
590
722
  exports.getDevSeed = getDevSeed;
591
723
  exports.getPublicKeyFromSecret = getPublicKeyFromSecret;
592
724
  exports.getSafeHash = getSafeHash;
593
725
  exports.isAddressEqual = isAddressEqual;
594
726
  exports.isBase58Address = isBase58Address;
727
+ exports.isBase58CheckAddress = isBase58CheckAddress;
728
+ exports.isBech32Address = isBech32Address;
729
+ exports.isBech32mAddress = isBech32mAddress;
730
+ exports.isBitcoinAddress = isBitcoinAddress;
595
731
  exports.isEthereumAddress = isEthereumAddress;
596
732
  exports.isSs58Address = isSs58Address;
597
733
  exports.isValidDerivationPath = isValidDerivationPath;
@@ -2,6 +2,8 @@ import { mnemonicToEntropy as mnemonicToEntropy$1, entropyToMnemonic as entropyT
2
2
  import { wordlist } from '@scure/bip39/wordlists/english';
3
3
  import { base58, bytesToString, stringToBytes } from '@scure/base';
4
4
  export { bytesToString, stringToBytes } from '@scure/base';
5
+ import { bech32m, bech32 } from 'bech32';
6
+ import bs58check from 'bs58check';
5
7
  import { keccak_256 } from '@noble/hashes/sha3';
6
8
  import { bytesToHex, randomBytes } from '@noble/hashes/utils';
7
9
  import { blake2b } from '@noble/hashes/blake2b';
@@ -55,6 +57,9 @@ const getSeedDerivationType = curve => {
55
57
  case "ethereum":
56
58
  case "solana":
57
59
  return "classic";
60
+ case "bitcoin-ecdsa":
61
+ case "bitcoin-ed25519":
62
+ throw new Error("seed derivation is not implemented for Bitcoin");
58
63
  }
59
64
  };
60
65
 
@@ -114,6 +119,26 @@ const getDevSeed = async curve => {
114
119
  return DEV_SEED_CACHE.get(type);
115
120
  };
116
121
 
122
+ /** NOTE: Try not to use this too much, it will need to change */
123
+ const addressEncodingFromCurve = curve => {
124
+ switch (curve) {
125
+ case "sr25519":
126
+ case "ed25519":
127
+ case "ecdsa":
128
+ return "ss58";
129
+ case "bitcoin-ecdsa":
130
+ case "bitcoin-ed25519":
131
+ // NOTE: Bitcoin has multiple address formats, so this isn't necessarily correct
132
+ // The format MAY be bech32m, but it might also be bech32 or base58check.
133
+ // bech32m is the most recent format.
134
+ return "bech32m";
135
+ case "ethereum":
136
+ return "ethereum";
137
+ case "solana":
138
+ return "base58";
139
+ }
140
+ };
141
+
117
142
  const encodeAddressBase58 = publicKey => {
118
143
  return base58.encode(publicKey);
119
144
  };
@@ -127,6 +152,94 @@ function isBase58Address(address) {
127
152
  }
128
153
  }
129
154
 
155
+ const isBitcoinAddress = address => isBech32mAddress(address) || isBech32Address(address) || isBase58CheckAddress(address);
156
+ function isBech32mAddress(address) {
157
+ try {
158
+ fromBech32m(address);
159
+ } catch {
160
+ return false;
161
+ }
162
+ return true;
163
+ }
164
+ function isBech32Address(address) {
165
+ try {
166
+ fromBech32(address);
167
+ } catch {
168
+ return false;
169
+ }
170
+ return true;
171
+ }
172
+ function isBase58CheckAddress(address) {
173
+ try {
174
+ fromBase58Check(address);
175
+ } catch {
176
+ return false;
177
+ }
178
+ return true;
179
+ }
180
+
181
+ /**
182
+ * Converts a Bech32m encoded address to its corresponding data representation.
183
+ * @param address - The Bech32m encoded address.
184
+ * @returns An object containing the version, prefix, and data of the address.
185
+ * @throws {TypeError} If the address uses the wrong encoding.
186
+ */
187
+ function fromBech32m(address) {
188
+ const result = bech32m.decode(address);
189
+ const version = result.words[0];
190
+ if (version === 0) throw new TypeError(address + " uses wrong encoding");
191
+ const data = bech32m.fromWords(result.words.slice(1));
192
+ return {
193
+ version,
194
+ prefix: result.prefix,
195
+ data: Uint8Array.from(data)
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Converts a Bech32 encoded address to its corresponding data representation.
201
+ * @param address - The Bech32 encoded address.
202
+ * @returns An object containing the version, prefix, and data of the address.
203
+ * @throws {TypeError} If the address uses the wrong encoding.
204
+ */
205
+ function fromBech32(address) {
206
+ const result = bech32.decode(address);
207
+ const version = result.words[0];
208
+ if (version !== 0) throw new TypeError(address + " uses wrong encoding");
209
+ const data = bech32.fromWords(result.words.slice(1));
210
+ return {
211
+ version,
212
+ prefix: result.prefix,
213
+ data: Uint8Array.from(data)
214
+ };
215
+ }
216
+
217
+ /**
218
+ * Decodes a base58check encoded Bitcoin address and returns the version and hash.
219
+ *
220
+ * @param address - The base58check encoded Bitcoin address to decode.
221
+ * @returns An object containing the version and hash of the decoded address.
222
+ * @throws {TypeError} If the address is too short or too long.
223
+ */
224
+ function fromBase58Check(address) {
225
+ const payload = bs58check.decode(address);
226
+ if (payload.length < 21) throw new TypeError(address + " is too short");
227
+ if (payload.length > 21) throw new TypeError(address + " is too long");
228
+ function readUInt8(buffer, offset) {
229
+ if (offset + 1 > buffer.length) {
230
+ throw new Error("Offset is outside the bounds of Uint8Array");
231
+ }
232
+ const buf = Buffer.from(buffer);
233
+ return buf.readUInt8(offset);
234
+ }
235
+ const version = readUInt8(payload, 0);
236
+ const hash = payload.slice(1);
237
+ return {
238
+ version,
239
+ hash
240
+ };
241
+ }
242
+
130
243
  /**
131
244
  * Encodes a public key using H160 encoding with Ethereum checksum.
132
245
  */
@@ -214,23 +327,13 @@ function isSs58Address(address) {
214
327
  }
215
328
  }
216
329
 
217
- const addressEncodingFromCurve = curve => {
218
- switch (curve) {
219
- case "sr25519":
220
- case "ed25519":
221
- case "ecdsa":
222
- return "ss58";
223
- case "ethereum":
224
- return "ethereum";
225
- case "solana":
226
- return "base58";
227
- }
228
- };
229
-
230
330
  const CACHE$1 = new Map();
231
331
  const detectAddressEncodingInner = address => {
232
332
  if (isEthereumAddress(address)) return "ethereum";
233
333
  if (isSs58Address(address)) return "ss58";
334
+ if (isBech32mAddress(address)) return "bech32m";
335
+ if (isBech32Address(address)) return "bech32";
336
+ if (isBase58CheckAddress(address)) return "base58check";
234
337
  if (isBase58Address(address)) return "base58";
235
338
  throw new Error(`Unknown address encoding`);
236
339
  };
@@ -245,6 +348,10 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
245
348
  return encodeAddressSs58(publicKey, options?.ss58Prefix);
246
349
  case "ethereum":
247
350
  return encodeAddressEthereum(publicKey);
351
+ case "bech32m":
352
+ case "bech32":
353
+ case "base58check":
354
+ throw new Error("addressFromPublicKey is not implemented for Bitcoin");
248
355
  case "base58":
249
356
  return encodeAddressBase58(publicKey);
250
357
  }
@@ -267,6 +374,9 @@ const normalizeAnyAddress = address => {
267
374
  switch (detectAddressEncoding(address)) {
268
375
  case "ethereum":
269
376
  return checksumEthereumAddress(address);
377
+ case "bech32m":
378
+ case "bech32":
379
+ case "base58check":
270
380
  case "base58":
271
381
  return address;
272
382
  case "ss58":
@@ -447,6 +557,9 @@ const deriveKeypair = (seed, derivationPath, curve) => {
447
557
  return deriveEd25519(seed, derivationPath);
448
558
  case "ecdsa":
449
559
  return deriveEcdsa(seed, derivationPath);
560
+ case "bitcoin-ecdsa":
561
+ case "bitcoin-ed25519":
562
+ throw new Error("deriveKeypair is not implemented for Bitcoin");
450
563
  case "ethereum":
451
564
  return deriveEthereum(seed, derivationPath);
452
565
  case "solana":
@@ -463,6 +576,9 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
463
576
  return getPublicKeySr25519(secretKey);
464
577
  case "ed25519":
465
578
  return getPublicKeyEd25519(secretKey);
579
+ case "bitcoin-ecdsa":
580
+ case "bitcoin-ed25519":
581
+ throw new Error("getPublicKeyFromSecret is not implemented for Bitcoin");
466
582
  case "solana":
467
583
  return getPublicKeySolana(secretKey);
468
584
  }
@@ -518,6 +634,8 @@ const parseSecretKey = (secretKey, curve) => {
518
634
  case "ed25519":
519
635
  case "sr25519":
520
636
  case "ecdsa":
637
+ case "bitcoin-ecdsa":
638
+ case "bitcoin-ed25519":
521
639
  case "solana":
522
640
  throw new Error("Not implemented");
523
641
  }
@@ -541,6 +659,9 @@ const platformFromCurve = curve => {
541
659
  return "polkadot";
542
660
  case "ethereum":
543
661
  return "ethereum";
662
+ case "bitcoin-ecdsa":
663
+ case "bitcoin-ed25519":
664
+ return "bitcoin";
544
665
  case "solana":
545
666
  return "solana";
546
667
  }
@@ -551,6 +672,10 @@ const platformFromEncoding = encoding => {
551
672
  return "polkadot";
552
673
  case "ethereum":
553
674
  return "ethereum";
675
+ case "bech32m":
676
+ case "bech32":
677
+ case "base58check":
678
+ return "bitcoin";
554
679
  case "base58":
555
680
  return "solana";
556
681
  }
@@ -560,4 +685,4 @@ const platformFromAddress = address => {
560
685
  return platformFromEncoding(encoding);
561
686
  };
562
687
 
563
- export { DEV_MNEMONIC_ETHEREUM, DEV_MNEMONIC_POLKADOT, addressEncodingFromCurve, addressFromPublicKey, addressFromSuri, blake2b256, blake2b512, blake3, checksumEthereumAddress, decodeSs58Address, deriveKeypair, detectAddressEncoding, encodeAddressBase58, encodeAddressEthereum, encodeAddressSs58, entropyToMnemonic, entropyToSeed, generateMnemonic, getDevSeed, getPublicKeyFromSecret, getSafeHash, isAddressEqual, isBase58Address, isEthereumAddress, isSs58Address, isValidDerivationPath, isValidMnemonic, mnemonicToEntropy, normalizeAddress, parseSecretKey, parseSuri, pbkdf2, platformFromAddress, platformFromCurve, platformFromEncoding, removeHexPrefix };
688
+ export { DEV_MNEMONIC_ETHEREUM, DEV_MNEMONIC_POLKADOT, addressEncodingFromCurve, addressFromPublicKey, addressFromSuri, blake2b256, blake2b512, blake3, checksumEthereumAddress, decodeSs58Address, deriveKeypair, detectAddressEncoding, encodeAddressBase58, encodeAddressEthereum, encodeAddressSs58, entropyToMnemonic, entropyToSeed, fromBase58Check, fromBech32, fromBech32m, generateMnemonic, getDevSeed, getPublicKeyFromSecret, getSafeHash, isAddressEqual, isBase58Address, isBase58CheckAddress, isBech32Address, isBech32mAddress, isBitcoinAddress, isEthereumAddress, isSs58Address, isValidDerivationPath, isValidMnemonic, mnemonicToEntropy, normalizeAddress, parseSecretKey, parseSuri, pbkdf2, platformFromAddress, platformFromCurve, platformFromEncoding, removeHexPrefix };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@talismn/crypto",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "author": "Talisman",
5
5
  "homepage": "https://talisman.xyz",
6
6
  "license": "GPL-3.0-or-later",
@@ -27,6 +27,8 @@
27
27
  "@scure/base": "1.2.4",
28
28
  "@scure/bip32": "1.6.2",
29
29
  "@scure/bip39": "1.5.4",
30
+ "bech32": "2.0.0",
31
+ "bs58check": "4.0.0",
30
32
  "micro-sr25519": "0.1.3",
31
33
  "scale-ts": "1.6.1"
32
34
  },