@hwlt/era-connect 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +9 -0
  3. package/README.md +101 -0
  4. package/btc/package.json +6 -0
  5. package/dist/btc-DfQ0q79G.d.ts +58 -0
  6. package/dist/btc-Dn6_Y12c.d.cts +58 -0
  7. package/dist/btc-Fr6Jz4Fi.cjs +104 -0
  8. package/dist/btc-Fr6Jz4Fi.cjs.map +1 -0
  9. package/dist/btc-VyJKXq7d.js +99 -0
  10. package/dist/btc-VyJKXq7d.js.map +1 -0
  11. package/dist/btc.cjs +9 -0
  12. package/dist/btc.d.cts +3 -0
  13. package/dist/btc.d.ts +3 -0
  14. package/dist/btc.js +3 -0
  15. package/dist/evm-BHj_2OTG.cjs +134 -0
  16. package/dist/evm-BHj_2OTG.cjs.map +1 -0
  17. package/dist/evm-DJxGGAbD.d.cts +76 -0
  18. package/dist/evm-KrV5wK08.d.ts +76 -0
  19. package/dist/evm-kJb3-oiR.js +117 -0
  20. package/dist/evm-kJb3-oiR.js.map +1 -0
  21. package/dist/evm.cjs +11 -0
  22. package/dist/evm.d.cts +3 -0
  23. package/dist/evm.d.ts +3 -0
  24. package/dist/evm.js +3 -0
  25. package/dist/index.cjs +530 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.cts +285 -0
  28. package/dist/index.d.ts +285 -0
  29. package/dist/index.js +506 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/messages-17Oup0-Z.js +208 -0
  32. package/dist/messages-17Oup0-Z.js.map +1 -0
  33. package/dist/messages-BzcdWlg1.cjs +243 -0
  34. package/dist/messages-BzcdWlg1.cjs.map +1 -0
  35. package/dist/messages-DsPvW8Oi.d.cts +29 -0
  36. package/dist/messages-DsPvW8Oi.d.ts +29 -0
  37. package/dist/shared-B8Wc7ViU.js +1472 -0
  38. package/dist/shared-B8Wc7ViU.js.map +1 -0
  39. package/dist/shared-CI8zhQiE.d.cts +218 -0
  40. package/dist/shared-CI8zhQiE.d.ts +218 -0
  41. package/dist/shared-nISrEktU.cjs +1777 -0
  42. package/dist/shared-nISrEktU.cjs.map +1 -0
  43. package/dist/solana-8eOwz0gM.d.cts +49 -0
  44. package/dist/solana-C2Xm7w8a.d.ts +49 -0
  45. package/dist/solana-C7JQEAec.js +87 -0
  46. package/dist/solana-C7JQEAec.js.map +1 -0
  47. package/dist/solana-DdEn24X4.cjs +98 -0
  48. package/dist/solana-DdEn24X4.cjs.map +1 -0
  49. package/dist/solana.cjs +10 -0
  50. package/dist/solana.d.cts +3 -0
  51. package/dist/solana.d.ts +3 -0
  52. package/dist/solana.js +3 -0
  53. package/dist/tron-Bo9HnvVE.js +158 -0
  54. package/dist/tron-Bo9HnvVE.js.map +1 -0
  55. package/dist/tron-CQIEqjCA.cjs +163 -0
  56. package/dist/tron-CQIEqjCA.cjs.map +1 -0
  57. package/dist/tron-YllfTmx6.d.ts +63 -0
  58. package/dist/tron-gG51KMnX.d.cts +63 -0
  59. package/dist/tron.cjs +11 -0
  60. package/dist/tron.d.cts +4 -0
  61. package/dist/tron.d.ts +4 -0
  62. package/dist/tron.js +4 -0
  63. package/dist/verify.cjs +445 -0
  64. package/dist/verify.cjs.map +1 -0
  65. package/dist/verify.d.cts +162 -0
  66. package/dist/verify.d.ts +162 -0
  67. package/dist/verify.js +438 -0
  68. package/dist/verify.js.map +1 -0
  69. package/evm/package.json +6 -0
  70. package/package.json +140 -0
  71. package/proto/tron/base.proto +16 -0
  72. package/proto/tron/message.proto +12 -0
  73. package/proto/tron/payload.proto +35 -0
  74. package/proto/tron/sign_transaction_result.proto +10 -0
  75. package/proto/tron/sync.proto +21 -0
  76. package/proto/tron/transaction.proto +17 -0
  77. package/proto/tron/tron_transaction.proto +31 -0
  78. package/proto/tron/verify_address.proto +10 -0
  79. package/solana/package.json +6 -0
  80. package/tron/package.json +6 -0
  81. package/verify/package.json +6 -0
