@talismn/crypto 0.1.5 → 0.2.1
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/dist/declarations/src/address/encodeAnyAddress.d.ts +5 -0
- package/dist/declarations/src/address/encoding/index.d.ts +1 -1
- package/dist/declarations/src/address/encoding/solana.d.ts +2 -0
- package/dist/declarations/src/address/index.d.ts +2 -0
- package/dist/declarations/src/address/isAddressValid.d.ts +1 -0
- package/dist/declarations/src/derivation/utils.d.ts +3 -12
- package/dist/declarations/src/platform/index.d.ts +4 -4
- package/dist/declarations/src/types/index.d.ts +2 -2
- package/dist/declarations/src/utils/exports.d.ts +2 -1
- package/dist/talismn-crypto.cjs.dev.js +93 -75
- package/dist/talismn-crypto.cjs.prod.js +93 -75
- package/dist/talismn-crypto.esm.js +73 -67
- package/package.json +6 -7
- package/dist/declarations/src/address/encoding/base58.d.ts +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isAddressValid: (address: string) => boolean;
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
import { KeypairCurve } from "../types";
|
|
1
|
+
import { AccountPlatform, KeypairCurve } from "../types";
|
|
2
2
|
export declare const deriveKeypair: (seed: Uint8Array, derivationPath: string, curve: KeypairCurve) => import("../types").Keypair;
|
|
3
3
|
export declare const getPublicKeyFromSecret: (secretKey: Uint8Array, curve: KeypairCurve) => Uint8Array;
|
|
4
|
-
export declare const
|
|
5
|
-
/**
|
|
6
|
-
* @dev we only expect suri to contain a mnemonic and derivation path.
|
|
7
|
-
* for other cases see https://polkadot.js.org/docs/keyring/start/suri/
|
|
8
|
-
*/
|
|
9
|
-
export declare const parseSuri: (suri: string) => {
|
|
10
|
-
mnemonic: string;
|
|
11
|
-
derivationPath: string;
|
|
12
|
-
password: string | undefined;
|
|
13
|
-
};
|
|
4
|
+
export declare const addressFromMnemonic: (mnemonic: string, derivationPath: string, curve: KeypairCurve) => Promise<string>;
|
|
14
5
|
export declare const removeHexPrefix: (secretKey: string) => string;
|
|
15
|
-
export declare const parseSecretKey: (secretKey: string,
|
|
6
|
+
export declare const parseSecretKey: (secretKey: string, platform: AccountPlatform) => Uint8Array<ArrayBufferLike>;
|
|
16
7
|
export declare const isValidDerivationPath: (derivationPath: string, curve: KeypairCurve) => Promise<boolean>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddressEncoding, KeypairCurve
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
1
|
+
import { AccountPlatform, AddressEncoding, KeypairCurve } from "../types";
|
|
2
|
+
export declare const getAccountPlatformFromCurve: (curve: KeypairCurve) => AccountPlatform;
|
|
3
|
+
export declare const getAccountPlatformFromEncoding: (encoding: AddressEncoding) => AccountPlatform;
|
|
4
|
+
export declare const getAccountPlatformFromAddress: (address: string) => AccountPlatform;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type KeypairCurve = "ecdsa" | "ed25519" | "sr25519" | "ethereum" | "bitcoin-ed25519" | "bitcoin-ecdsa" | "solana";
|
|
2
|
-
export type AddressEncoding = "ss58" | "ethereum" | "bech32m" | "bech32" | "base58check" | "
|
|
2
|
+
export type AddressEncoding = "ss58" | "ethereum" | "bech32m" | "bech32" | "base58check" | "base58solana";
|
|
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
|
|
9
|
+
export type AccountPlatform = "ethereum" | "polkadot" | "bitcoin" | "solana";
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { base58, base64, hex, utf8 } from "@scure/base";
|
|
2
|
+
export { ed25519 } from "@noble/curves/ed25519";
|
|
@@ -3,15 +3,15 @@
|
|
|
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 ed25519 = require('@noble/curves/ed25519');
|
|
7
|
+
var secp256k1 = require('@noble/curves/secp256k1');
|
|
6
8
|
var bech32 = require('bech32');
|
|
7
9
|
var bs58check = require('bs58check');
|
|
8
10
|
var sha3 = require('@noble/hashes/sha3');
|
|
9
11
|
var utils = require('@noble/hashes/utils');
|
|
10
12
|
var blake2b = require('@noble/hashes/blake2b');
|
|
11
13
|
var blake3$1 = require('@noble/hashes/blake3');
|
|
12
|
-
var secp256k1 = require('@noble/curves/secp256k1');
|
|
13
14
|
var scaleTs = require('scale-ts');
|
|
14
|
-
var ed25519 = require('@noble/curves/ed25519');
|
|
15
15
|
var bip32 = require('@scure/bip32');
|
|
16
16
|
var hmac = require('@noble/hashes/hmac');
|
|
17
17
|
var sha512 = require('@noble/hashes/sha512');
|
|
@@ -140,18 +140,18 @@ const addressEncodingFromCurve = curve => {
|
|
|
140
140
|
case "ethereum":
|
|
141
141
|
return "ethereum";
|
|
142
142
|
case "solana":
|
|
143
|
-
return "
|
|
143
|
+
return "base58solana";
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
const
|
|
147
|
+
const encodeAddressSolana = publicKey => {
|
|
148
|
+
if (publicKey.length !== 32) throw new Error("Public key must be 32 bytes long for Solana base58 encoding");
|
|
148
149
|
return base.base58.encode(publicKey);
|
|
149
150
|
};
|
|
150
|
-
|
|
151
|
-
function isBase58Address(address) {
|
|
151
|
+
function isSolanaAddress(address) {
|
|
152
152
|
try {
|
|
153
|
-
base.base58.decode(address);
|
|
154
|
-
return
|
|
153
|
+
const bytes = base.base58.decode(address);
|
|
154
|
+
return bytes.length === 32;
|
|
155
155
|
} catch (error) {
|
|
156
156
|
return false;
|
|
157
157
|
}
|
|
@@ -287,7 +287,7 @@ const blake2b512 = msg => blake2b.blake2b(msg, {
|
|
|
287
287
|
const getSafeHash = bytes => {
|
|
288
288
|
// cryptographically secure one way hash
|
|
289
289
|
// outputs 44 characters without special characters
|
|
290
|
-
return base.
|
|
290
|
+
return base.base58.encode(blake3$1.blake3(bytes));
|
|
291
291
|
};
|
|
292
292
|
|
|
293
293
|
// Inspired from MIT licensed @polkadot-labs/hdkd-helpers
|
|
@@ -336,10 +336,10 @@ const CACHE$1 = new Map();
|
|
|
336
336
|
const detectAddressEncodingInner = address => {
|
|
337
337
|
if (isEthereumAddress(address)) return "ethereum";
|
|
338
338
|
if (isSs58Address(address)) return "ss58";
|
|
339
|
+
if (isSolanaAddress(address)) return "base58solana";
|
|
339
340
|
if (isBech32mAddress(address)) return "bech32m";
|
|
340
341
|
if (isBech32Address(address)) return "bech32";
|
|
341
342
|
if (isBase58CheckAddress(address)) return "base58check";
|
|
342
|
-
if (isBase58Address(address)) return "base58";
|
|
343
343
|
throw new Error(`Unknown address encoding`);
|
|
344
344
|
};
|
|
345
345
|
const detectAddressEncoding = address => {
|
|
@@ -353,12 +353,12 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
|
|
|
353
353
|
return encodeAddressSs58(publicKey, options?.ss58Prefix);
|
|
354
354
|
case "ethereum":
|
|
355
355
|
return encodeAddressEthereum(publicKey);
|
|
356
|
+
case "base58solana":
|
|
357
|
+
return encodeAddressSolana(publicKey);
|
|
356
358
|
case "bech32m":
|
|
357
359
|
case "bech32":
|
|
358
360
|
case "base58check":
|
|
359
361
|
throw new Error("addressFromPublicKey is not implemented for Bitcoin");
|
|
360
|
-
case "base58":
|
|
361
|
-
return encodeAddressBase58(publicKey);
|
|
362
362
|
}
|
|
363
363
|
};
|
|
364
364
|
|
|
@@ -382,7 +382,7 @@ const normalizeAnyAddress = address => {
|
|
|
382
382
|
case "bech32m":
|
|
383
383
|
case "bech32":
|
|
384
384
|
case "base58check":
|
|
385
|
-
case "
|
|
385
|
+
case "base58solana":
|
|
386
386
|
return address;
|
|
387
387
|
case "ss58":
|
|
388
388
|
{
|
|
@@ -401,6 +401,29 @@ const isAddressEqual = (address1, address2) => {
|
|
|
401
401
|
}
|
|
402
402
|
};
|
|
403
403
|
|
|
404
|
+
const encodeAnyAddress = (address, options) => {
|
|
405
|
+
// this leverages cache
|
|
406
|
+
const encoding = detectAddressEncoding(address);
|
|
407
|
+
|
|
408
|
+
// this does NOT leverage cache
|
|
409
|
+
if (encoding === "ss58" && options?.ss58Format !== undefined) {
|
|
410
|
+
const [publicKey] = decodeSs58Address(address);
|
|
411
|
+
return encodeAddressSs58(publicKey, options?.ss58Format ?? 42);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// this leverages cache
|
|
415
|
+
return normalizeAddress(address);
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const isAddressValid = address => {
|
|
419
|
+
try {
|
|
420
|
+
detectAddressEncoding(address);
|
|
421
|
+
return true;
|
|
422
|
+
} catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
404
427
|
// Inspired from MIT licensed @polkadot-labs/hdkd helpers
|
|
405
428
|
// https://github.com/polkadot-labs/hdkd/blob/3ef6e02827212d934b59a4e566d8aa61d3ba7b27/packages/hdkd-helpers/src/parseDerivations.ts#L1
|
|
406
429
|
|
|
@@ -535,7 +558,7 @@ const deriveSolana = (seed, derivationPath) => {
|
|
|
535
558
|
type: "solana",
|
|
536
559
|
secretKey,
|
|
537
560
|
publicKey,
|
|
538
|
-
address: addressFromPublicKey(publicKey, "
|
|
561
|
+
address: addressFromPublicKey(publicKey, "base58solana")
|
|
539
562
|
};
|
|
540
563
|
};
|
|
541
564
|
const getPublicKeySolana = secretKey => {
|
|
@@ -593,60 +616,42 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
|
|
|
593
616
|
return getPublicKeySolana(secretKey);
|
|
594
617
|
}
|
|
595
618
|
};
|
|
596
|
-
const
|
|
597
|
-
const {
|
|
598
|
-
mnemonic,
|
|
599
|
-
derivationPath,
|
|
600
|
-
password
|
|
601
|
-
} = parseSuri(suri);
|
|
619
|
+
const addressFromMnemonic = async (mnemonic, derivationPath, curve) => {
|
|
602
620
|
const entropy = mnemonicToEntropy(mnemonic);
|
|
603
|
-
const seed = await entropyToSeed(entropy,
|
|
621
|
+
const seed = await entropyToSeed(entropy, curve);
|
|
604
622
|
const {
|
|
605
|
-
|
|
606
|
-
} = deriveKeypair(seed, derivationPath,
|
|
607
|
-
|
|
608
|
-
const encoding = addressEncodingFromCurve(type);
|
|
609
|
-
return addressFromPublicKey(publicKey, encoding);
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* @dev we only expect suri to contain a mnemonic and derivation path.
|
|
614
|
-
* for other cases see https://polkadot.js.org/docs/keyring/start/suri/
|
|
615
|
-
*/
|
|
616
|
-
const parseSuri = suri => {
|
|
617
|
-
// extract password if any
|
|
618
|
-
const indexOfPassword = suri.indexOf("///");
|
|
619
|
-
const password = indexOfPassword === -1 ? undefined : suri.slice(indexOfPassword + 3);
|
|
620
|
-
if (password) suri = suri.slice(0, indexOfPassword);
|
|
621
|
-
|
|
622
|
-
// split mnemonic and derivation path
|
|
623
|
-
const indexOfSlash = suri.indexOf("/");
|
|
624
|
-
const mnemonic = indexOfSlash === -1 ? suri : suri.slice(0, indexOfSlash);
|
|
625
|
-
let derivationPath = indexOfSlash === -1 ? "" : suri.slice(indexOfSlash);
|
|
626
|
-
|
|
627
|
-
// if BIP44, leading slash must be removed
|
|
628
|
-
if (derivationPath.startsWith("/m/")) derivationPath = derivationPath.slice(1);
|
|
629
|
-
if (!isValidMnemonic(mnemonic)) throw new Error("Invalid mnemonic");
|
|
630
|
-
return {
|
|
631
|
-
mnemonic,
|
|
632
|
-
derivationPath,
|
|
633
|
-
password
|
|
634
|
-
};
|
|
623
|
+
address
|
|
624
|
+
} = deriveKeypair(seed, derivationPath, curve);
|
|
625
|
+
return address;
|
|
635
626
|
};
|
|
636
627
|
const removeHexPrefix = secretKey => {
|
|
637
628
|
if (secretKey.startsWith("0x")) return secretKey.slice(2);
|
|
638
629
|
return secretKey;
|
|
639
630
|
};
|
|
640
|
-
const parseSecretKey = (secretKey,
|
|
641
|
-
switch (
|
|
631
|
+
const parseSecretKey = (secretKey, platform) => {
|
|
632
|
+
switch (platform) {
|
|
642
633
|
case "ethereum":
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
case "bitcoin-ecdsa":
|
|
648
|
-
case "bitcoin-ed25519":
|
|
634
|
+
{
|
|
635
|
+
const privateKey = removeHexPrefix(secretKey);
|
|
636
|
+
return base.hex.decode(privateKey);
|
|
637
|
+
}
|
|
649
638
|
case "solana":
|
|
639
|
+
{
|
|
640
|
+
const bytes = secretKey.startsWith("[") ?
|
|
641
|
+
// JSON bytes array (ex: solflare)
|
|
642
|
+
Uint8Array.from(JSON.parse(secretKey)) :
|
|
643
|
+
// base58 encoded string (ex: phantom)
|
|
644
|
+
base.base58.decode(secretKey);
|
|
645
|
+
if (bytes.length === 64) {
|
|
646
|
+
const privateKey = bytes.slice(0, 32);
|
|
647
|
+
const publicKey = bytes.slice(32, 64);
|
|
648
|
+
const computedPublicKey = getPublicKeySolana(privateKey);
|
|
649
|
+
if (!publicKey.every((b, i) => b === computedPublicKey[i])) throw new Error("Invalid Solana secret key: public key does not match");
|
|
650
|
+
return privateKey;
|
|
651
|
+
} else if (bytes.length === 32) return bytes;
|
|
652
|
+
throw new Error("Invalid Solana secret key length");
|
|
653
|
+
}
|
|
654
|
+
default:
|
|
650
655
|
throw new Error("Not implemented");
|
|
651
656
|
}
|
|
652
657
|
};
|
|
@@ -661,7 +666,7 @@ const isValidDerivationPath = async (derivationPath, curve) => {
|
|
|
661
666
|
}
|
|
662
667
|
};
|
|
663
668
|
|
|
664
|
-
const
|
|
669
|
+
const getAccountPlatformFromCurve = curve => {
|
|
665
670
|
switch (curve) {
|
|
666
671
|
case "sr25519":
|
|
667
672
|
case "ed25519":
|
|
@@ -676,7 +681,7 @@ const platformFromCurve = curve => {
|
|
|
676
681
|
return "solana";
|
|
677
682
|
}
|
|
678
683
|
};
|
|
679
|
-
const
|
|
684
|
+
const getAccountPlatformFromEncoding = encoding => {
|
|
680
685
|
switch (encoding) {
|
|
681
686
|
case "ss58":
|
|
682
687
|
return "polkadot";
|
|
@@ -686,28 +691,40 @@ const platformFromEncoding = encoding => {
|
|
|
686
691
|
case "bech32":
|
|
687
692
|
case "base58check":
|
|
688
693
|
return "bitcoin";
|
|
689
|
-
case "
|
|
694
|
+
case "base58solana":
|
|
690
695
|
return "solana";
|
|
691
696
|
}
|
|
692
697
|
};
|
|
693
|
-
const
|
|
698
|
+
const getAccountPlatformFromAddress = address => {
|
|
694
699
|
const encoding = detectAddressEncoding(address);
|
|
695
|
-
return
|
|
700
|
+
return getAccountPlatformFromEncoding(encoding);
|
|
696
701
|
};
|
|
697
702
|
|
|
698
|
-
Object.defineProperty(exports, "
|
|
703
|
+
Object.defineProperty(exports, "base58", {
|
|
704
|
+
enumerable: true,
|
|
705
|
+
get: function () { return base.base58; }
|
|
706
|
+
});
|
|
707
|
+
Object.defineProperty(exports, "base64", {
|
|
708
|
+
enumerable: true,
|
|
709
|
+
get: function () { return base.base64; }
|
|
710
|
+
});
|
|
711
|
+
Object.defineProperty(exports, "hex", {
|
|
712
|
+
enumerable: true,
|
|
713
|
+
get: function () { return base.hex; }
|
|
714
|
+
});
|
|
715
|
+
Object.defineProperty(exports, "utf8", {
|
|
699
716
|
enumerable: true,
|
|
700
|
-
get: function () { return base.
|
|
717
|
+
get: function () { return base.utf8; }
|
|
701
718
|
});
|
|
702
|
-
Object.defineProperty(exports, "
|
|
719
|
+
Object.defineProperty(exports, "ed25519", {
|
|
703
720
|
enumerable: true,
|
|
704
|
-
get: function () { return
|
|
721
|
+
get: function () { return ed25519.ed25519; }
|
|
705
722
|
});
|
|
706
723
|
exports.DEV_MNEMONIC_ETHEREUM = DEV_MNEMONIC_ETHEREUM;
|
|
707
724
|
exports.DEV_MNEMONIC_POLKADOT = DEV_MNEMONIC_POLKADOT;
|
|
708
725
|
exports.addressEncodingFromCurve = addressEncodingFromCurve;
|
|
726
|
+
exports.addressFromMnemonic = addressFromMnemonic;
|
|
709
727
|
exports.addressFromPublicKey = addressFromPublicKey;
|
|
710
|
-
exports.addressFromSuri = addressFromSuri;
|
|
711
728
|
exports.blake2b256 = blake2b256;
|
|
712
729
|
exports.blake2b512 = blake2b512;
|
|
713
730
|
exports.blake3 = blake3;
|
|
@@ -715,34 +732,35 @@ exports.checksumEthereumAddress = checksumEthereumAddress;
|
|
|
715
732
|
exports.decodeSs58Address = decodeSs58Address;
|
|
716
733
|
exports.deriveKeypair = deriveKeypair;
|
|
717
734
|
exports.detectAddressEncoding = detectAddressEncoding;
|
|
718
|
-
exports.encodeAddressBase58 = encodeAddressBase58;
|
|
719
735
|
exports.encodeAddressEthereum = encodeAddressEthereum;
|
|
736
|
+
exports.encodeAddressSolana = encodeAddressSolana;
|
|
720
737
|
exports.encodeAddressSs58 = encodeAddressSs58;
|
|
738
|
+
exports.encodeAnyAddress = encodeAnyAddress;
|
|
721
739
|
exports.entropyToMnemonic = entropyToMnemonic;
|
|
722
740
|
exports.entropyToSeed = entropyToSeed;
|
|
723
741
|
exports.fromBase58Check = fromBase58Check;
|
|
724
742
|
exports.fromBech32 = fromBech32;
|
|
725
743
|
exports.fromBech32m = fromBech32m;
|
|
726
744
|
exports.generateMnemonic = generateMnemonic;
|
|
745
|
+
exports.getAccountPlatformFromAddress = getAccountPlatformFromAddress;
|
|
746
|
+
exports.getAccountPlatformFromCurve = getAccountPlatformFromCurve;
|
|
747
|
+
exports.getAccountPlatformFromEncoding = getAccountPlatformFromEncoding;
|
|
727
748
|
exports.getDevSeed = getDevSeed;
|
|
728
749
|
exports.getPublicKeyFromSecret = getPublicKeyFromSecret;
|
|
729
750
|
exports.getSafeHash = getSafeHash;
|
|
730
751
|
exports.isAddressEqual = isAddressEqual;
|
|
731
|
-
exports.
|
|
752
|
+
exports.isAddressValid = isAddressValid;
|
|
732
753
|
exports.isBase58CheckAddress = isBase58CheckAddress;
|
|
733
754
|
exports.isBech32Address = isBech32Address;
|
|
734
755
|
exports.isBech32mAddress = isBech32mAddress;
|
|
735
756
|
exports.isBitcoinAddress = isBitcoinAddress;
|
|
736
757
|
exports.isEthereumAddress = isEthereumAddress;
|
|
758
|
+
exports.isSolanaAddress = isSolanaAddress;
|
|
737
759
|
exports.isSs58Address = isSs58Address;
|
|
738
760
|
exports.isValidDerivationPath = isValidDerivationPath;
|
|
739
761
|
exports.isValidMnemonic = isValidMnemonic;
|
|
740
762
|
exports.mnemonicToEntropy = mnemonicToEntropy;
|
|
741
763
|
exports.normalizeAddress = normalizeAddress;
|
|
742
764
|
exports.parseSecretKey = parseSecretKey;
|
|
743
|
-
exports.parseSuri = parseSuri;
|
|
744
765
|
exports.pbkdf2 = pbkdf2;
|
|
745
|
-
exports.platformFromAddress = platformFromAddress;
|
|
746
|
-
exports.platformFromCurve = platformFromCurve;
|
|
747
|
-
exports.platformFromEncoding = platformFromEncoding;
|
|
748
766
|
exports.removeHexPrefix = removeHexPrefix;
|
|
@@ -3,15 +3,15 @@
|
|
|
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 ed25519 = require('@noble/curves/ed25519');
|
|
7
|
+
var secp256k1 = require('@noble/curves/secp256k1');
|
|
6
8
|
var bech32 = require('bech32');
|
|
7
9
|
var bs58check = require('bs58check');
|
|
8
10
|
var sha3 = require('@noble/hashes/sha3');
|
|
9
11
|
var utils = require('@noble/hashes/utils');
|
|
10
12
|
var blake2b = require('@noble/hashes/blake2b');
|
|
11
13
|
var blake3$1 = require('@noble/hashes/blake3');
|
|
12
|
-
var secp256k1 = require('@noble/curves/secp256k1');
|
|
13
14
|
var scaleTs = require('scale-ts');
|
|
14
|
-
var ed25519 = require('@noble/curves/ed25519');
|
|
15
15
|
var bip32 = require('@scure/bip32');
|
|
16
16
|
var hmac = require('@noble/hashes/hmac');
|
|
17
17
|
var sha512 = require('@noble/hashes/sha512');
|
|
@@ -140,18 +140,18 @@ const addressEncodingFromCurve = curve => {
|
|
|
140
140
|
case "ethereum":
|
|
141
141
|
return "ethereum";
|
|
142
142
|
case "solana":
|
|
143
|
-
return "
|
|
143
|
+
return "base58solana";
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
const
|
|
147
|
+
const encodeAddressSolana = publicKey => {
|
|
148
|
+
if (publicKey.length !== 32) throw new Error("Public key must be 32 bytes long for Solana base58 encoding");
|
|
148
149
|
return base.base58.encode(publicKey);
|
|
149
150
|
};
|
|
150
|
-
|
|
151
|
-
function isBase58Address(address) {
|
|
151
|
+
function isSolanaAddress(address) {
|
|
152
152
|
try {
|
|
153
|
-
base.base58.decode(address);
|
|
154
|
-
return
|
|
153
|
+
const bytes = base.base58.decode(address);
|
|
154
|
+
return bytes.length === 32;
|
|
155
155
|
} catch (error) {
|
|
156
156
|
return false;
|
|
157
157
|
}
|
|
@@ -287,7 +287,7 @@ const blake2b512 = msg => blake2b.blake2b(msg, {
|
|
|
287
287
|
const getSafeHash = bytes => {
|
|
288
288
|
// cryptographically secure one way hash
|
|
289
289
|
// outputs 44 characters without special characters
|
|
290
|
-
return base.
|
|
290
|
+
return base.base58.encode(blake3$1.blake3(bytes));
|
|
291
291
|
};
|
|
292
292
|
|
|
293
293
|
// Inspired from MIT licensed @polkadot-labs/hdkd-helpers
|
|
@@ -336,10 +336,10 @@ const CACHE$1 = new Map();
|
|
|
336
336
|
const detectAddressEncodingInner = address => {
|
|
337
337
|
if (isEthereumAddress(address)) return "ethereum";
|
|
338
338
|
if (isSs58Address(address)) return "ss58";
|
|
339
|
+
if (isSolanaAddress(address)) return "base58solana";
|
|
339
340
|
if (isBech32mAddress(address)) return "bech32m";
|
|
340
341
|
if (isBech32Address(address)) return "bech32";
|
|
341
342
|
if (isBase58CheckAddress(address)) return "base58check";
|
|
342
|
-
if (isBase58Address(address)) return "base58";
|
|
343
343
|
throw new Error(`Unknown address encoding`);
|
|
344
344
|
};
|
|
345
345
|
const detectAddressEncoding = address => {
|
|
@@ -353,12 +353,12 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
|
|
|
353
353
|
return encodeAddressSs58(publicKey, options?.ss58Prefix);
|
|
354
354
|
case "ethereum":
|
|
355
355
|
return encodeAddressEthereum(publicKey);
|
|
356
|
+
case "base58solana":
|
|
357
|
+
return encodeAddressSolana(publicKey);
|
|
356
358
|
case "bech32m":
|
|
357
359
|
case "bech32":
|
|
358
360
|
case "base58check":
|
|
359
361
|
throw new Error("addressFromPublicKey is not implemented for Bitcoin");
|
|
360
|
-
case "base58":
|
|
361
|
-
return encodeAddressBase58(publicKey);
|
|
362
362
|
}
|
|
363
363
|
};
|
|
364
364
|
|
|
@@ -382,7 +382,7 @@ const normalizeAnyAddress = address => {
|
|
|
382
382
|
case "bech32m":
|
|
383
383
|
case "bech32":
|
|
384
384
|
case "base58check":
|
|
385
|
-
case "
|
|
385
|
+
case "base58solana":
|
|
386
386
|
return address;
|
|
387
387
|
case "ss58":
|
|
388
388
|
{
|
|
@@ -401,6 +401,29 @@ const isAddressEqual = (address1, address2) => {
|
|
|
401
401
|
}
|
|
402
402
|
};
|
|
403
403
|
|
|
404
|
+
const encodeAnyAddress = (address, options) => {
|
|
405
|
+
// this leverages cache
|
|
406
|
+
const encoding = detectAddressEncoding(address);
|
|
407
|
+
|
|
408
|
+
// this does NOT leverage cache
|
|
409
|
+
if (encoding === "ss58" && options?.ss58Format !== undefined) {
|
|
410
|
+
const [publicKey] = decodeSs58Address(address);
|
|
411
|
+
return encodeAddressSs58(publicKey, options?.ss58Format ?? 42);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// this leverages cache
|
|
415
|
+
return normalizeAddress(address);
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
const isAddressValid = address => {
|
|
419
|
+
try {
|
|
420
|
+
detectAddressEncoding(address);
|
|
421
|
+
return true;
|
|
422
|
+
} catch {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
|
|
404
427
|
// Inspired from MIT licensed @polkadot-labs/hdkd helpers
|
|
405
428
|
// https://github.com/polkadot-labs/hdkd/blob/3ef6e02827212d934b59a4e566d8aa61d3ba7b27/packages/hdkd-helpers/src/parseDerivations.ts#L1
|
|
406
429
|
|
|
@@ -535,7 +558,7 @@ const deriveSolana = (seed, derivationPath) => {
|
|
|
535
558
|
type: "solana",
|
|
536
559
|
secretKey,
|
|
537
560
|
publicKey,
|
|
538
|
-
address: addressFromPublicKey(publicKey, "
|
|
561
|
+
address: addressFromPublicKey(publicKey, "base58solana")
|
|
539
562
|
};
|
|
540
563
|
};
|
|
541
564
|
const getPublicKeySolana = secretKey => {
|
|
@@ -593,60 +616,42 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
|
|
|
593
616
|
return getPublicKeySolana(secretKey);
|
|
594
617
|
}
|
|
595
618
|
};
|
|
596
|
-
const
|
|
597
|
-
const {
|
|
598
|
-
mnemonic,
|
|
599
|
-
derivationPath,
|
|
600
|
-
password
|
|
601
|
-
} = parseSuri(suri);
|
|
619
|
+
const addressFromMnemonic = async (mnemonic, derivationPath, curve) => {
|
|
602
620
|
const entropy = mnemonicToEntropy(mnemonic);
|
|
603
|
-
const seed = await entropyToSeed(entropy,
|
|
621
|
+
const seed = await entropyToSeed(entropy, curve);
|
|
604
622
|
const {
|
|
605
|
-
|
|
606
|
-
} = deriveKeypair(seed, derivationPath,
|
|
607
|
-
|
|
608
|
-
const encoding = addressEncodingFromCurve(type);
|
|
609
|
-
return addressFromPublicKey(publicKey, encoding);
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* @dev we only expect suri to contain a mnemonic and derivation path.
|
|
614
|
-
* for other cases see https://polkadot.js.org/docs/keyring/start/suri/
|
|
615
|
-
*/
|
|
616
|
-
const parseSuri = suri => {
|
|
617
|
-
// extract password if any
|
|
618
|
-
const indexOfPassword = suri.indexOf("///");
|
|
619
|
-
const password = indexOfPassword === -1 ? undefined : suri.slice(indexOfPassword + 3);
|
|
620
|
-
if (password) suri = suri.slice(0, indexOfPassword);
|
|
621
|
-
|
|
622
|
-
// split mnemonic and derivation path
|
|
623
|
-
const indexOfSlash = suri.indexOf("/");
|
|
624
|
-
const mnemonic = indexOfSlash === -1 ? suri : suri.slice(0, indexOfSlash);
|
|
625
|
-
let derivationPath = indexOfSlash === -1 ? "" : suri.slice(indexOfSlash);
|
|
626
|
-
|
|
627
|
-
// if BIP44, leading slash must be removed
|
|
628
|
-
if (derivationPath.startsWith("/m/")) derivationPath = derivationPath.slice(1);
|
|
629
|
-
if (!isValidMnemonic(mnemonic)) throw new Error("Invalid mnemonic");
|
|
630
|
-
return {
|
|
631
|
-
mnemonic,
|
|
632
|
-
derivationPath,
|
|
633
|
-
password
|
|
634
|
-
};
|
|
623
|
+
address
|
|
624
|
+
} = deriveKeypair(seed, derivationPath, curve);
|
|
625
|
+
return address;
|
|
635
626
|
};
|
|
636
627
|
const removeHexPrefix = secretKey => {
|
|
637
628
|
if (secretKey.startsWith("0x")) return secretKey.slice(2);
|
|
638
629
|
return secretKey;
|
|
639
630
|
};
|
|
640
|
-
const parseSecretKey = (secretKey,
|
|
641
|
-
switch (
|
|
631
|
+
const parseSecretKey = (secretKey, platform) => {
|
|
632
|
+
switch (platform) {
|
|
642
633
|
case "ethereum":
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
case "bitcoin-ecdsa":
|
|
648
|
-
case "bitcoin-ed25519":
|
|
634
|
+
{
|
|
635
|
+
const privateKey = removeHexPrefix(secretKey);
|
|
636
|
+
return base.hex.decode(privateKey);
|
|
637
|
+
}
|
|
649
638
|
case "solana":
|
|
639
|
+
{
|
|
640
|
+
const bytes = secretKey.startsWith("[") ?
|
|
641
|
+
// JSON bytes array (ex: solflare)
|
|
642
|
+
Uint8Array.from(JSON.parse(secretKey)) :
|
|
643
|
+
// base58 encoded string (ex: phantom)
|
|
644
|
+
base.base58.decode(secretKey);
|
|
645
|
+
if (bytes.length === 64) {
|
|
646
|
+
const privateKey = bytes.slice(0, 32);
|
|
647
|
+
const publicKey = bytes.slice(32, 64);
|
|
648
|
+
const computedPublicKey = getPublicKeySolana(privateKey);
|
|
649
|
+
if (!publicKey.every((b, i) => b === computedPublicKey[i])) throw new Error("Invalid Solana secret key: public key does not match");
|
|
650
|
+
return privateKey;
|
|
651
|
+
} else if (bytes.length === 32) return bytes;
|
|
652
|
+
throw new Error("Invalid Solana secret key length");
|
|
653
|
+
}
|
|
654
|
+
default:
|
|
650
655
|
throw new Error("Not implemented");
|
|
651
656
|
}
|
|
652
657
|
};
|
|
@@ -661,7 +666,7 @@ const isValidDerivationPath = async (derivationPath, curve) => {
|
|
|
661
666
|
}
|
|
662
667
|
};
|
|
663
668
|
|
|
664
|
-
const
|
|
669
|
+
const getAccountPlatformFromCurve = curve => {
|
|
665
670
|
switch (curve) {
|
|
666
671
|
case "sr25519":
|
|
667
672
|
case "ed25519":
|
|
@@ -676,7 +681,7 @@ const platformFromCurve = curve => {
|
|
|
676
681
|
return "solana";
|
|
677
682
|
}
|
|
678
683
|
};
|
|
679
|
-
const
|
|
684
|
+
const getAccountPlatformFromEncoding = encoding => {
|
|
680
685
|
switch (encoding) {
|
|
681
686
|
case "ss58":
|
|
682
687
|
return "polkadot";
|
|
@@ -686,28 +691,40 @@ const platformFromEncoding = encoding => {
|
|
|
686
691
|
case "bech32":
|
|
687
692
|
case "base58check":
|
|
688
693
|
return "bitcoin";
|
|
689
|
-
case "
|
|
694
|
+
case "base58solana":
|
|
690
695
|
return "solana";
|
|
691
696
|
}
|
|
692
697
|
};
|
|
693
|
-
const
|
|
698
|
+
const getAccountPlatformFromAddress = address => {
|
|
694
699
|
const encoding = detectAddressEncoding(address);
|
|
695
|
-
return
|
|
700
|
+
return getAccountPlatformFromEncoding(encoding);
|
|
696
701
|
};
|
|
697
702
|
|
|
698
|
-
Object.defineProperty(exports, "
|
|
703
|
+
Object.defineProperty(exports, "base58", {
|
|
704
|
+
enumerable: true,
|
|
705
|
+
get: function () { return base.base58; }
|
|
706
|
+
});
|
|
707
|
+
Object.defineProperty(exports, "base64", {
|
|
708
|
+
enumerable: true,
|
|
709
|
+
get: function () { return base.base64; }
|
|
710
|
+
});
|
|
711
|
+
Object.defineProperty(exports, "hex", {
|
|
712
|
+
enumerable: true,
|
|
713
|
+
get: function () { return base.hex; }
|
|
714
|
+
});
|
|
715
|
+
Object.defineProperty(exports, "utf8", {
|
|
699
716
|
enumerable: true,
|
|
700
|
-
get: function () { return base.
|
|
717
|
+
get: function () { return base.utf8; }
|
|
701
718
|
});
|
|
702
|
-
Object.defineProperty(exports, "
|
|
719
|
+
Object.defineProperty(exports, "ed25519", {
|
|
703
720
|
enumerable: true,
|
|
704
|
-
get: function () { return
|
|
721
|
+
get: function () { return ed25519.ed25519; }
|
|
705
722
|
});
|
|
706
723
|
exports.DEV_MNEMONIC_ETHEREUM = DEV_MNEMONIC_ETHEREUM;
|
|
707
724
|
exports.DEV_MNEMONIC_POLKADOT = DEV_MNEMONIC_POLKADOT;
|
|
708
725
|
exports.addressEncodingFromCurve = addressEncodingFromCurve;
|
|
726
|
+
exports.addressFromMnemonic = addressFromMnemonic;
|
|
709
727
|
exports.addressFromPublicKey = addressFromPublicKey;
|
|
710
|
-
exports.addressFromSuri = addressFromSuri;
|
|
711
728
|
exports.blake2b256 = blake2b256;
|
|
712
729
|
exports.blake2b512 = blake2b512;
|
|
713
730
|
exports.blake3 = blake3;
|
|
@@ -715,34 +732,35 @@ exports.checksumEthereumAddress = checksumEthereumAddress;
|
|
|
715
732
|
exports.decodeSs58Address = decodeSs58Address;
|
|
716
733
|
exports.deriveKeypair = deriveKeypair;
|
|
717
734
|
exports.detectAddressEncoding = detectAddressEncoding;
|
|
718
|
-
exports.encodeAddressBase58 = encodeAddressBase58;
|
|
719
735
|
exports.encodeAddressEthereum = encodeAddressEthereum;
|
|
736
|
+
exports.encodeAddressSolana = encodeAddressSolana;
|
|
720
737
|
exports.encodeAddressSs58 = encodeAddressSs58;
|
|
738
|
+
exports.encodeAnyAddress = encodeAnyAddress;
|
|
721
739
|
exports.entropyToMnemonic = entropyToMnemonic;
|
|
722
740
|
exports.entropyToSeed = entropyToSeed;
|
|
723
741
|
exports.fromBase58Check = fromBase58Check;
|
|
724
742
|
exports.fromBech32 = fromBech32;
|
|
725
743
|
exports.fromBech32m = fromBech32m;
|
|
726
744
|
exports.generateMnemonic = generateMnemonic;
|
|
745
|
+
exports.getAccountPlatformFromAddress = getAccountPlatformFromAddress;
|
|
746
|
+
exports.getAccountPlatformFromCurve = getAccountPlatformFromCurve;
|
|
747
|
+
exports.getAccountPlatformFromEncoding = getAccountPlatformFromEncoding;
|
|
727
748
|
exports.getDevSeed = getDevSeed;
|
|
728
749
|
exports.getPublicKeyFromSecret = getPublicKeyFromSecret;
|
|
729
750
|
exports.getSafeHash = getSafeHash;
|
|
730
751
|
exports.isAddressEqual = isAddressEqual;
|
|
731
|
-
exports.
|
|
752
|
+
exports.isAddressValid = isAddressValid;
|
|
732
753
|
exports.isBase58CheckAddress = isBase58CheckAddress;
|
|
733
754
|
exports.isBech32Address = isBech32Address;
|
|
734
755
|
exports.isBech32mAddress = isBech32mAddress;
|
|
735
756
|
exports.isBitcoinAddress = isBitcoinAddress;
|
|
736
757
|
exports.isEthereumAddress = isEthereumAddress;
|
|
758
|
+
exports.isSolanaAddress = isSolanaAddress;
|
|
737
759
|
exports.isSs58Address = isSs58Address;
|
|
738
760
|
exports.isValidDerivationPath = isValidDerivationPath;
|
|
739
761
|
exports.isValidMnemonic = isValidMnemonic;
|
|
740
762
|
exports.mnemonicToEntropy = mnemonicToEntropy;
|
|
741
763
|
exports.normalizeAddress = normalizeAddress;
|
|
742
764
|
exports.parseSecretKey = parseSecretKey;
|
|
743
|
-
exports.parseSuri = parseSuri;
|
|
744
765
|
exports.pbkdf2 = pbkdf2;
|
|
745
|
-
exports.platformFromAddress = platformFromAddress;
|
|
746
|
-
exports.platformFromCurve = platformFromCurve;
|
|
747
|
-
exports.platformFromEncoding = platformFromEncoding;
|
|
748
766
|
exports.removeHexPrefix = removeHexPrefix;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { mnemonicToEntropy as mnemonicToEntropy$1, entropyToMnemonic as entropyToMnemonic$1, validateMnemonic, generateMnemonic as generateMnemonic$1 } from '@scure/bip39';
|
|
2
2
|
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
3
|
-
import { base58,
|
|
4
|
-
export {
|
|
3
|
+
import { base58, hex } from '@scure/base';
|
|
4
|
+
export { base58, base64, hex, utf8 } from '@scure/base';
|
|
5
|
+
import { ed25519 } from '@noble/curves/ed25519';
|
|
6
|
+
export { ed25519 } from '@noble/curves/ed25519';
|
|
7
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
5
8
|
import { bech32m, bech32 } from 'bech32';
|
|
6
9
|
import bs58check from 'bs58check';
|
|
7
10
|
import { keccak_256 } from '@noble/hashes/sha3';
|
|
8
11
|
import { bytesToHex, randomBytes } from '@noble/hashes/utils';
|
|
9
12
|
import { blake2b } from '@noble/hashes/blake2b';
|
|
10
13
|
import { blake3 as blake3$1 } from '@noble/hashes/blake3';
|
|
11
|
-
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
12
14
|
import { Tuple, str, Bytes, u32 } from 'scale-ts';
|
|
13
|
-
import { ed25519 } from '@noble/curves/ed25519';
|
|
14
15
|
import { HDKey } from '@scure/bip32';
|
|
15
16
|
import { hmac } from '@noble/hashes/hmac';
|
|
16
17
|
import { sha512 } from '@noble/hashes/sha512';
|
|
@@ -135,18 +136,18 @@ const addressEncodingFromCurve = curve => {
|
|
|
135
136
|
case "ethereum":
|
|
136
137
|
return "ethereum";
|
|
137
138
|
case "solana":
|
|
138
|
-
return "
|
|
139
|
+
return "base58solana";
|
|
139
140
|
}
|
|
140
141
|
};
|
|
141
142
|
|
|
142
|
-
const
|
|
143
|
+
const encodeAddressSolana = publicKey => {
|
|
144
|
+
if (publicKey.length !== 32) throw new Error("Public key must be 32 bytes long for Solana base58 encoding");
|
|
143
145
|
return base58.encode(publicKey);
|
|
144
146
|
};
|
|
145
|
-
|
|
146
|
-
function isBase58Address(address) {
|
|
147
|
+
function isSolanaAddress(address) {
|
|
147
148
|
try {
|
|
148
|
-
base58.decode(address);
|
|
149
|
-
return
|
|
149
|
+
const bytes = base58.decode(address);
|
|
150
|
+
return bytes.length === 32;
|
|
150
151
|
} catch (error) {
|
|
151
152
|
return false;
|
|
152
153
|
}
|
|
@@ -282,7 +283,7 @@ const blake2b512 = msg => blake2b(msg, {
|
|
|
282
283
|
const getSafeHash = bytes => {
|
|
283
284
|
// cryptographically secure one way hash
|
|
284
285
|
// outputs 44 characters without special characters
|
|
285
|
-
return
|
|
286
|
+
return base58.encode(blake3$1(bytes));
|
|
286
287
|
};
|
|
287
288
|
|
|
288
289
|
// Inspired from MIT licensed @polkadot-labs/hdkd-helpers
|
|
@@ -331,10 +332,10 @@ const CACHE$1 = new Map();
|
|
|
331
332
|
const detectAddressEncodingInner = address => {
|
|
332
333
|
if (isEthereumAddress(address)) return "ethereum";
|
|
333
334
|
if (isSs58Address(address)) return "ss58";
|
|
335
|
+
if (isSolanaAddress(address)) return "base58solana";
|
|
334
336
|
if (isBech32mAddress(address)) return "bech32m";
|
|
335
337
|
if (isBech32Address(address)) return "bech32";
|
|
336
338
|
if (isBase58CheckAddress(address)) return "base58check";
|
|
337
|
-
if (isBase58Address(address)) return "base58";
|
|
338
339
|
throw new Error(`Unknown address encoding`);
|
|
339
340
|
};
|
|
340
341
|
const detectAddressEncoding = address => {
|
|
@@ -348,12 +349,12 @@ const addressFromPublicKey = (publicKey, encoding, options) => {
|
|
|
348
349
|
return encodeAddressSs58(publicKey, options?.ss58Prefix);
|
|
349
350
|
case "ethereum":
|
|
350
351
|
return encodeAddressEthereum(publicKey);
|
|
352
|
+
case "base58solana":
|
|
353
|
+
return encodeAddressSolana(publicKey);
|
|
351
354
|
case "bech32m":
|
|
352
355
|
case "bech32":
|
|
353
356
|
case "base58check":
|
|
354
357
|
throw new Error("addressFromPublicKey is not implemented for Bitcoin");
|
|
355
|
-
case "base58":
|
|
356
|
-
return encodeAddressBase58(publicKey);
|
|
357
358
|
}
|
|
358
359
|
};
|
|
359
360
|
|
|
@@ -377,7 +378,7 @@ const normalizeAnyAddress = address => {
|
|
|
377
378
|
case "bech32m":
|
|
378
379
|
case "bech32":
|
|
379
380
|
case "base58check":
|
|
380
|
-
case "
|
|
381
|
+
case "base58solana":
|
|
381
382
|
return address;
|
|
382
383
|
case "ss58":
|
|
383
384
|
{
|
|
@@ -396,6 +397,29 @@ const isAddressEqual = (address1, address2) => {
|
|
|
396
397
|
}
|
|
397
398
|
};
|
|
398
399
|
|
|
400
|
+
const encodeAnyAddress = (address, options) => {
|
|
401
|
+
// this leverages cache
|
|
402
|
+
const encoding = detectAddressEncoding(address);
|
|
403
|
+
|
|
404
|
+
// this does NOT leverage cache
|
|
405
|
+
if (encoding === "ss58" && options?.ss58Format !== undefined) {
|
|
406
|
+
const [publicKey] = decodeSs58Address(address);
|
|
407
|
+
return encodeAddressSs58(publicKey, options?.ss58Format ?? 42);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// this leverages cache
|
|
411
|
+
return normalizeAddress(address);
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const isAddressValid = address => {
|
|
415
|
+
try {
|
|
416
|
+
detectAddressEncoding(address);
|
|
417
|
+
return true;
|
|
418
|
+
} catch {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
399
423
|
// Inspired from MIT licensed @polkadot-labs/hdkd helpers
|
|
400
424
|
// https://github.com/polkadot-labs/hdkd/blob/3ef6e02827212d934b59a4e566d8aa61d3ba7b27/packages/hdkd-helpers/src/parseDerivations.ts#L1
|
|
401
425
|
|
|
@@ -530,7 +554,7 @@ const deriveSolana = (seed, derivationPath) => {
|
|
|
530
554
|
type: "solana",
|
|
531
555
|
secretKey,
|
|
532
556
|
publicKey,
|
|
533
|
-
address: addressFromPublicKey(publicKey, "
|
|
557
|
+
address: addressFromPublicKey(publicKey, "base58solana")
|
|
534
558
|
};
|
|
535
559
|
};
|
|
536
560
|
const getPublicKeySolana = secretKey => {
|
|
@@ -588,60 +612,42 @@ const getPublicKeyFromSecret = (secretKey, curve) => {
|
|
|
588
612
|
return getPublicKeySolana(secretKey);
|
|
589
613
|
}
|
|
590
614
|
};
|
|
591
|
-
const
|
|
592
|
-
const {
|
|
593
|
-
mnemonic,
|
|
594
|
-
derivationPath,
|
|
595
|
-
password
|
|
596
|
-
} = parseSuri(suri);
|
|
615
|
+
const addressFromMnemonic = async (mnemonic, derivationPath, curve) => {
|
|
597
616
|
const entropy = mnemonicToEntropy(mnemonic);
|
|
598
|
-
const seed = await entropyToSeed(entropy,
|
|
617
|
+
const seed = await entropyToSeed(entropy, curve);
|
|
599
618
|
const {
|
|
600
|
-
|
|
601
|
-
} = deriveKeypair(seed, derivationPath,
|
|
602
|
-
|
|
603
|
-
const encoding = addressEncodingFromCurve(type);
|
|
604
|
-
return addressFromPublicKey(publicKey, encoding);
|
|
605
|
-
};
|
|
606
|
-
|
|
607
|
-
/**
|
|
608
|
-
* @dev we only expect suri to contain a mnemonic and derivation path.
|
|
609
|
-
* for other cases see https://polkadot.js.org/docs/keyring/start/suri/
|
|
610
|
-
*/
|
|
611
|
-
const parseSuri = suri => {
|
|
612
|
-
// extract password if any
|
|
613
|
-
const indexOfPassword = suri.indexOf("///");
|
|
614
|
-
const password = indexOfPassword === -1 ? undefined : suri.slice(indexOfPassword + 3);
|
|
615
|
-
if (password) suri = suri.slice(0, indexOfPassword);
|
|
616
|
-
|
|
617
|
-
// split mnemonic and derivation path
|
|
618
|
-
const indexOfSlash = suri.indexOf("/");
|
|
619
|
-
const mnemonic = indexOfSlash === -1 ? suri : suri.slice(0, indexOfSlash);
|
|
620
|
-
let derivationPath = indexOfSlash === -1 ? "" : suri.slice(indexOfSlash);
|
|
621
|
-
|
|
622
|
-
// if BIP44, leading slash must be removed
|
|
623
|
-
if (derivationPath.startsWith("/m/")) derivationPath = derivationPath.slice(1);
|
|
624
|
-
if (!isValidMnemonic(mnemonic)) throw new Error("Invalid mnemonic");
|
|
625
|
-
return {
|
|
626
|
-
mnemonic,
|
|
627
|
-
derivationPath,
|
|
628
|
-
password
|
|
629
|
-
};
|
|
619
|
+
address
|
|
620
|
+
} = deriveKeypair(seed, derivationPath, curve);
|
|
621
|
+
return address;
|
|
630
622
|
};
|
|
631
623
|
const removeHexPrefix = secretKey => {
|
|
632
624
|
if (secretKey.startsWith("0x")) return secretKey.slice(2);
|
|
633
625
|
return secretKey;
|
|
634
626
|
};
|
|
635
|
-
const parseSecretKey = (secretKey,
|
|
636
|
-
switch (
|
|
627
|
+
const parseSecretKey = (secretKey, platform) => {
|
|
628
|
+
switch (platform) {
|
|
637
629
|
case "ethereum":
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
case "bitcoin-ecdsa":
|
|
643
|
-
case "bitcoin-ed25519":
|
|
630
|
+
{
|
|
631
|
+
const privateKey = removeHexPrefix(secretKey);
|
|
632
|
+
return hex.decode(privateKey);
|
|
633
|
+
}
|
|
644
634
|
case "solana":
|
|
635
|
+
{
|
|
636
|
+
const bytes = secretKey.startsWith("[") ?
|
|
637
|
+
// JSON bytes array (ex: solflare)
|
|
638
|
+
Uint8Array.from(JSON.parse(secretKey)) :
|
|
639
|
+
// base58 encoded string (ex: phantom)
|
|
640
|
+
base58.decode(secretKey);
|
|
641
|
+
if (bytes.length === 64) {
|
|
642
|
+
const privateKey = bytes.slice(0, 32);
|
|
643
|
+
const publicKey = bytes.slice(32, 64);
|
|
644
|
+
const computedPublicKey = getPublicKeySolana(privateKey);
|
|
645
|
+
if (!publicKey.every((b, i) => b === computedPublicKey[i])) throw new Error("Invalid Solana secret key: public key does not match");
|
|
646
|
+
return privateKey;
|
|
647
|
+
} else if (bytes.length === 32) return bytes;
|
|
648
|
+
throw new Error("Invalid Solana secret key length");
|
|
649
|
+
}
|
|
650
|
+
default:
|
|
645
651
|
throw new Error("Not implemented");
|
|
646
652
|
}
|
|
647
653
|
};
|
|
@@ -656,7 +662,7 @@ const isValidDerivationPath = async (derivationPath, curve) => {
|
|
|
656
662
|
}
|
|
657
663
|
};
|
|
658
664
|
|
|
659
|
-
const
|
|
665
|
+
const getAccountPlatformFromCurve = curve => {
|
|
660
666
|
switch (curve) {
|
|
661
667
|
case "sr25519":
|
|
662
668
|
case "ed25519":
|
|
@@ -671,7 +677,7 @@ const platformFromCurve = curve => {
|
|
|
671
677
|
return "solana";
|
|
672
678
|
}
|
|
673
679
|
};
|
|
674
|
-
const
|
|
680
|
+
const getAccountPlatformFromEncoding = encoding => {
|
|
675
681
|
switch (encoding) {
|
|
676
682
|
case "ss58":
|
|
677
683
|
return "polkadot";
|
|
@@ -681,13 +687,13 @@ const platformFromEncoding = encoding => {
|
|
|
681
687
|
case "bech32":
|
|
682
688
|
case "base58check":
|
|
683
689
|
return "bitcoin";
|
|
684
|
-
case "
|
|
690
|
+
case "base58solana":
|
|
685
691
|
return "solana";
|
|
686
692
|
}
|
|
687
693
|
};
|
|
688
|
-
const
|
|
694
|
+
const getAccountPlatformFromAddress = address => {
|
|
689
695
|
const encoding = detectAddressEncoding(address);
|
|
690
|
-
return
|
|
696
|
+
return getAccountPlatformFromEncoding(encoding);
|
|
691
697
|
};
|
|
692
698
|
|
|
693
|
-
export { DEV_MNEMONIC_ETHEREUM, DEV_MNEMONIC_POLKADOT, addressEncodingFromCurve,
|
|
699
|
+
export { DEV_MNEMONIC_ETHEREUM, DEV_MNEMONIC_POLKADOT, addressEncodingFromCurve, addressFromMnemonic, addressFromPublicKey, blake2b256, blake2b512, blake3, checksumEthereumAddress, decodeSs58Address, deriveKeypair, detectAddressEncoding, encodeAddressEthereum, encodeAddressSolana, encodeAddressSs58, encodeAnyAddress, entropyToMnemonic, entropyToSeed, fromBase58Check, fromBech32, fromBech32m, generateMnemonic, getAccountPlatformFromAddress, getAccountPlatformFromCurve, getAccountPlatformFromEncoding, getDevSeed, getPublicKeyFromSecret, getSafeHash, isAddressEqual, isAddressValid, isBase58CheckAddress, isBech32Address, isBech32mAddress, isBitcoinAddress, isEthereumAddress, isSolanaAddress, isSs58Address, isValidDerivationPath, isValidMnemonic, mnemonicToEntropy, normalizeAddress, parseSecretKey, pbkdf2, removeHexPrefix };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@talismn/crypto",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"author": "Talisman",
|
|
5
5
|
"homepage": "https://talisman.xyz",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -15,8 +15,7 @@
|
|
|
15
15
|
"main": "dist/talismn-crypto.cjs.js",
|
|
16
16
|
"module": "dist/talismn-crypto.esm.js",
|
|
17
17
|
"files": [
|
|
18
|
-
"/dist"
|
|
19
|
-
"/plugins"
|
|
18
|
+
"/dist"
|
|
20
19
|
],
|
|
21
20
|
"engines": {
|
|
22
21
|
"node": ">=18"
|
|
@@ -38,8 +37,8 @@
|
|
|
38
37
|
"jest": "^29.7.0",
|
|
39
38
|
"ts-jest": "^29.2.5",
|
|
40
39
|
"typescript": "^5.6.3",
|
|
41
|
-
"@talismn/
|
|
42
|
-
"@talismn/
|
|
40
|
+
"@talismn/eslint-config": "0.0.3",
|
|
41
|
+
"@talismn/tsconfig": "0.0.2"
|
|
43
42
|
},
|
|
44
43
|
"preconstruct": {
|
|
45
44
|
"entrypoints": [
|
|
@@ -53,8 +52,8 @@
|
|
|
53
52
|
]
|
|
54
53
|
},
|
|
55
54
|
"scripts": {
|
|
56
|
-
"test": "jest",
|
|
55
|
+
"test": "jest --detectOpenHandles",
|
|
57
56
|
"lint": "eslint src --max-warnings 0",
|
|
58
|
-
"clean": "rm -rf dist
|
|
57
|
+
"clean": "rm -rf dist .turbo node_modules"
|
|
59
58
|
}
|
|
60
59
|
}
|