@hwlt/era-connect 0.2.0 → 0.3.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,176 @@
1
+ const require_shared = require("./shared-nISrEktU.cjs");
2
+ let _noble_curves_secp256k1 = require("@noble/curves/secp256k1");
3
+ let _noble_hashes_ripemd160 = require("@noble/hashes/ripemd160");
4
+ let _noble_hashes_sha2 = require("@noble/hashes/sha2");
5
+ let _noble_hashes_sha3 = require("@noble/hashes/sha3");
6
+ let _scure_base = require("@scure/base");
7
+ let _scure_bip32 = require("@scure/bip32");
8
+ let _noble_curves_ed25519 = require("@noble/curves/ed25519");
9
+ let _noble_hashes_hmac = require("@noble/hashes/hmac");
10
+ //#region src/accounts/derive.ts
11
+ const base58check = (0, _scure_base.createBase58check)(_noble_hashes_sha2.sha256);
12
+ /** Non-hardened BIP-32 child public key from an account-level (publicKey, chainCode). */
13
+ function derivePublicKey(publicKey, chainCode, change, index) {
14
+ const child = new _scure_bip32.HDKey({
15
+ publicKey,
16
+ chainCode
17
+ }).deriveChild(change).deriveChild(index);
18
+ if (!child.publicKey) throw new require_shared.EraSdkError("invalid-props", "child derivation produced no public key");
19
+ return child.publicKey;
20
+ }
21
+ function uncompressed(publicKey33) {
22
+ return _noble_curves_secp256k1.secp256k1.ProjectivePoint.fromHex(publicKey33).toRawBytes(false);
23
+ }
24
+ /** EIP-55 checksummed address from a compressed secp256k1 public key. */
25
+ function evmAddressFromPublicKey(publicKey33) {
26
+ const hash = (0, _noble_hashes_sha3.keccak_256)(uncompressed(publicKey33).slice(1));
27
+ const addr = require_shared.bytesToHex(hash.slice(12));
28
+ const check = (0, _noble_hashes_sha3.keccak_256)(new Uint8Array([...addr].map((c) => c.charCodeAt(0))));
29
+ let out = "";
30
+ for (let i = 0; i < addr.length; i++) {
31
+ const nibble = i % 2 === 0 ? check[i >> 1] >> 4 : check[i >> 1] & 15;
32
+ out += nibble >= 8 ? addr[i].toUpperCase() : addr[i];
33
+ }
34
+ return `0x${out}`;
35
+ }
36
+ function hash160(data) {
37
+ return (0, _noble_hashes_ripemd160.ripemd160)((0, _noble_hashes_sha2.sha256)(data));
38
+ }
39
+ /** P2WPKH (witness v0) bech32 address. */
40
+ function btcP2wpkhAddressFromPublicKey(publicKey33, hrp = "bc") {
41
+ return _scure_base.bech32.encode(hrp, [0, ..._scure_base.bech32.toWords(hash160(publicKey33))]);
42
+ }
43
+ /** Legacy P2PKH base58check address (`1...`) — the kind the device signs messages for. */
44
+ function btcP2pkhAddressFromPublicKey(publicKey33, testnet = false) {
45
+ return base58check.encode(require_shared.concatBytes(new Uint8Array([testnet ? 111 : 0]), hash160(publicKey33)));
46
+ }
47
+ /** Nested segwit (P2SH-P2WPKH) base58check address (`3...`). */
48
+ function btcNestedSegwitAddressFromPublicKey(publicKey33, testnet = false) {
49
+ const redeemScript = require_shared.concatBytes(new Uint8Array([0, 20]), hash160(publicKey33));
50
+ return base58check.encode(require_shared.concatBytes(new Uint8Array([testnet ? 196 : 5]), hash160(redeemScript)));
51
+ }
52
+ /** Tron base58check address (0x41-prefixed keccak hash). */
53
+ function tronAddressFromPublicKey(publicKey33) {
54
+ const hash = (0, _noble_hashes_sha3.keccak_256)(uncompressed(publicKey33).slice(1));
55
+ return base58check.encode(require_shared.concatBytes(new Uint8Array([65]), hash.slice(12)));
56
+ }
57
+ /** A Solana address IS the Ed25519 public key, base58. */
58
+ function solanaAddressFromPublicKey(publicKey32) {
59
+ return _scure_base.base58.encode(publicKey32);
60
+ }
61
+ const XPUB_VERSION = 76067358;
62
+ const ZPUB_VERSION = 78792518;
63
+ /** BIP-32 extended public key serialization. */
64
+ function serializeExtendedPublicKey(args) {
65
+ const { version = XPUB_VERSION, depth, parentFingerprint, childNumber, chainCode, publicKey } = args;
66
+ if (chainCode.length !== 32 || publicKey.length !== 33) throw new require_shared.EraSdkError("invalid-props", "extended key needs a 32-byte chain code and 33-byte key");
67
+ return base58check.encode(require_shared.concatBytes(require_shared.u32be(version), new Uint8Array([depth & 255]), require_shared.u32be(parentFingerprint), require_shared.u32be(childNumber), chainCode, publicKey));
68
+ }
69
+ function u32le(value) {
70
+ return new Uint8Array([
71
+ value & 255,
72
+ value >> 8 & 255,
73
+ value >> 16 & 255,
74
+ value >> 24 & 255
75
+ ]);
76
+ }
77
+ function leBytesToBigint(bytes) {
78
+ let out = 0n;
79
+ for (let i = bytes.length - 1; i >= 0; i--) out = out << 8n | BigInt(bytes[i]);
80
+ return out;
81
+ }
82
+ /**
83
+ * Public (soft) child of a BIP32-Ed25519 extended public key — the scheme
84
+ * Cardano wallets share account xpubs under (CIP-3/V2):
85
+ *
86
+ * Z = HMAC-SHA512(chainCode, 0x02 || A || le32(index))
87
+ * childA = A + [8 * ZL[0..28]] * B
88
+ * childCC = HMAC-SHA512(chainCode, 0x03 || A || le32(index))[32..]
89
+ *
90
+ * Only non-hardened indices are derivable publicly, which is exactly what the
91
+ * role/index tail of a CIP-1852 path uses.
92
+ */
93
+ function cardanoSoftDeriveChild(publicKey, chainCode, index) {
94
+ if (publicKey.length !== 32 || chainCode.length !== 32) throw new require_shared.EraSdkError("invalid-props", "Cardano derivation needs a 32-byte key and chain code");
95
+ if (!Number.isSafeInteger(index) || index < 0 || index >= 2147483648) throw new require_shared.EraSdkError("invalid-props", "Cardano public derivation is soft-index only");
96
+ const z = (0, _noble_hashes_hmac.hmac)(_noble_hashes_sha2.sha512, chainCode, require_shared.concatBytes(new Uint8Array([2]), publicKey, u32le(index)));
97
+ const cc = (0, _noble_hashes_hmac.hmac)(_noble_hashes_sha2.sha512, chainCode, require_shared.concatBytes(new Uint8Array([3]), publicKey, u32le(index))).slice(32);
98
+ const scalar = 8n * leBytesToBigint(z.slice(0, 28));
99
+ const parent = _noble_curves_ed25519.ed25519.ExtendedPoint.fromHex(require_shared.bytesToHex(publicKey));
100
+ return {
101
+ publicKey: (scalar === 0n ? parent : parent.add(_noble_curves_ed25519.ed25519.ExtendedPoint.BASE.multiply(scalar))).toRawBytes(),
102
+ chainCode: cc
103
+ };
104
+ }
105
+ /** Soft-derive along several indices (e.g. role, then address index). */
106
+ function cardanoSoftDerivePath(publicKey, chainCode, indices) {
107
+ let node = {
108
+ publicKey,
109
+ chainCode
110
+ };
111
+ for (const index of indices) node = cardanoSoftDeriveChild(node.publicKey, node.chainCode, index);
112
+ return node.publicKey;
113
+ }
114
+ //#endregion
115
+ Object.defineProperty(exports, "ZPUB_VERSION", {
116
+ enumerable: true,
117
+ get: function() {
118
+ return ZPUB_VERSION;
119
+ }
120
+ });
121
+ Object.defineProperty(exports, "btcNestedSegwitAddressFromPublicKey", {
122
+ enumerable: true,
123
+ get: function() {
124
+ return btcNestedSegwitAddressFromPublicKey;
125
+ }
126
+ });
127
+ Object.defineProperty(exports, "btcP2pkhAddressFromPublicKey", {
128
+ enumerable: true,
129
+ get: function() {
130
+ return btcP2pkhAddressFromPublicKey;
131
+ }
132
+ });
133
+ Object.defineProperty(exports, "btcP2wpkhAddressFromPublicKey", {
134
+ enumerable: true,
135
+ get: function() {
136
+ return btcP2wpkhAddressFromPublicKey;
137
+ }
138
+ });
139
+ Object.defineProperty(exports, "cardanoSoftDerivePath", {
140
+ enumerable: true,
141
+ get: function() {
142
+ return cardanoSoftDerivePath;
143
+ }
144
+ });
145
+ Object.defineProperty(exports, "derivePublicKey", {
146
+ enumerable: true,
147
+ get: function() {
148
+ return derivePublicKey;
149
+ }
150
+ });
151
+ Object.defineProperty(exports, "evmAddressFromPublicKey", {
152
+ enumerable: true,
153
+ get: function() {
154
+ return evmAddressFromPublicKey;
155
+ }
156
+ });
157
+ Object.defineProperty(exports, "serializeExtendedPublicKey", {
158
+ enumerable: true,
159
+ get: function() {
160
+ return serializeExtendedPublicKey;
161
+ }
162
+ });
163
+ Object.defineProperty(exports, "solanaAddressFromPublicKey", {
164
+ enumerable: true,
165
+ get: function() {
166
+ return solanaAddressFromPublicKey;
167
+ }
168
+ });
169
+ Object.defineProperty(exports, "tronAddressFromPublicKey", {
170
+ enumerable: true,
171
+ get: function() {
172
+ return tronAddressFromPublicKey;
173
+ }
174
+ });
175
+
176
+ //# sourceMappingURL=derive-CuILJRPT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-CuILJRPT.cjs","names":["createBase58check","sha256","HDKey","EraSdkError","secp256k1","keccak_256","bytesToHex","ripemd160","bech32","concatBytes","base58","u32be","hmac","sha512","ed25519"],"sources":["../src/accounts/derive.ts"],"sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1';\nimport { ripemd160 } from '@noble/hashes/ripemd160';\nimport { sha256 } from '@noble/hashes/sha2';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { base58, bech32, createBase58check } from '@scure/base';\nimport { HDKey } from '@scure/bip32';\nimport { bytesToHex, concatBytes, u32be } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\n\nconst base58check = createBase58check(sha256);\n\n/** Non-hardened BIP-32 child public key from an account-level (publicKey, chainCode). */\nexport function derivePublicKey(\n publicKey: Uint8Array,\n chainCode: Uint8Array,\n change: number,\n index: number,\n): Uint8Array {\n const node = new HDKey({ publicKey, chainCode });\n const child = node.deriveChild(change).deriveChild(index);\n if (!child.publicKey) {\n throw new EraSdkError('invalid-props', 'child derivation produced no public key');\n }\n return child.publicKey;\n}\n\nfunction uncompressed(publicKey33: Uint8Array): Uint8Array {\n return secp256k1.ProjectivePoint.fromHex(publicKey33).toRawBytes(false);\n}\n\n/** EIP-55 checksummed address from a compressed secp256k1 public key. */\nexport function evmAddressFromPublicKey(publicKey33: Uint8Array): `0x${string}` {\n const hash = keccak_256(uncompressed(publicKey33).slice(1));\n const addr = bytesToHex(hash.slice(12));\n const check = keccak_256(new Uint8Array([...addr].map((c) => c.charCodeAt(0))));\n let out = '';\n for (let i = 0; i < addr.length; i++) {\n const nibble = i % 2 === 0 ? check[i >> 1]! >> 4 : check[i >> 1]! & 0x0f;\n out += nibble >= 8 ? addr[i]!.toUpperCase() : addr[i]!;\n }\n return `0x${out}`;\n}\n\nfunction hash160(data: Uint8Array): Uint8Array {\n return ripemd160(sha256(data));\n}\n\n/** P2WPKH (witness v0) bech32 address. */\nexport function btcP2wpkhAddressFromPublicKey(\n publicKey33: Uint8Array,\n hrp: 'bc' | 'tb' = 'bc',\n): string {\n return bech32.encode(hrp, [0, ...bech32.toWords(hash160(publicKey33))]);\n}\n\n/** Legacy P2PKH base58check address (`1...`) — the kind the device signs messages for. */\nexport function btcP2pkhAddressFromPublicKey(publicKey33: Uint8Array, testnet = false): string {\n return base58check.encode(\n concatBytes(new Uint8Array([testnet ? 0x6f : 0x00]), hash160(publicKey33)),\n );\n}\n\n/** Nested segwit (P2SH-P2WPKH) base58check address (`3...`). */\nexport function btcNestedSegwitAddressFromPublicKey(\n publicKey33: Uint8Array,\n testnet = false,\n): string {\n const redeemScript = concatBytes(new Uint8Array([0x00, 0x14]), hash160(publicKey33));\n return base58check.encode(\n concatBytes(new Uint8Array([testnet ? 0xc4 : 0x05]), hash160(redeemScript)),\n );\n}\n\n/** Tron base58check address (0x41-prefixed keccak hash). */\nexport function tronAddressFromPublicKey(publicKey33: Uint8Array): string {\n const hash = keccak_256(uncompressed(publicKey33).slice(1));\n return base58check.encode(concatBytes(new Uint8Array([0x41]), hash.slice(12)));\n}\n\n/** A Solana address IS the Ed25519 public key, base58. */\nexport function solanaAddressFromPublicKey(publicKey32: Uint8Array): string {\n return base58.encode(publicKey32);\n}\n\nconst XPUB_VERSION = 0x0488b21e;\nconst ZPUB_VERSION = 0x04b24746; // SLIP-132, BIP-84 P2WPKH\n\n/** BIP-32 extended public key serialization. */\nexport function serializeExtendedPublicKey(args: {\n version?: number;\n depth: number;\n parentFingerprint: number;\n childNumber: number;\n chainCode: Uint8Array;\n publicKey: Uint8Array;\n}): string {\n const {\n version = XPUB_VERSION,\n depth,\n parentFingerprint,\n childNumber,\n chainCode,\n publicKey,\n } = args;\n if (chainCode.length !== 32 || publicKey.length !== 33) {\n throw new EraSdkError(\n 'invalid-props',\n 'extended key needs a 32-byte chain code and 33-byte key',\n );\n }\n return base58check.encode(\n concatBytes(\n u32be(version),\n new Uint8Array([depth & 0xff]),\n u32be(parentFingerprint),\n u32be(childNumber),\n chainCode,\n publicKey,\n ),\n );\n}\n\nexport { XPUB_VERSION, ZPUB_VERSION };\n\n// ---------------------------------------------------------------------------\n// Cardano (BIP32-Ed25519 / CIP-3 \"V2\") soft public derivation\n// ---------------------------------------------------------------------------\n\nimport { ed25519 } from '@noble/curves/ed25519';\nimport { hmac } from '@noble/hashes/hmac';\nimport { sha512 } from '@noble/hashes/sha2';\n\nfunction u32le(value: number): Uint8Array {\n return new Uint8Array([\n value & 0xff,\n (value >> 8) & 0xff,\n (value >> 16) & 0xff,\n (value >> 24) & 0xff,\n ]);\n}\n\nfunction leBytesToBigint(bytes: Uint8Array): bigint {\n let out = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) out = (out << 8n) | BigInt(bytes[i]!);\n return out;\n}\n\n/**\n * Public (soft) child of a BIP32-Ed25519 extended public key — the scheme\n * Cardano wallets share account xpubs under (CIP-3/V2):\n *\n * Z = HMAC-SHA512(chainCode, 0x02 || A || le32(index))\n * childA = A + [8 * ZL[0..28]] * B\n * childCC = HMAC-SHA512(chainCode, 0x03 || A || le32(index))[32..]\n *\n * Only non-hardened indices are derivable publicly, which is exactly what the\n * role/index tail of a CIP-1852 path uses.\n */\nexport function cardanoSoftDeriveChild(\n publicKey: Uint8Array,\n chainCode: Uint8Array,\n index: number,\n): { publicKey: Uint8Array; chainCode: Uint8Array } {\n if (publicKey.length !== 32 || chainCode.length !== 32) {\n throw new EraSdkError('invalid-props', 'Cardano derivation needs a 32-byte key and chain code');\n }\n if (!Number.isSafeInteger(index) || index < 0 || index >= 0x80000000) {\n throw new EraSdkError('invalid-props', 'Cardano public derivation is soft-index only');\n }\n const z = hmac(sha512, chainCode, concatBytes(new Uint8Array([0x02]), publicKey, u32le(index)));\n const cc = hmac(\n sha512,\n chainCode,\n concatBytes(new Uint8Array([0x03]), publicKey, u32le(index)),\n ).slice(32);\n const scalar = 8n * leBytesToBigint(z.slice(0, 28));\n const parent = ed25519.ExtendedPoint.fromHex(bytesToHex(publicKey));\n const child = scalar === 0n ? parent : parent.add(ed25519.ExtendedPoint.BASE.multiply(scalar));\n return { publicKey: child.toRawBytes(), chainCode: cc };\n}\n\n/** Soft-derive along several indices (e.g. role, then address index). */\nexport function cardanoSoftDerivePath(\n publicKey: Uint8Array,\n chainCode: Uint8Array,\n indices: readonly number[],\n): Uint8Array {\n let node = { publicKey, chainCode };\n for (const index of indices) {\n node = cardanoSoftDeriveChild(node.publicKey, node.chainCode, index);\n }\n return node.publicKey;\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,16 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_shared = require("./shared-nISrEktU.cjs");
3
+ const require_derive = require("./derive-CuILJRPT.cjs");
3
4
  const require_btc = require("./btc-Fr6Jz4Fi.cjs");