package/dist/index.js ADDED
@@ -0,0 +1,506 @@
1
+ import { A as utf8Encode, B as asMap, F as parsePathComponents, G as cbMap, H as asUint, I as pathEquals, J as cbUint, K as cbTag, L as xfpToHex, M as keypath304, O as u32be, P as parsePath, R as asArray, T as concatBytes, U as cbArray, V as asText, Y as mapGet, Z as EraSdkError, _ as Ur, b as cborDecode, d as UrScanner, f as AnimatedUr, j as formatPath, k as utf8Decode, l as toUr, m as UrLimits, p as DEFAULT_FRAGMENT_LENGTH, q as cbText, s as resolveContext, t as DEFAULT_ORIGIN, u as TypedUrScanner, v as parseUrString, w as bytesToHex, x as cborEncode, z as asBytes } from "./shared-B8Wc7ViU.js";
2
+ import { t as BtcChain } from "./btc-VyJKXq7d.js";
3
+ import { n as EvmDataType, t as EvmChain } from "./evm-kJb3-oiR.js";
4
+ import { n as SolanaChain, t as SolSignType } from "./solana-C7JQEAec.js";
5
+ import { t as TronChain } from "./tron-Bo9HnvVE.js";
6
+ import { secp256k1 } from "@noble/curves/secp256k1";
7
+ import { ripemd160 } from "@noble/hashes/ripemd160";
8
+ import { sha256 } from "@noble/hashes/sha2";
9
+ import { keccak_256 } from "@noble/hashes/sha3";
10
+ import { base58, bech32, createBase58check } from "@scure/base";
11
+ import { HDKey } from "@scure/bip32";
12
+ //#region src/registry/multi-accounts.ts
13
+ /** UR types a device links a watch-only wallet with. */
14
+ const WALLET_UR_TYPES = /* @__PURE__ */ new Set([
15
+ "crypto-multi-accounts",
16
+ "crypto-account",
17
+ "crypto-hdkey"
18
+ ]);
19
+ /**
20
+ * Parse a wallet-export UR.
21
+ *
22
+ * Of the three admitted link types only the `crypto-multi-accounts` shape
23
+ * yields derivable accounts; an export that yields none is refused rather
24
+ * than stored as an unusable wallet. Malformed entries are skipped
25
+ * individually so one foreign item does not abort the rest.
26
+ */
27
+ function parseMultiAccountsUr(input) {
28
+ let type;
29
+ let cbor;
30
+ if (typeof input === "string") {
31
+ const parsed = parseUrString(input);
32
+ if (parsed.seq !== null) throw new EraSdkError("invalid-props", "multi-part UR string: assemble it with a UrScanner first");
33
+ type = parsed.type;
34
+ cbor = parsed.payload;
35
+ } else {
36
+ type = input.type;
37
+ cbor = input.cbor;
38
+ }
39
+ if (!WALLET_UR_TYPES.has(type)) {
40
+ const shown = type.length > 32 ? `${type.slice(0, 32)}…` : type;
41
+ throw new EraSdkError("wrong-ur-type", `"${shown}" is not a wallet export; expected one of ${[...WALLET_UR_TYPES].join(", ")}`, { received: shown });
42
+ }
43
+ let decoded;
44
+ try {
45
+ decoded = cborDecode(cbor);
46
+ } catch (e) {
47
+ throw new EraSdkError("malformed-cbor", `cannot decode wallet UR: ${e.message}`);
48
+ }
49
+ const root = asMap(decoded);
50
+ if (!root) throw new EraSdkError("malformed-cbor", "wallet UR is not a CBOR map");
51
+ const master = asUint(mapGet(root, 1));
52
+ const list = asArray(mapGet(root, 2));
53
+ if (master === void 0 || !list) throw new EraSdkError("malformed-reply", "wallet UR missing master fingerprint (key 1) or accounts (key 2)");
54
+ const entries = [];
55
+ for (const item of list) {
56
+ const entry = tryParseEntry(item);
57
+ if (entry) entries.push(entry);
58
+ }
59
+ if (entries.length === 0) throw new EraSdkError("malformed-reply", "wallet UR carries no account this SDK can derive an address from");
60
+ return {
61
+ masterFingerprint: Number(master & 4294967295n),
62
+ deviceName: asText(mapGet(root, 3)) ?? null,
63
+ deviceId: asText(mapGet(root, 4)) ?? null,
64
+ deviceVersion: asText(mapGet(root, 5)) ?? null,
65
+ entries
66
+ };
67
+ }
68
+ function tryParseEntry(item) {
69
+ const map = asMap(item);
70
+ if (!map) return null;
71
+ const origin = asMap(mapGet(map, 6));
72
+ if (!origin) return null;
73
+ const path = parsePathComponents(mapGet(origin, 1));
74
+ const xfp = asUint(mapGet(origin, 2));
75
+ if (!path || path.length === 0 || xfp === void 0 || xfp > 4294967295n) return null;
76
+ const parentFp = asUint(mapGet(map, 8));
77
+ return {
78
+ path,
79
+ xfp: Number(xfp),
80
+ publicKey: asBytes(mapGet(map, 3)) ?? null,
81
+ chainCode: asBytes(mapGet(map, 4)) ?? null,
82
+ parentFingerprint: parentFp !== void 0 && parentFp <= 4294967295n ? Number(parentFp) : null,
83
+ name: asText(mapGet(map, 9)) ?? null,
84
+ note: asText(mapGet(map, 10)) ?? null
85
+ };
86
+ }
87
+ //#endregion
88
+ //#region src/accounts/derive.ts
89
+ const base58check = createBase58check(sha256);
90
+ /** Non-hardened BIP-32 child public key from an account-level (publicKey, chainCode). */
91
+ function derivePublicKey(publicKey, chainCode, change, index) {
92
+ const child = new HDKey({
93
+ publicKey,
94
+ chainCode
95
+ }).deriveChild(change).deriveChild(index);
96
+ if (!child.publicKey) throw new EraSdkError("invalid-props", "child derivation produced no public key");
97
+ return child.publicKey;
98
+ }
99
+ function uncompressed(publicKey33) {
100
+ return secp256k1.ProjectivePoint.fromHex(publicKey33).toRawBytes(false);
101
+ }
102
+ /** EIP-55 checksummed address from a compressed secp256k1 public key. */
103
+ function evmAddressFromPublicKey(publicKey33) {
104
+ const hash = keccak_256(uncompressed(publicKey33).slice(1));
105
+ const addr = bytesToHex(hash.slice(12));
106
+ const check = keccak_256(new Uint8Array([...addr].map((c) => c.charCodeAt(0))));
107
+ let out = "";
108
+ for (let i = 0; i < addr.length; i++) {
109
+ const nibble = i % 2 === 0 ? check[i >> 1] >> 4 : check[i >> 1] & 15;
110
+ out += nibble >= 8 ? addr[i].toUpperCase() : addr[i];
111
+ }
112
+ return `0x${out}`;
113
+ }
114
+ function hash160(data) {
115
+ return ripemd160(sha256(data));
116
+ }
117
+ /** P2WPKH (witness v0) bech32 address. */
118
+ function btcP2wpkhAddressFromPublicKey(publicKey33, hrp = "bc") {
119
+ return bech32.encode(hrp, [0, ...bech32.toWords(hash160(publicKey33))]);
120
+ }
121
+ /** Legacy P2PKH base58check address (`1...`) — the kind the device signs messages for. */
122
+ function btcP2pkhAddressFromPublicKey(publicKey33, testnet = false) {
123
+ return base58check.encode(concatBytes(new Uint8Array([testnet ? 111 : 0]), hash160(publicKey33)));
124
+ }
125
+ /** Nested segwit (P2SH-P2WPKH) base58check address (`3...`). */
126
+ function btcNestedSegwitAddressFromPublicKey(publicKey33, testnet = false) {
127
+ const redeemScript = concatBytes(new Uint8Array([0, 20]), hash160(publicKey33));
128
+ return base58check.encode(concatBytes(new Uint8Array([testnet ? 196 : 5]), hash160(redeemScript)));
129
+ }
130
+ /** Tron base58check address (0x41-prefixed keccak hash). */
131
+ function tronAddressFromPublicKey(publicKey33) {
132
+ const hash = keccak_256(uncompressed(publicKey33).slice(1));
133
+ return base58check.encode(concatBytes(new Uint8Array([65]), hash.slice(12)));
134
+ }
135
+ /** A Solana address IS the Ed25519 public key, base58. */
136
+ function solanaAddressFromPublicKey(publicKey32) {
137
+ return base58.encode(publicKey32);
138
+ }
139
+ const XPUB_VERSION = 76067358;
140
+ const ZPUB_VERSION = 78792518;
141
+ /** BIP-32 extended public key serialization. */
142
+ function serializeExtendedPublicKey(args) {
143
+ const { version = XPUB_VERSION, depth, parentFingerprint, childNumber, chainCode, publicKey } = args;
144
+ if (chainCode.length !== 32 || publicKey.length !== 33) throw new EraSdkError("invalid-props", "extended key needs a 32-byte chain code and 33-byte key");
145
+ return base58check.encode(concatBytes(u32be(version), new Uint8Array([depth & 255]), u32be(parentFingerprint), u32be(childNumber), chainCode, publicKey));
146
+ }
147
+ //#endregion
148
+ //#region src/accounts/accounts.ts
149
+ function classify(path) {
150
+ const p0 = path[0];
151
+ const p1 = path[1];
152
+ if (!p0 || !p1 || !p0.hardened || !p1.hardened) return "unknown";
153
+ if (p0.index === 44 && p1.index === 60) return "evm";
154
+ if (p1.index === 0 && (p0.index === 84 || p0.index === 49 || p0.index === 44 || p0.index === 86)) return "btc";
155
+ if (p0.index === 44 && p1.index === 501) return "solana";
156
+ if (p0.index === 44 && p1.index === 195) return "tron";
157
+ return "unknown";
158
+ }
159
+ function withChainCode(entry) {
160
+ if (!entry.chainCode) throw new EraSdkError("account-not-found", `account ${formatPath([...entry.path])} carries no chain code; cannot derive children`);
161
+ return entry.chainCode;
162
+ }
163
+ /** The entry's key at the required length, or a typed refusal (derivation only). */
164
+ function requireKey(entry, length) {
165
+ if (!entry.publicKey || entry.publicKey.length !== length) throw new EraSdkError("invalid-props", `account ${formatPath([...entry.path])} carries no ${length}-byte public key; xfp lookup still works, address derivation does not`);
166
+ return entry.publicKey;
167
+ }
168
+ /** EVM view over the linked wallet: one account xpub, addresses derived at `0/index`. */
169
+ var EvmAccountView = class {
170
+ constructor(entry) {
171
+ this.entry = entry;
172
+ }
173
+ get xfp() {
174
+ return xfpToHex(this.entry.xfp);
175
+ }
176
+ get accountPath() {
177
+ return formatPath([...this.entry.path]);
178
+ }
179
+ /** Signing path for address `index`: `<account>/0/<index>`. */
180
+ pathFor(index) {
181
+ return `${this.accountPath}/0/${index}`;
182
+ }
183
+ deriveAddress(index) {
184
+ return evmAddressFromPublicKey(derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
185
+ }
186
+ xpub() {
187
+ return extendedKeyOf(this.entry);
188
+ }
189
+ };
190
+ /**
191
+ * Bitcoin view over one exported account. The default is the BIP-84
192
+ * native-segwit account; pass `purpose` to reach the other script types the
193
+ * device exports (44 = legacy P2PKH — the kind the device signs MESSAGES for,
194
+ * 49 = nested segwit, 86 = taproot).
195
+ */
196
+ var BtcAccountView = class {
197
+ constructor(entry, testnet, purpose) {
198
+ this.entry = entry;
199
+ this.testnet = testnet;
200
+ this.purpose = purpose;
201
+ }
202
+ get xfp() {
203
+ return xfpToHex(this.entry.xfp);
204
+ }
205
+ get accountPath() {
206
+ return formatPath([...this.entry.path]);
207
+ }
208
+ receivePath(index) {
209
+ return `${this.accountPath}/0/${index}`;
210
+ }
211
+ changePath(index) {
212
+ return `${this.accountPath}/1/${index}`;
213
+ }
214
+ deriveAddress(index, options) {
215
+ const change = options?.change ? 1 : 0;
216
+ const child = derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), change, index);
217
+ switch (this.purpose) {
218
+ case 84: return btcP2wpkhAddressFromPublicKey(child, this.testnet ? "tb" : "bc");
219
+ case 44: return btcP2pkhAddressFromPublicKey(child, this.testnet);
220
+ case 49: return btcNestedSegwitAddressFromPublicKey(child, this.testnet);
221
+ case 86: throw new EraSdkError("invalid-props", "taproot addresses need the BIP-341 output-key tweak; derive them from xpub() with your Bitcoin library");
222
+ }
223
+ }
224
+ xpub() {
225
+ return extendedKeyOf(this.entry);
226
+ }
227
+ /** SLIP-132 zpub form of the BIP-84 key, for tools that require it. */
228
+ zpub() {
229
+ if (this.purpose !== 84) throw new EraSdkError("invalid-props", "zpub is the SLIP-132 form of the BIP-84 account only");
230
+ return extendedKeyOf(this.entry, ZPUB_VERSION);
231
+ }
232
+ };
233
+ /** Tron view: addresses derived at `0/index`. */
234
+ var TronAccountView = class {
235
+ constructor(entry) {
236
+ this.entry = entry;
237
+ }
238
+ get xfp() {
239
+ return xfpToHex(this.entry.xfp);
240
+ }
241
+ get accountPath() {
242
+ return formatPath([...this.entry.path]);
243
+ }
244
+ pathFor(index) {
245
+ return `${this.accountPath}/0/${index}`;
246
+ }
247
+ deriveAddress(index) {
248
+ return tronAddressFromPublicKey(derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index));
249
+ }
250
+ };
251
+ /**
252
+ * Solana view: Ed25519 has no public child derivation, so the device
253
+ * pre-derives hardened accounts (`m/44'/501'/idx'`) and each entry IS a
254
+ * signer. The public key, base58, IS the address.
255
+ */
256
+ var SolanaAccountView = class {
257
+ constructor(entry) {
258
+ this.entry = entry;
259
+ }
260
+ get xfp() {
261
+ return xfpToHex(this.entry.xfp);
262
+ }
263
+ get path() {
264
+ return formatPath([...this.entry.path]);
265
+ }
266
+ /** The hardened account index (third path level). */
267
+ get index() {
268
+ return this.entry.path[2]?.index ?? 0;
269
+ }
270
+ get publicKey() {
271
+ return requireKey(this.entry, 32);
272
+ }
273
+ get address() {
274
+ return solanaAddressFromPublicKey(requireKey(this.entry, 32));
275
+ }
276
+ };
277
+ function extendedKeyOf(entry, version) {
278
+ const chainCode = withChainCode(entry);
279
+ const publicKey = requireKey(entry, 33);
280
+ const last = entry.path[entry.path.length - 1];
281
+ const args = {
282
+ depth: entry.path.length,
283
+ parentFingerprint: entry.parentFingerprint ?? 0,
284
+ childNumber: last.hardened ? last.index + 2147483648 : last.index,
285
+ chainCode,
286
+ publicKey
287
+ };
288
+ return version === void 0 ? serializeExtendedPublicKey(args) : serializeExtendedPublicKey({
289
+ ...args,
290
+ version
291
+ });
292
+ }
293
+ /**
294
+ * The linked wallet: everything a software wallet extracts from the device's
295
+ * `crypto-multi-accounts` QR. Parse once, store the source UR string, derive
296
+ * addresses locally — the device is not needed again until signing.
297
+ */
298
+ var EraAccounts = class EraAccounts {
299
+ constructor(raw, sourceUr) {
300
+ this.raw = raw;
301
+ this.sourceUr = sourceUr;
302
+ }
303
+ static fromUr(input) {
304
+ const raw = parseMultiAccountsUr(input);
305
+ return new EraAccounts(raw, typeof input === "string" ? input : input.toString());
306
+ }
307
+ /** Master fingerprint, lowercase 8-hex. */
308
+ get masterFingerprint() {
309
+ return xfpToHex(this.raw.masterFingerprint);
310
+ }
311
+ get device() {
312
+ return {
313
+ name: this.raw.deviceName ?? void 0,
314
+ id: this.raw.deviceId ?? void 0,
315
+ firmwareVersion: this.raw.deviceVersion ?? void 0
316
+ };
317
+ }
318
+ get keys() {
319
+ return this.raw.entries.map((entry) => ({
320
+ chain: classify(entry.path),
321
+ path: formatPath([...entry.path]),
322
+ xfp: xfpToHex(entry.xfp),
323
+ publicKey: entry.publicKey ?? void 0,
324
+ chainCode: entry.chainCode ?? void 0,
325
+ name: entry.name ?? void 0,
326
+ note: entry.note ?? void 0
327
+ }));
328
+ }
329
+ /**
330
+ * The xfp a sign request must carry for the account whose path exactly
331
+ * equals `accountPath`. Throws `account-not-found` — never a silent zero.
332
+ */
333
+ xfpFor(accountPath) {
334
+ return xfpToHex(this.entryFor(accountPath).xfp);
335
+ }
336
+ /** The EVM account (standard `m/44'/60'/...` scheme), if the export carries one. */
337
+ evm() {
338
+ 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");
339
+ return entry ? new EvmAccountView(entry) : void 0;
340
+ }
341
+ /**
342
+ * A Bitcoin account view. Defaults to the BIP-84 native-segwit account;
343
+ * pass `purpose: 44` for the legacy P2PKH account (message signing), 49 for
344
+ * nested segwit, 86 for taproot — if the export carries them.
345
+ */
346
+ btc(options) {
347
+ const purpose = options?.purpose ?? 84;
348
+ const entry = this.raw.entries.find((e) => classify(e.path) === "btc" && e.path[0]?.index === purpose);
349
+ return entry ? new BtcAccountView(entry, options?.testnet ?? false, purpose) : void 0;
350
+ }
351
+ tron() {
352
+ const entry = this.raw.entries.find((e) => classify(e.path) === "tron");
353
+ return entry ? new TronAccountView(entry) : void 0;
354
+ }
355
+ /** All pre-derived Solana signers (usually `m/44'/501'/0'..9'`). */
356
+ solana() {
357
+ return this.raw.entries.filter((e) => classify(e.path) === "solana" && e.publicKey?.length === 32).map((e) => new SolanaAccountView(e));
358
+ }
359
+ entryFor(accountPath) {
360
+ const levels = parsePath(accountPath);
361
+ const entry = this.raw.entries.find((e) => pathEquals(e.path, levels));
362
+ if (!entry) throw new EraSdkError("account-not-found", `the linked wallet carries no account at ${accountPath}`, { path: accountPath });
363
+ return entry;
364
+ }
365
+ };
366
+ //#endregion
367
+ //#region src/hardware-call/key-derivation.ts
368
+ const CURVES = {
369
+ secp256k1: 0,
370
+ ed25519: 1
371
+ };
372
+ const ALGOS = {
373
+ slip10: 0,
374
+ bip32ed25519: 1
375
+ };
376
+ /**
377
+ * Build a `qr-hardware-call` (1201) wrapping a `key-derivation-call` (1301):
378
+ * the WALLET asks the device for specific derivation paths, curves and
379
+ * algorithms instead of accepting whatever the device's sync screen
380
+ * volunteers. The device answers with a `crypto-multi-accounts` export, which
381
+ * closes the loop through `parseAccounts`.
382
+ *
383
+ * Registry shape (Keystone-standard):
384
+ * `1201({1: type=0, 2: 1301({1: [1302({1: 304(keypath), 2: curve, 3: algo, 4?: chainType})...]}), 3?: origin})`.
385
+ */
386
+ function generateKeyDerivationCall(context, props) {
387
+ if (props.schemas.length === 0) throw new EraSdkError("invalid-props", "at least one derivation schema is required");
388
+ const schemas = props.schemas.map((schema) => {
389
+ const levels = parsePath(schema.path);
390
+ const entries = [
391
+ [1, keypath304(levels)],
392
+ [2, cbUint(CURVES[schema.curve ?? "secp256k1"])],
393
+ [3, cbUint(ALGOS[schema.algo ?? "slip10"])]
394
+ ];
395
+ if (schema.chainType !== void 0) entries.push([4, cbText(schema.chainType)]);
396
+ return cbTag(1302, cbMap(entries));
397
+ });
398
+ const call = cbTag(1301, cbMap([[1, cbArray(schemas)]]));
399
+ const root = cbMap([
400
+ [1, cbUint(0)],
401
+ [2, call],
402
+ [3, cbText(props.origin ?? context.origin)]
403
+ ]);
404
+ const ur = new Ur("qr-hardware-call", cborEncode(root));
405
+ const replyTypes = [...WALLET_UR_TYPES];
406
+ return {
407
+ ur,
408
+ replyTypes,
409
+ toAnimated: (options) => new AnimatedUr(ur, { maxFragmentLength: options?.maxFragmentLength ?? context.maxFragmentLength }),
410
+ scanner: () => new TypedUrScanner({ expectedTypes: replyTypes }, (reply) => EraAccounts.fromUr(reply))
411
+ };
412
+ }
413
+ //#endregion
414
+ //#region src/raw.ts
415
+ /**
416
+ * Escape hatch for UR types this SDK has no dedicated module for (future
417
+ * chains, custom registry items). You bring the CBOR; the SDK brings the UR
418
+ * plumbing, fountain frames and the hardened scanner
419
+ * (`EraConnect.scanner({expectedTypes})`).
420
+ */
421
+ var RawModule = class {
422
+ constructor(context) {
423
+ this.context = context;
424
+ }
425
+ /** Wrap raw CBOR bytes in a UR of the given registry type. */
426
+ ur(type, cbor) {
427
+ return new Ur(type, cbor);
428
+ }
429
+ /** Parse a single-part `ur:` string into a Ur. */
430
+ parse(text) {
431
+ return toUr(text);
432
+ }
433
+ /** Fragment + animate any UR. */
434
+ animate(ur, options) {
435
+ return new AnimatedUr(ur, { maxFragmentLength: options?.maxFragmentLength ?? this.context.maxFragmentLength });
436
+ }
437
+ };
438
+ //#endregion
439
+ //#region src/index.ts
440
+ /** Timing/size constants of the device's own QR pipeline, for progress UI and timeouts. */
441
+ const DeviceProfile = {
442
+ /** What the phone displays to the device: ~200 wire bytes per frame at 8 fps. */
443
+ phoneToDevice: {
444
+ fragmentBytesOnWire: 200,
445
+ payloadBytes: 180,
446
+ frameIntervalMs: 125
447
+ },
448
+ /**
449
+ * What the device displays back: 150-byte fragments at 2.5 fps. Receiving
450
+ * is SLOWER than sending — budget scan timeouts accordingly.
451
+ */
452
+ deviceToPhone: {
453
+ fragmentBytesOnWire: 150,
454
+ frameIntervalMs: 400
455
+ }
456
+ };
457
+ /** The SDK facade. Cheap to construct; chain modules are created lazily. */
458
+ var EraConnect = class {
459
+ constructor(config) {
460
+ this.context = resolveContext(config);
461
+ }
462
+ get evm() {
463
+ this._evm ?? (this._evm = new EvmChain(this.context));
464
+ return this._evm;
465
+ }
466
+ get btc() {
467
+ this._btc ?? (this._btc = new BtcChain(this.context));
468
+ return this._btc;
469
+ }
470
+ get solana() {
471
+ this._solana ?? (this._solana = new SolanaChain(this.context));
472
+ return this._solana;
473
+ }
474
+ get tron() {
475
+ this._tron ?? (this._tron = new TronChain(this.context));
476
+ return this._tron;
477
+ }
478
+ /** Escape hatch for UR types without a dedicated module. */
479
+ get raw() {
480
+ this._raw ?? (this._raw = new RawModule(this.context));
481
+ return this._raw;
482
+ }
483
+ /**
484
+ * Linking: parse the device's `crypto-multi-accounts` export (a `Ur` from a
485
+ * scanner, or a single-part `ur:` string).
486
+ */
487
+ parseAccounts(input) {
488
+ return EraAccounts.fromUr(input);
489
+ }
490
+ /**
491
+ * Pull-model linking: ask the device for SPECIFIC derivations
492
+ * (`qr-hardware-call` 1201). The device answers with a
493
+ * `crypto-multi-accounts` export.
494
+ */
495
+ generateKeyDerivationCall(props) {
496
+ return generateKeyDerivationCall(this.context, props);
497
+ }
498
+ /** A type-agnostic hardened scanner (linking flows, raw flows). */
499
+ scanner(options) {
500
+ return new UrScanner(options);
501
+ }
502
+ };
503
+ //#endregion
504
+ export { AnimatedUr, BtcAccountView, BtcChain, DEFAULT_FRAGMENT_LENGTH, DEFAULT_ORIGIN, DeviceProfile, EraAccounts, EraConnect, EraSdkError, EvmAccountView, EvmChain, EvmDataType, RawModule, SolSignType, SolanaAccountView, SolanaChain, TronAccountView, TronChain, TypedUrScanner, Ur, UrLimits, UrScanner, utf8Decode, utf8Encode };
505
+
506
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["UrValue","EraAccountsClass","UrValue"],"sources":["../src/registry/multi-accounts.ts","../src/accounts/derive.ts","../src/accounts/accounts.ts","../src/hardware-call/key-derivation.ts","../src/raw.ts","../src/index.ts"],"sourcesContent":["import { cborDecode } from '../cbor/decode';\nimport type { CborValue } from '../cbor/model';\nimport { asArray, asBytes, asMap, asText, asUint, mapGet } from '../cbor/model';\nimport { EraSdkError } from '../core/errors';\nimport { parseUrString, type Ur } from '../ur/ur';\nimport type { PathLevel } from './keypath';\nimport { parsePathComponents } from './keypath';\n\n/**\n * Raw account entry parsed from a `crypto-multi-accounts` (1103) export.\n *\n * `xfp` is the entry's ORIGIN source fingerprint (`crypto-keypath` key 2) —\n * the value a `*-sign-request` keypath must carry. It is NOT the top-level\n * master fingerprint, although the two often coincide.\n */\nexport interface RawAccountEntry {\n readonly path: readonly PathLevel[];\n readonly xfp: number;\n /**\n * Nullable and length-unconstrained, as in the reference implementation: an\n * entry without a usable key still resolves its xfp for signing — only the\n * address-derivation views require the 33/32-byte forms.\n */\n readonly publicKey: Uint8Array | null;\n readonly chainCode: Uint8Array | null;\n readonly parentFingerprint: number | null;\n readonly name: string | null;\n /** A label string (`account.standard`, ...) — NEVER chain metadata. */\n readonly note: string | null;\n}\n\nexport interface RawMultiAccounts {\n readonly masterFingerprint: number;\n readonly deviceName: string | null;\n readonly deviceId: string | null;\n readonly deviceVersion: string | null;\n readonly entries: readonly RawAccountEntry[];\n}\n\n/** UR types a device links a watch-only wallet with. */\nexport const WALLET_UR_TYPES: ReadonlySet<string> = new Set([\n 'crypto-multi-accounts',\n 'crypto-account',\n 'crypto-hdkey',\n]);\n\n/**\n * Parse a wallet-export UR.\n *\n * Of the three admitted link types only the `crypto-multi-accounts` shape\n * yields derivable accounts; an export that yields none is refused rather\n * than stored as an unusable wallet. Malformed entries are skipped\n * individually so one foreign item does not abort the rest.\n */\nexport function parseMultiAccountsUr(input: Ur | string): RawMultiAccounts {\n let type: string;\n let cbor: Uint8Array;\n if (typeof input === 'string') {\n const parsed = parseUrString(input);\n if (parsed.seq !== null) {\n throw new EraSdkError(\n 'invalid-props',\n 'multi-part UR string: assemble it with a UrScanner first',\n );\n }\n type = parsed.type;\n cbor = parsed.payload;\n } else {\n type = input.type;\n cbor = input.cbor;\n }\n\n if (!WALLET_UR_TYPES.has(type)) {\n // The type is attacker-sized (the UR grammar allows an unbounded letter\n // run) — truncate before it reaches a message or error data.\n const shown = type.length > 32 ? `${type.slice(0, 32)}…` : type;\n throw new EraSdkError(\n 'wrong-ur-type',\n `\"${shown}\" is not a wallet export; expected one of ${[...WALLET_UR_TYPES].join(', ')}`,\n { received: shown },\n );\n }\n\n let decoded: CborValue;\n try {\n decoded = cborDecode(cbor);\n } catch (e) {\n throw new EraSdkError('malformed-cbor', `cannot decode wallet UR: ${(e as Error).message}`);\n }\n const root = asMap(decoded);\n if (!root) {\n throw new EraSdkError('malformed-cbor', 'wallet UR is not a CBOR map');\n }\n\n const master = asUint(mapGet(root, 1));\n const list = asArray(mapGet(root, 2));\n if (master === undefined || !list) {\n throw new EraSdkError(\n 'malformed-reply',\n 'wallet UR missing master fingerprint (key 1) or accounts (key 2)',\n );\n }\n\n const entries: RawAccountEntry[] = [];\n for (const item of list) {\n const entry = tryParseEntry(item);\n if (entry) entries.push(entry);\n }\n if (entries.length === 0) {\n throw new EraSdkError(\n 'malformed-reply',\n 'wallet UR carries no account this SDK can derive an address from',\n );\n }\n\n return {\n masterFingerprint: Number(master & 0xffffffffn),\n deviceName: asText(mapGet(root, 3)) ?? null,\n deviceId: asText(mapGet(root, 4)) ?? null,\n deviceVersion: asText(mapGet(root, 5)) ?? null,\n entries,\n };\n}\n\nfunction tryParseEntry(item: CborValue): RawAccountEntry | null {\n const map = asMap(item);\n if (!map) return null;\n const origin = asMap(mapGet(map, 6));\n if (!origin) return null;\n\n const path = parsePathComponents(mapGet(origin, 1));\n const xfp = asUint(mapGet(origin, 2));\n if (!path || path.length === 0 || xfp === undefined || xfp > 0xffffffffn) return null;\n\n const parentFp = asUint(mapGet(map, 8));\n return {\n path,\n xfp: Number(xfp),\n publicKey: asBytes(mapGet(map, 3)) ?? null,\n chainCode: asBytes(mapGet(map, 4)) ?? null,\n parentFingerprint: parentFp !== undefined && parentFp <= 0xffffffffn ? Number(parentFp) : null,\n name: asText(mapGet(map, 9)) ?? null,\n note: asText(mapGet(map, 10)) ?? null,\n };\n}\n","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","import { EraSdkError } from '../core/errors';\nimport type { PathLevel } from '../registry/keypath';\nimport { formatPath, parsePath, pathEquals, xfpToHex } from '../registry/keypath';\nimport type { RawAccountEntry, RawMultiAccounts } from '../registry/multi-accounts';\nimport { parseMultiAccountsUr } from '../registry/multi-accounts';\nimport type { Ur } from '../ur/ur';\nimport {\n btcNestedSegwitAddressFromPublicKey,\n btcP2pkhAddressFromPublicKey,\n btcP2wpkhAddressFromPublicKey,\n derivePublicKey,\n evmAddressFromPublicKey,\n serializeExtendedPublicKey,\n solanaAddressFromPublicKey,\n tronAddressFromPublicKey,\n ZPUB_VERSION,\n} from './derive';\n\n/** Chain family of an exported account, matched by its derivation path — never by the note label. */\nexport type AccountChain = 'evm' | 'btc' | 'solana' | 'tron' | 'unknown';\n\nexport interface AccountKey {\n readonly chain: AccountChain;\n /** Account-level derivation path, e.g. `m/44'/60'/0'`. */\n readonly path: string;\n /**\n * The source fingerprint a `*-sign-request` keypath must carry for this\n * account (lowercase 8-hex). NOT necessarily the master fingerprint.\n */\n readonly xfp: string;\n /** 33-byte compressed secp256k1, or 32-byte Ed25519 (Solana); absent when the export omitted it. */\n readonly publicKey: Uint8Array | undefined;\n readonly chainCode: Uint8Array | undefined;\n readonly name: string | undefined;\n /** Derivation-scheme label (`account.standard`, ...) — display only. */\n readonly note: string | undefined;\n}\n\nexport interface DeviceInfo {\n readonly name: string | undefined;\n readonly id: string | undefined;\n readonly firmwareVersion: string | undefined;\n}\n\nfunction classify(path: readonly PathLevel[]): AccountChain {\n const p0 = path[0];\n const p1 = path[1];\n if (!p0 || !p1 || !p0.hardened || !p1.hardened) return 'unknown';\n if (p0.index === 44 && p1.index === 60) return 'evm';\n if (\n p1.index === 0 &&\n (p0.index === 84 || p0.index === 49 || p0.index === 44 || p0.index === 86)\n ) {\n return 'btc';\n }\n if (p0.index === 44 && p1.index === 501) return 'solana';\n if (p0.index === 44 && p1.index === 195) return 'tron';\n return 'unknown';\n}\n\nfunction withChainCode(entry: RawAccountEntry): Uint8Array {\n if (!entry.chainCode) {\n throw new EraSdkError(\n 'account-not-found',\n `account ${formatPath([...entry.path])} carries no chain code; cannot derive children`,\n );\n }\n return entry.chainCode;\n}\n\n/** The entry's key at the required length, or a typed refusal (derivation only). */\nfunction requireKey(entry: RawAccountEntry, length: number): Uint8Array {\n if (!entry.publicKey || entry.publicKey.length !== length) {\n throw new EraSdkError(\n 'invalid-props',\n `account ${formatPath([...entry.path])} carries no ${length}-byte public key; ` +\n 'xfp lookup still works, address derivation does not',\n );\n }\n return entry.publicKey;\n}\n\n/** EVM view over the linked wallet: one account xpub, addresses derived at `0/index`. */\nexport class EvmAccountView {\n constructor(private readonly entry: RawAccountEntry) {}\n\n get xfp(): string {\n return xfpToHex(this.entry.xfp);\n }\n\n get accountPath(): string {\n return formatPath([...this.entry.path]);\n }\n\n /** Signing path for address `index`: `<account>/0/<index>`. */\n pathFor(index: number): string {\n return `${this.accountPath}/0/${index}`;\n }\n\n deriveAddress(index: number): `0x${string}` {\n return evmAddressFromPublicKey(\n derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index),\n );\n }\n\n xpub(): string {\n return extendedKeyOf(this.entry);\n }\n}\n\nexport type BtcPurpose = 44 | 49 | 84 | 86;\n\n/**\n * Bitcoin view over one exported account. The default is the BIP-84\n * native-segwit account; pass `purpose` to reach the other script types the\n * device exports (44 = legacy P2PKH — the kind the device signs MESSAGES for,\n * 49 = nested segwit, 86 = taproot).\n */\nexport class BtcAccountView {\n constructor(\n private readonly entry: RawAccountEntry,\n private readonly testnet: boolean,\n readonly purpose: BtcPurpose,\n ) {}\n\n get xfp(): string {\n return xfpToHex(this.entry.xfp);\n }\n\n get accountPath(): string {\n return formatPath([...this.entry.path]);\n }\n\n receivePath(index: number): string {\n return `${this.accountPath}/0/${index}`;\n }\n\n changePath(index: number): string {\n return `${this.accountPath}/1/${index}`;\n }\n\n deriveAddress(index: number, options?: { change?: boolean }): string {\n const change = options?.change ? 1 : 0;\n const child = derivePublicKey(\n requireKey(this.entry, 33),\n withChainCode(this.entry),\n change,\n index,\n );\n switch (this.purpose) {\n case 84:\n return btcP2wpkhAddressFromPublicKey(child, this.testnet ? 'tb' : 'bc');\n case 44:\n return btcP2pkhAddressFromPublicKey(child, this.testnet);\n case 49:\n return btcNestedSegwitAddressFromPublicKey(child, this.testnet);\n case 86:\n throw new EraSdkError(\n 'invalid-props',\n 'taproot addresses need the BIP-341 output-key tweak; derive them from xpub() with your Bitcoin library',\n );\n }\n }\n\n xpub(): string {\n return extendedKeyOf(this.entry);\n }\n\n /** SLIP-132 zpub form of the BIP-84 key, for tools that require it. */\n zpub(): string {\n if (this.purpose !== 84) {\n throw new EraSdkError(\n 'invalid-props',\n 'zpub is the SLIP-132 form of the BIP-84 account only',\n );\n }\n return extendedKeyOf(this.entry, ZPUB_VERSION);\n }\n}\n\n/** Tron view: addresses derived at `0/index`. */\nexport class TronAccountView {\n constructor(private readonly entry: RawAccountEntry) {}\n\n get xfp(): string {\n return xfpToHex(this.entry.xfp);\n }\n\n get accountPath(): string {\n return formatPath([...this.entry.path]);\n }\n\n pathFor(index: number): string {\n return `${this.accountPath}/0/${index}`;\n }\n\n deriveAddress(index: number): string {\n return tronAddressFromPublicKey(\n derivePublicKey(requireKey(this.entry, 33), withChainCode(this.entry), 0, index),\n );\n }\n}\n\n/**\n * Solana view: Ed25519 has no public child derivation, so the device\n * pre-derives hardened accounts (`m/44'/501'/idx'`) and each entry IS a\n * signer. The public key, base58, IS the address.\n */\nexport class SolanaAccountView {\n constructor(private readonly entry: RawAccountEntry) {}\n\n get xfp(): string {\n return xfpToHex(this.entry.xfp);\n }\n\n get path(): string {\n return formatPath([...this.entry.path]);\n }\n\n /** The hardened account index (third path level). */\n get index(): number {\n return this.entry.path[2]?.index ?? 0;\n }\n\n get publicKey(): Uint8Array {\n return requireKey(this.entry, 32);\n }\n\n get address(): string {\n return solanaAddressFromPublicKey(requireKey(this.entry, 32));\n }\n}\n\nfunction extendedKeyOf(entry: RawAccountEntry, version?: number): string {\n const chainCode = withChainCode(entry);\n const publicKey = requireKey(entry, 33);\n const last = entry.path[entry.path.length - 1]!;\n const args = {\n depth: entry.path.length,\n parentFingerprint: entry.parentFingerprint ?? 0,\n childNumber: last.hardened ? last.index + 0x80000000 : last.index,\n chainCode,\n publicKey,\n };\n return version === undefined\n ? serializeExtendedPublicKey(args)\n : serializeExtendedPublicKey({ ...args, version });\n}\n\n/**\n * The linked wallet: everything a software wallet extracts from the device's\n * `crypto-multi-accounts` QR. Parse once, store the source UR string, derive\n * addresses locally — the device is not needed again until signing.\n */\nexport class EraAccounts {\n private constructor(\n private readonly raw: RawMultiAccounts,\n readonly sourceUr: string | undefined,\n ) {}\n\n static fromUr(input: Ur | string): EraAccounts {\n const raw = parseMultiAccountsUr(input);\n return new EraAccounts(raw, typeof input === 'string' ? input : input.toString());\n }\n\n /** Master fingerprint, lowercase 8-hex. */\n get masterFingerprint(): string {\n return xfpToHex(this.raw.masterFingerprint);\n }\n\n get device(): DeviceInfo {\n return {\n name: this.raw.deviceName ?? undefined,\n id: this.raw.deviceId ?? undefined,\n firmwareVersion: this.raw.deviceVersion ?? undefined,\n };\n }\n\n get keys(): AccountKey[] {\n return this.raw.entries.map((entry) => ({\n chain: classify(entry.path),\n path: formatPath([...entry.path]),\n xfp: xfpToHex(entry.xfp),\n publicKey: entry.publicKey ?? undefined,\n chainCode: entry.chainCode ?? undefined,\n name: entry.name ?? undefined,\n note: entry.note ?? undefined,\n }));\n }\n\n /**\n * The xfp a sign request must carry for the account whose path exactly\n * equals `accountPath`. Throws `account-not-found` — never a silent zero.\n */\n xfpFor(accountPath: string): string {\n return xfpToHex(this.entryFor(accountPath).xfp);\n }\n\n /** The EVM account (standard `m/44'/60'/...` scheme), if the export carries one. */\n evm(): EvmAccountView | undefined {\n const entry =\n this.raw.entries.find(\n (e) => classify(e.path) === 'evm' && (e.note === null || e.note === 'account.standard'),\n ) ?? this.raw.entries.find((e) => classify(e.path) === 'evm');\n return entry ? new EvmAccountView(entry) : undefined;\n }\n\n /**\n * A Bitcoin account view. Defaults to the BIP-84 native-segwit account;\n * pass `purpose: 44` for the legacy P2PKH account (message signing), 49 for\n * nested segwit, 86 for taproot — if the export carries them.\n */\n btc(options?: { testnet?: boolean; purpose?: BtcPurpose }): BtcAccountView | undefined {\n const purpose = options?.purpose ?? 84;\n const entry = this.raw.entries.find(\n (e) => classify(e.path) === 'btc' && e.path[0]?.index === purpose,\n );\n return entry ? new BtcAccountView(entry, options?.testnet ?? false, purpose) : undefined;\n }\n\n tron(): TronAccountView | undefined {\n const entry = this.raw.entries.find((e) => classify(e.path) === 'tron');\n return entry ? new TronAccountView(entry) : undefined;\n }\n\n /** All pre-derived Solana signers (usually `m/44'/501'/0'..9'`). */\n solana(): SolanaAccountView[] {\n return this.raw.entries\n .filter((e) => classify(e.path) === 'solana' && e.publicKey?.length === 32)\n .map((e) => new SolanaAccountView(e));\n }\n\n private entryFor(accountPath: string): RawAccountEntry {\n const levels = parsePath(accountPath);\n const entry = this.raw.entries.find((e) => pathEquals(e.path, levels));\n if (!entry) {\n throw new EraSdkError(\n 'account-not-found',\n `the linked wallet carries no account at ${accountPath}`,\n { path: accountPath },\n );\n }\n return entry;\n }\n}\n","import type { EraAccounts } from '../accounts/accounts';\nimport { EraAccounts as EraAccountsClass } from '../accounts/accounts';\nimport { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { cbArray, cbMap, cbTag, cbText, cbUint } from '../cbor/model';\nimport type { ChainContext } from '../chains/shared';\nimport { EraSdkError } from '../core/errors';\nimport type { AnimatedUrOptions } from '../qr/animated-ur';\nimport { AnimatedUr } from '../qr/animated-ur';\nimport { keypath304, parsePath } from '../registry/keypath';\nimport { WALLET_UR_TYPES } from '../registry/multi-accounts';\nimport { TypedUrScanner } from '../scan/ur-scanner';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\n\nexport type DerivationCurve = 'secp256k1' | 'ed25519';\nexport type DerivationAlgorithm = 'slip10' | 'bip32ed25519';\n\nexport interface KeyDerivationSchema {\n /** The derivation path to request, e.g. `m/44'/60'/0'`. */\n readonly path: string;\n /** Defaults to `secp256k1`. */\n readonly curve?: DerivationCurve;\n /** Defaults to `slip10`. */\n readonly algo?: DerivationAlgorithm;\n /** Optional chain hint shown by the device. */\n readonly chainType?: string;\n}\n\nexport interface KeyDerivationCallProps {\n readonly schemas: readonly KeyDerivationSchema[];\n readonly origin?: string;\n}\n\n/** The pull-model linking request: display it, then scan the device's account export back. */\nexport interface HardwareCallRequest {\n readonly ur: Ur;\n readonly replyTypes: readonly string[];\n toAnimated(options?: AnimatedUrOptions): AnimatedUr;\n scanner(): TypedUrScanner<EraAccounts>;\n}\n\nconst CURVES: Record<DerivationCurve, number> = { secp256k1: 0, ed25519: 1 };\nconst ALGOS: Record<DerivationAlgorithm, number> = { slip10: 0, bip32ed25519: 1 };\n\n/**\n * Build a `qr-hardware-call` (1201) wrapping a `key-derivation-call` (1301):\n * the WALLET asks the device for specific derivation paths, curves and\n * algorithms instead of accepting whatever the device's sync screen\n * volunteers. The device answers with a `crypto-multi-accounts` export, which\n * closes the loop through `parseAccounts`.\n *\n * Registry shape (Keystone-standard):\n * `1201({1: type=0, 2: 1301({1: [1302({1: 304(keypath), 2: curve, 3: algo, 4?: chainType})...]}), 3?: origin})`.\n */\nexport function generateKeyDerivationCall(\n context: ChainContext,\n props: KeyDerivationCallProps,\n): HardwareCallRequest {\n if (props.schemas.length === 0) {\n throw new EraSdkError('invalid-props', 'at least one derivation schema is required');\n }\n const schemas: CborValue[] = props.schemas.map((schema) => {\n const levels = parsePath(schema.path);\n const entries: [number, CborValue][] = [\n [1, keypath304(levels)],\n [2, cbUint(CURVES[schema.curve ?? 'secp256k1'])],\n [3, cbUint(ALGOS[schema.algo ?? 'slip10'])],\n ];\n if (schema.chainType !== undefined) entries.push([4, cbText(schema.chainType)]);\n return cbTag(1302, cbMap(entries));\n });\n\n const call = cbTag(1301, cbMap([[1, cbArray(schemas)]]));\n const root = cbMap([\n [1, cbUint(0)], // type: KeyDerivation\n [2, call],\n [3, cbText(props.origin ?? context.origin)],\n ]);\n\n const ur = new UrValue('qr-hardware-call', cborEncode(root));\n const replyTypes = [...WALLET_UR_TYPES];\n return {\n ur,\n replyTypes,\n toAnimated: (options?: AnimatedUrOptions) =>\n new AnimatedUr(ur, {\n maxFragmentLength: options?.maxFragmentLength ?? context.maxFragmentLength,\n }),\n scanner: () =>\n new TypedUrScanner<EraAccounts>({ expectedTypes: replyTypes }, (reply) =>\n EraAccountsClass.fromUr(reply),\n ),\n };\n}\n","import type { ChainContext } from './chains/shared';\nimport { toUr } from './chains/shared';\nimport type { AnimatedUrOptions } from './qr/animated-ur';\nimport { AnimatedUr } from './qr/animated-ur';\nimport type { Ur } from './ur/ur';\nimport { Ur as UrValue } from './ur/ur';\n\n/**\n * Escape hatch for UR types this SDK has no dedicated module for (future\n * chains, custom registry items). You bring the CBOR; the SDK brings the UR\n * plumbing, fountain frames and the hardened scanner\n * (`EraConnect.scanner({expectedTypes})`).\n */\nexport class RawModule {\n constructor(private readonly context: ChainContext) {}\n\n /** Wrap raw CBOR bytes in a UR of the given registry type. */\n ur(type: string, cbor: Uint8Array): Ur {\n return new UrValue(type, cbor);\n }\n\n /** Parse a single-part `ur:` string into a Ur. */\n parse(text: string): Ur {\n return toUr(text);\n }\n\n /** Fragment + animate any UR. */\n animate(ur: Ur, options?: AnimatedUrOptions): AnimatedUr {\n return new AnimatedUr(ur, {\n maxFragmentLength: options?.maxFragmentLength ?? this.context.maxFragmentLength,\n });\n }\n}\n","/**\n * ERA Connect SDK — air-gapped UR/QR linking and signing for the ERA\n * hardware wallet.\n *\n * Headless by design: you render the QR codes and own the camera; the SDK\n * owns every byte of the protocol. No network I/O, no Node built-ins,\n * `Uint8Array` end-to-end.\n */\n\nimport type { EraAccounts as EraAccountsType } from './accounts/accounts';\nimport { EraAccounts } from './accounts/accounts';\nimport { BtcChain } from './chains/btc';\nimport { EvmChain } from './chains/evm';\nimport type { ChainContext, EraConnectConfig } from './chains/shared';\nimport { resolveContext } from './chains/shared';\nimport { SolanaChain } from './chains/solana';\nimport { TronChain } from './chains/tron';\nimport type { HardwareCallRequest, KeyDerivationCallProps } from './hardware-call/key-derivation';\nimport { generateKeyDerivationCall } from './hardware-call/key-derivation';\nimport { RawModule } from './raw';\nimport type { UrScannerOptions } from './scan/ur-scanner';\nimport { UrScanner } from './scan/ur-scanner';\nimport type { Ur } from './ur/ur';\n\n/** Timing/size constants of the device's own QR pipeline, for progress UI and timeouts. */\nexport const DeviceProfile = {\n /** What the phone displays to the device: ~200 wire bytes per frame at 8 fps. */\n phoneToDevice: { fragmentBytesOnWire: 200, payloadBytes: 180, frameIntervalMs: 125 },\n /**\n * What the device displays back: 150-byte fragments at 2.5 fps. Receiving\n * is SLOWER than sending — budget scan timeouts accordingly.\n */\n deviceToPhone: { fragmentBytesOnWire: 150, frameIntervalMs: 400 },\n} as const;\n\n/** The SDK facade. Cheap to construct; chain modules are created lazily. */\nexport class EraConnect {\n private readonly context: ChainContext;\n private _evm: EvmChain | undefined;\n private _btc: BtcChain | undefined;\n private _solana: SolanaChain | undefined;\n private _tron: TronChain | undefined;\n private _raw: RawModule | undefined;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n get evm(): EvmChain {\n this._evm ??= new EvmChain(this.context);\n return this._evm;\n }\n\n get btc(): BtcChain {\n this._btc ??= new BtcChain(this.context);\n return this._btc;\n }\n\n get solana(): SolanaChain {\n this._solana ??= new SolanaChain(this.context);\n return this._solana;\n }\n\n get tron(): TronChain {\n this._tron ??= new TronChain(this.context);\n return this._tron;\n }\n\n /** Escape hatch for UR types without a dedicated module. */\n get raw(): RawModule {\n this._raw ??= new RawModule(this.context);\n return this._raw;\n }\n\n /**\n * Linking: parse the device's `crypto-multi-accounts` export (a `Ur` from a\n * scanner, or a single-part `ur:` string).\n */\n parseAccounts(input: Ur | string): EraAccountsType {\n return EraAccounts.fromUr(input);\n }\n\n /**\n * Pull-model linking: ask the device for SPECIFIC derivations\n * (`qr-hardware-call` 1201). The device answers with a\n * `crypto-multi-accounts` export.\n */\n generateKeyDerivationCall(props: KeyDerivationCallProps): HardwareCallRequest {\n return generateKeyDerivationCall(this.context, props);\n }\n\n /** A type-agnostic hardened scanner (linking flows, raw flows). */\n scanner(options?: UrScannerOptions): UrScanner {\n return new UrScanner(options);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public types & modules\n// ---------------------------------------------------------------------------\n\nexport type { AccountChain, AccountKey, BtcPurpose, DeviceInfo } from './accounts/accounts';\nexport {\n BtcAccountView,\n EraAccounts,\n EvmAccountView,\n SolanaAccountView,\n TronAccountView,\n} from './accounts/accounts';\nexport type {\n BtcMessageSignatureResult,\n BtcMessageSignRequestProps,\n BtcPsbtResult,\n BtcPsbtSignRequestProps,\n} from './chains/btc';\nexport { BtcChain } from './chains/btc';\nexport type { EvmSignatureResult, EvmSignRequestProps } from './chains/evm';\nexport { EvmChain, EvmDataType } from './chains/evm';\nexport type {\n ChainContext,\n EraConnectConfig,\n ExpectedReply,\n SignRequest,\n} from './chains/shared';\nexport { DEFAULT_ORIGIN } from './chains/shared';\nexport type { SolSignatureResult, SolSignRequestProps } from './chains/solana';\nexport { SolanaChain, SolSignType } from './chains/solana';\nexport type { TronLatestBlock, TronSignatureResult, TronSignRequestProps } from './chains/tron';\nexport { TronChain } from './chains/tron';\n// UTF-8 helpers that work on every Hermes version (TextEncoder does not):\nexport { utf8Decode, utf8Encode } from './core/bytes';\nexport type { EraErrorCode } from './core/errors';\nexport { EraSdkError } from './core/errors';\nexport type { RandomBytesFn } from './core/rand';\nexport type {\n DerivationAlgorithm,\n DerivationCurve,\n HardwareCallRequest,\n KeyDerivationCallProps,\n KeyDerivationSchema,\n} from './hardware-call/key-derivation';\nexport type { AnimatedUrOptions } from './qr/animated-ur';\nexport { AnimatedUr, DEFAULT_FRAGMENT_LENGTH } from './qr/animated-ur';\nexport { RawModule } from './raw';\nexport type { ScanFeedResult, ScanRejection, UrScannerOptions } from './scan/ur-scanner';\nexport { TypedUrScanner, UrScanner } from './scan/ur-scanner';\nexport { UrLimits } from './ur/limits';\nexport { Ur } from './ur/ur';\n"],"mappings":"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"}