5
+ const require_cardano = require("./cardano-DP6U_K1J.cjs");
4
6
  const require_evm = require("./evm-BHj_2OTG.cjs");
5
7
  const require_solana = require("./solana-DdEn24X4.cjs");
6
8
  const require_ton = require("./ton-DUJGXdGa.cjs");
7
9
  const require_tron = require("./tron-CQIEqjCA.cjs");
8
- let _noble_curves_secp256k1 = require("@noble/curves/secp256k1");
9
- let _noble_hashes_ripemd160 = require("@noble/hashes/ripemd160");
10
- let _noble_hashes_sha2 = require("@noble/hashes/sha2");
11
- let _noble_hashes_sha3 = require("@noble/hashes/sha3");
12
- let _scure_base = require("@scure/base");
13
- let _scure_bip32 = require("@scure/bip32");
14
10
  //#region src/registry/multi-accounts.ts
15
11
  /** UR types a device links a watch-only wallet with. */
16
12
  const WALLET_UR_TYPES = /* @__PURE__ */ new Set([
@@ -54,7 +50,7 @@ function parseMultiAccountsUr(input) {
54
50
  const entry = tryParseEntry(decoded);
55
51
  if (!entry) throw new require_shared.EraSdkError("malformed-reply", "crypto-hdkey export carries no derivable account (missing origin keypath)");
56
52
  return {
57
- masterFingerprint: entry.xfp,
53
+ masterFingerprint: entry.xfp ?? 0,
58
54
  deviceName: null,
59
55
  deviceId: null,
60
56
  deviceVersion: null,
@@ -84,12 +80,13 @@ function tryParseEntry(item) {
84
80
  const origin = require_shared.asMap(require_shared.mapGet(map, 6));
85
81
  if (!origin) return null;
86
82
  const path = require_shared.parsePathComponents(require_shared.mapGet(origin, 1));
87
- const xfp = require_shared.asUint(require_shared.mapGet(origin, 2));
88
- if (!path || path.length === 0 || xfp === void 0 || xfp > 4294967295n) return null;
83
+ if (!path || path.length === 0) return null;
84
+ const xfpValue = require_shared.asUint(require_shared.mapGet(origin, 2));
85
+ const xfp = xfpValue !== void 0 && xfpValue <= 4294967295n ? Number(xfpValue) : null;
89
86
  const parentFp = require_shared.asUint(require_shared.mapGet(map, 8));
90
87
  return {
91
88
  path,
92
- xfp: Number(xfp),
89
+ xfp,
93
90
  publicKey: require_shared.asBytes(require_shared.mapGet(map, 3)) ?? null,
94
91
  chainCode: require_shared.asBytes(require_shared.mapGet(map, 4)) ?? null,
95
92
  parentFingerprint: parentFp !== void 0 && parentFp <= 4294967295n ? Number(parentFp) : null,
@@ -98,66 +95,6 @@ function tryParseEntry(item) {
98
95
  };
99
96
  }
100
97
  //#endregion
101
- //#region src/accounts/derive.ts
102
- const base58check = (0, _scure_base.createBase58check)(_noble_hashes_sha2.sha256);
103
- /** Non-hardened BIP-32 child public key from an account-level (publicKey, chainCode). */
104
- function derivePublicKey(publicKey, chainCode, change, index) {
105
- const child = new _scure_bip32.HDKey({
106
- publicKey,
107
- chainCode
108
- }).deriveChild(change).deriveChild(index);
109
- if (!child.publicKey) throw new require_shared.EraSdkError("invalid-props", "child derivation produced no public key");
110
- return child.publicKey;
111
- }
112
- function uncompressed(publicKey33) {
113
- return _noble_curves_secp256k1.secp256k1.ProjectivePoint.fromHex(publicKey33).toRawBytes(false);
114
- }
115
- /** EIP-55 checksummed address from a compressed secp256k1 public key. */
116
- function evmAddressFromPublicKey(publicKey33) {
117
- const hash = (0, _noble_hashes_sha3.keccak_256)(uncompressed(publicKey33).slice(1));
118
- const addr = require_shared.bytesToHex(hash.slice(12));
119
- const check = (0, _noble_hashes_sha3.keccak_256)(new Uint8Array([...addr].map((c) => c.charCodeAt(0))));
120
- let out = "";
121
- for (let i = 0; i < addr.length; i++) {
122
- const nibble = i % 2 === 0 ? check[i >> 1] >> 4 : check[i >> 1] & 15;
123
- out += nibble >= 8 ? addr[i].toUpperCase() : addr[i];
124
- }
125
- return `0x${out}`;
126
- }
127
- function hash160(data) {
128
- return (0, _noble_hashes_ripemd160.ripemd160)((0, _noble_hashes_sha2.sha256)(data));
129
- }
130
- /** P2WPKH (witness v0) bech32 address. */
131
- function btcP2wpkhAddressFromPublicKey(publicKey33, hrp = "bc") {
132
- return _scure_base.bech32.encode(hrp, [0, ..._scure_base.bech32.toWords(hash160(publicKey33))]);
133
- }
134
- /** Legacy P2PKH base58check address (`1...`) — the kind the device signs messages for. */
135
- function btcP2pkhAddressFromPublicKey(publicKey33, testnet = false) {
136
- return base58check.encode(require_shared.concatBytes(new Uint8Array([testnet ? 111 : 0]), hash160(publicKey33)));
137
- }
138
- /** Nested segwit (P2SH-P2WPKH) base58check address (`3...`). */
139
- function btcNestedSegwitAddressFromPublicKey(publicKey33, testnet = false) {
140
- const redeemScript = require_shared.concatBytes(new Uint8Array([0, 20]), hash160(publicKey33));
141
- return base58check.encode(require_shared.concatBytes(new Uint8Array([testnet ? 196 : 5]), hash160(redeemScript)));
142
- }
143
- /** Tron base58check address (0x41-prefixed keccak hash). */
144
- function tronAddressFromPublicKey(publicKey33) {
145
- const hash = (0, _noble_hashes_sha3.keccak_256)(uncompressed(publicKey33).slice(1));
146
- return base58check.encode(require_shared.concatBytes(new Uint8Array([65]), hash.slice(12)));
147
- }
148
- /** A Solana address IS the Ed25519 public key, base58. */
149
- function solanaAddressFromPublicKey(publicKey32) {
150
- return _scure_base.base58.encode(publicKey32);
151
- }
152
- const XPUB_VERSION = 76067358;
153
- const ZPUB_VERSION = 78792518;
154
- /** BIP-32 extended public key serialization. */
155
- function serializeExtendedPublicKey(args) {
156
- const { version = XPUB_VERSION, depth, parentFingerprint, childNumber, chainCode, publicKey } = args;
157
- if (chainCode.length !== 32 || publicKey.length !== 33) throw new require_shared.EraSdkError("invalid-props", "extended key needs a 32-byte chain code and 33-byte key");
158
- return base58check.encode(require_shared.concatBytes(require_shared.u32be(version), new Uint8Array([depth & 255]), require_shared.u32be(parentFingerprint), require_shared.u32be(childNumber), chainCode, publicKey));
159
- }
160
- //#endregion
161
98
  //#region src/accounts/accounts.ts
162
99
  function classify(path) {
163
100
  const p0 = path[0];
@@ -168,6 +105,7 @@ function classify(path) {
168
105
  if (p0.index === 44 && p1.index === 501) return "solana";
169
106
  if (p0.index === 44 && p1.index === 195) return "tron";
170
107
  if (p0.index === 44 && p1.index === 607) return "ton";
108
+ if (p0.index === 1852 && p1.index === 1815) return "cardano";
171
109
  return "unknown";
172
110
  }
173
111
  function withChainCode(entry) {
@@ -181,11 +119,12 @@ function requireKey(entry, length) {
181
119
  }
182
120
  /** EVM view over the linked wallet: one account xpub, addresses derived at `0/index`. */
183
121
  var EvmAccountView = class {
184
- constructor(entry) {
122
+ constructor(entry, resolvedXfp) {
185
123
  this.entry = entry;
124
+ this.resolvedXfp = resolvedXfp;
186
125
  }
187
126
  get xfp() {
188
- return require_shared.xfpToHex(this.entry.xfp);
127
+ return require_shared.xfpToHex(this.resolvedXfp);
189
128
  }
190
129
  get accountPath() {
191
130
  return require_shared.formatPath([...this.entry.path]);
@@ -195,7 +134,7 @@ var EvmAccountView = class {
195
134
  return `${this.accountPath}/0/${index}`;
196
135
  }
197
136
  deriveAddress(index) {
198
- return evmAddressFromPublicKey(derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
137
+ return require_derive.evmAddressFromPublicKey(require_derive.derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
199
138
  }
200
139
  xpub() {
201
140
  return extendedKeyOf(this.entry);
@@ -208,13 +147,14 @@ var EvmAccountView = class {
208
147
  * 49 = nested segwit, 86 = taproot).
209
148
  */
210
149
  var BtcAccountView = class {
211
- constructor(entry, testnet, purpose) {
150
+ constructor(entry, testnet, purpose, resolvedXfp) {
212
151
  this.entry = entry;
213
152
  this.testnet = testnet;
214
153
  this.purpose = purpose;
154
+ this.resolvedXfp = resolvedXfp;
215
155
  }
216
156
  get xfp() {
217
- return require_shared.xfpToHex(this.entry.xfp);
157
+ return require_shared.xfpToHex(this.resolvedXfp);
218
158
  }
219
159
  get accountPath() {
220
160
  return require_shared.formatPath([...this.entry.path]);
@@ -227,11 +167,11 @@ var BtcAccountView = class {
227
167
  }
228
168
  deriveAddress(index, options) {
229
169
  const change = options?.change ? 1 : 0;
230
- const child = derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), change, index);
170
+ const child = require_derive.derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), change, index);
231
171
  switch (this.purpose) {
232
- case 84: return btcP2wpkhAddressFromPublicKey(child, this.testnet ? "tb" : "bc");
233
- case 44: return btcP2pkhAddressFromPublicKey(child, this.testnet);
234
- case 49: return btcNestedSegwitAddressFromPublicKey(child, this.testnet);
172
+ case 84: return require_derive.btcP2wpkhAddressFromPublicKey(child, this.testnet ? "tb" : "bc");
173
+ case 44: return require_derive.btcP2pkhAddressFromPublicKey(child, this.testnet);
174
+ case 49: return require_derive.btcNestedSegwitAddressFromPublicKey(child, this.testnet);
235
175
  case 86: throw new require_shared.EraSdkError("invalid-props", "taproot addresses need the BIP-341 output-key tweak; derive them from xpub() with your Bitcoin library");
236
176
  }
237
177
  }
@@ -241,16 +181,17 @@ var BtcAccountView = class {
241
181
  /** SLIP-132 zpub form of the BIP-84 key, for tools that require it. */
242
182
  zpub() {
243
183
  if (this.purpose !== 84) throw new require_shared.EraSdkError("invalid-props", "zpub is the SLIP-132 form of the BIP-84 account only");
244
- return extendedKeyOf(this.entry, ZPUB_VERSION);
184
+ return extendedKeyOf(this.entry, require_derive.ZPUB_VERSION);
245
185
  }
246
186
  };
247
187
  /** Tron view: addresses derived at `0/index`. */
248
188
  var TronAccountView = class {
249
- constructor(entry) {
189
+ constructor(entry, resolvedXfp) {
250
190
  this.entry = entry;
191
+ this.resolvedXfp = resolvedXfp;
251
192
  }
252
193
  get xfp() {
253
- return require_shared.xfpToHex(this.entry.xfp);
194
+ return require_shared.xfpToHex(this.resolvedXfp);
254
195
  }
255
196
  get accountPath() {
256
197
  return require_shared.formatPath([...this.entry.path]);
@@ -259,7 +200,7 @@ var TronAccountView = class {
259
200
  return `${this.accountPath}/0/${index}`;
260
201
  }
261
202
  deriveAddress(index) {
262
- return tronAddressFromPublicKey(derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
203
+ return require_derive.tronAddressFromPublicKey(require_derive.derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
263
204
  }
264
205
  };
265
206
  /**
@@ -269,11 +210,12 @@ var TronAccountView = class {
269
210
  * with @ton/core or equivalent).
270
211
  */
271
212
  var TonAccountView = class {
272
- constructor(entry) {
213
+ constructor(entry, resolvedXfp) {
273
214
  this.entry = entry;
215
+ this.resolvedXfp = resolvedXfp;
274
216
  }
275
217
  get xfp() {
276
- return require_shared.xfpToHex(this.entry.xfp);
218
+ return require_shared.xfpToHex(this.resolvedXfp);
277
219
  }
278
220
  get accountPath() {
279
221
  return require_shared.formatPath([...this.entry.path]);
@@ -287,16 +229,50 @@ var TonAccountView = class {
287
229
  }
288
230
  };
289
231
  /**
232
+ * Cardano view (CIP-1852): the exported account key supports SOFT public
233
+ * derivation (BIP32-Ed25519), so payment (`0/i`), change (`1/i`) and stake
234
+ * (`2/0`) verification keys derive locally. Bech32 ADDRESS assembly is left
235
+ * to Cardano tooling — `deriveKey` hands you the raw vkeys it needs.
236
+ */
237
+ var CardanoAccountView = class {
238
+ constructor(entry, resolvedXfp) {
239
+ this.entry = entry;
240
+ this.resolvedXfp = resolvedXfp;
241
+ }
242
+ get xfp() {
243
+ return require_shared.xfpToHex(this.resolvedXfp);
244
+ }
245
+ get accountPath() {
246
+ return require_shared.formatPath([...this.entry.path]);
247
+ }
248
+ /** The account-level extended public key material. */
249
+ get publicKey() {
250
+ return requireKey(this.entry, 32);
251
+ }
252
+ get chainCode() {
253
+ return withChainCode(this.entry);
254
+ }
255
+ /** Signing path for `role/index`, e.g. `pathFor(0, 0)` → `.../0/0`. */
256
+ pathFor(role, index) {
257
+ return `${this.accountPath}/${role}/${index}`;
258
+ }
259
+ /** Soft-derived 32-byte verification key at `role/index` (0 payment, 1 change, 2 stake). */
260
+ deriveKey(role, index) {
261
+ return require_derive.cardanoSoftDerivePath(requireKey(this.entry, 32), withChainCode(this.entry), [role, index]);
262
+ }
263
+ };
264
+ /**
290
265
  * Solana view: Ed25519 has no public child derivation, so the device
291
266
  * pre-derives hardened accounts (`m/44'/501'/idx'`) and each entry IS a
292
267
  * signer. The public key, base58, IS the address.
293
268
  */
294
269
  var SolanaAccountView = class {
295
- constructor(entry) {
270
+ constructor(entry, resolvedXfp) {
296
271
  this.entry = entry;
272
+ this.resolvedXfp = resolvedXfp;
297
273
  }
298
274
  get xfp() {
299
- return require_shared.xfpToHex(this.entry.xfp);
275
+ return require_shared.xfpToHex(this.resolvedXfp);
300
276
  }
301
277
  get path() {
302
278
  return require_shared.formatPath([...this.entry.path]);
@@ -309,7 +285,7 @@ var SolanaAccountView = class {
309
285
  return requireKey(this.entry, 32);
310
286
  }
311
287
  get address() {
312
- return solanaAddressFromPublicKey(requireKey(this.entry, 32));
288
+ return require_derive.solanaAddressFromPublicKey(requireKey(this.entry, 32));
313
289
  }
314
290
  };
315
291
  function extendedKeyOf(entry, version) {
@@ -323,7 +299,7 @@ function extendedKeyOf(entry, version) {
323
299
  chainCode,
324
300
  publicKey
325
301
  };
326
- return version === void 0 ? serializeExtendedPublicKey(args) : serializeExtendedPublicKey({
302
+ return version === void 0 ? require_derive.serializeExtendedPublicKey(args) : require_derive.serializeExtendedPublicKey({
327
303
  ...args,
328
304
  version
329
305
  });
@@ -357,7 +333,7 @@ var EraAccounts = class EraAccounts {
357
333
  return this.raw.entries.map((entry) => ({
358
334
  chain: classify(entry.path),
359
335
  path: require_shared.formatPath([...entry.path]),
360
- xfp: require_shared.xfpToHex(entry.xfp),
336
+ xfp: require_shared.xfpToHex(entry.xfp ?? this.raw.masterFingerprint),
361
337
  publicKey: entry.publicKey ?? void 0,
362
338
  chainCode: entry.chainCode ?? void 0,
363
339
  name: entry.name ?? void 0,
@@ -369,12 +345,16 @@ var EraAccounts = class EraAccounts {
369
345
  * equals `accountPath`. Throws `account-not-found` — never a silent zero.
370
346
  */
371
347
  xfpFor(accountPath) {
372
- return require_shared.xfpToHex(this.entryFor(accountPath).xfp);
348
+ return require_shared.xfpToHex(this.resolveXfp(this.entryFor(accountPath)));
349
+ }
350
+ /** Entry xfp, falling back to the wrapper's master fingerprint (Cardano-style path-only origins). */
351
+ resolveXfp(entry) {
352
+ return entry.xfp ?? this.raw.masterFingerprint;
373
353
  }
374
354
  /** The EVM account (standard `m/44'/60'/...` scheme), if the export carries one. */
375
355
  evm() {
376
356
  const entry = this.raw.entries.find((e) => classify(e.path) === "evm" && (e.note === null || e.note === "account.standard")) ?? this.raw.entries.find((e) => classify(e.path) === "evm");
377
- return entry ? new EvmAccountView(entry) : void 0;
357
+ return entry ? new EvmAccountView(entry, this.resolveXfp(entry)) : void 0;
378
358
  }
379
359
  /**
380
360
  * A Bitcoin account view. Defaults to the BIP-84 native-segwit account;
@@ -384,20 +364,25 @@ var EraAccounts = class EraAccounts {
384
364
  btc(options) {
385
365
  const purpose = options?.purpose ?? 84;
386
366
  const entry = this.raw.entries.find((e) => classify(e.path) === "btc" && e.path[0]?.index === purpose);
387
- return entry ? new BtcAccountView(entry, options?.testnet ?? false, purpose) : void 0;
367
+ return entry ? new BtcAccountView(entry, options?.testnet ?? false, purpose, this.resolveXfp(entry)) : void 0;
388
368
  }
389
369
  tron() {
390
370
  const entry = this.raw.entries.find((e) => classify(e.path) === "tron");
391
- return entry ? new TronAccountView(entry) : void 0;
371
+ return entry ? new TronAccountView(entry, this.resolveXfp(entry)) : void 0;
392
372
  }
393
373
  /** The TON account (linked via the Tonkeeper-style `crypto-hdkey` export). */
394
374
  ton() {
395
375
  const entry = this.raw.entries.find((e) => classify(e.path) === "ton" && e.publicKey?.length === 32);
396
- return entry ? new TonAccountView(entry) : void 0;
376
+ return entry ? new TonAccountView(entry, this.resolveXfp(entry)) : void 0;
377
+ }
378
+ /** The Cardano account (CIP-1852 Icarus export), if the export carries one. */
379
+ cardano() {
380
+ const entry = this.raw.entries.find((e) => classify(e.path) === "cardano" && e.publicKey?.length === 32);
381
+ return entry ? new CardanoAccountView(entry, this.resolveXfp(entry)) : void 0;
397
382
  }
398
383
  /** All pre-derived Solana signers (usually `m/44'/501'/0'..9'`). */
399
384
  solana() {
400
- return this.raw.entries.filter((e) => classify(e.path) === "solana" && e.publicKey?.length === 32).map((e) => new SolanaAccountView(e));
385
+ return this.raw.entries.filter((e) => classify(e.path) === "solana" && e.publicKey?.length === 32).map((e) => new SolanaAccountView(e, this.resolveXfp(e)));
401
386
  }
402
387
  entryFor(accountPath) {
403
388
  const levels = require_shared.parsePath(accountPath);
@@ -522,6 +507,10 @@ var EraConnect = class {
522
507
  this._ton ?? (this._ton = new require_ton.TonChain(this.context));
523
508
  return this._ton;
524
509
  }
510
+ get cardano() {
511
+ this._cardano ?? (this._cardano = new require_cardano.CardanoChain(this.context));
512
+ return this._cardano;
513
+ }
525
514
  /** Escape hatch for UR types without a dedicated module. */
526
515
  get raw() {
527
516
  this._raw ?? (this._raw = new RawModule(this.context));
@@ -551,6 +540,8 @@ var EraConnect = class {
551
540
  exports.AnimatedUr = require_shared.AnimatedUr;
552
541
  exports.BtcAccountView = BtcAccountView;
553
542
  exports.BtcChain = require_btc.BtcChain;
543
+ exports.CardanoAccountView = CardanoAccountView;
544
+ exports.CardanoChain = require_cardano.CardanoChain;
554
545
  exports.DEFAULT_FRAGMENT_LENGTH = require_shared.DEFAULT_FRAGMENT_LENGTH;
555
546
  exports.DEFAULT_ORIGIN = require_shared.DEFAULT_ORIGIN;
556
547
  exports.DeviceProfile = DeviceProfile;
@@ -573,6 +564,7 @@ exports.TypedUrScanner = require_shared.TypedUrScanner;
573
564
  exports.Ur = require_shared.Ur;
574
565
  exports.UrLimits = require_shared.UrLimits;
575
566
  exports.UrScanner = require_shared.UrScanner;
567
+ exports.parseWitnessSet = require_cardano.parseWitnessSet;
576
568
  exports.utf8Decode = require_shared.utf8Decode;
577
569
  exports.utf8Encode = require_shared.utf8Encode;
578
570