@hwlt/era-connect 0.3.0 → 0.5.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.
- package/README.md +8 -14
- package/bch/package.json +6 -0
- package/cosmos/package.json +6 -0
- package/dist/bch-CK6dKGQA.d.ts +74 -0
- package/dist/bch-CpLACx0j.cjs +139 -0
- package/dist/bch-CpLACx0j.cjs.map +1 -0
- package/dist/bch-DHsIVJqK.d.cts +74 -0
- package/dist/bch-dMESlQfv.js +134 -0
- package/dist/bch-dMESlQfv.js.map +1 -0
- package/dist/bch.cjs +13 -0
- package/dist/bch.d.cts +26 -0
- package/dist/bch.d.ts +26 -0
- package/dist/bch.js +4 -0
- package/dist/{btc-VyJKXq7d.js → btc-BmVgvvBd.js} +17 -8
- package/dist/btc-BmVgvvBd.js.map +1 -0
- package/dist/{btc-Fr6Jz4Fi.cjs → btc-BxNww6kW.cjs} +20 -11
- package/dist/btc-BxNww6kW.cjs.map +1 -0
- package/dist/{btc-DfQ0q79G.d.ts → btc-uzt0uC-Q.d.ts} +15 -4
- package/dist/{btc-Dn6_Y12c.d.cts → btc-wogJ4INA.d.cts} +15 -4
- package/dist/btc.cjs +2 -2
- package/dist/btc.d.cts +1 -1
- package/dist/btc.d.ts +1 -1
- package/dist/btc.js +2 -2
- package/dist/{cardano-yuOygqwp.js → cardano-BCT55gwf.js} +3 -2
- package/dist/{cardano-yuOygqwp.js.map → cardano-BCT55gwf.js.map} +1 -1
- package/dist/{cardano-DP6U_K1J.cjs → cardano-CzYswGzK.cjs} +5 -4
- package/dist/{cardano-DP6U_K1J.cjs.map → cardano-CzYswGzK.cjs.map} +1 -1
- package/dist/cardano.cjs +2 -2
- package/dist/cardano.js +2 -2
- package/dist/cashaddr-BIzawizX.js +134 -0
- package/dist/cashaddr-BIzawizX.js.map +1 -0
- package/dist/cashaddr-Ci0_8ITN.cjs +151 -0
- package/dist/cashaddr-Ci0_8ITN.cjs.map +1 -0
- package/dist/cosmos-BYrhIqRk.d.cts +77 -0
- package/dist/cosmos-DDsgtUki.cjs +113 -0
- package/dist/cosmos-DDsgtUki.cjs.map +1 -0
- package/dist/cosmos-DqyjA6lg.d.ts +77 -0
- package/dist/cosmos-jUHNxgWC.js +102 -0
- package/dist/cosmos-jUHNxgWC.js.map +1 -0
- package/dist/cosmos.cjs +10 -0
- package/dist/cosmos.d.cts +3 -0
- package/dist/cosmos.d.ts +3 -0
- package/dist/cosmos.js +3 -0
- package/dist/{derive-C4JdycUh.js → derive-00JUOkmn.js} +14 -3
- package/dist/derive-00JUOkmn.js.map +1 -0
- package/dist/{derive-CuILJRPT.cjs → derive-BuNsfWlg.cjs} +25 -2
- package/dist/derive-BuNsfWlg.cjs.map +1 -0
- package/dist/{evm-kJb3-oiR.js → evm-CI1cuZsp.js} +3 -2
- package/dist/{evm-kJb3-oiR.js.map → evm-CI1cuZsp.js.map} +1 -1
- package/dist/{evm-BHj_2OTG.cjs → evm-yfKOc2dy.cjs} +6 -5
- package/dist/{evm-BHj_2OTG.cjs.map → evm-yfKOc2dy.cjs.map} +1 -1
- package/dist/evm.cjs +2 -2
- package/dist/evm.js +2 -2
- package/dist/gzip-CLzDX7AZ.cjs +79 -0
- package/dist/gzip-CLzDX7AZ.cjs.map +1 -0
- package/dist/gzip-DyZLtgJJ.js +68 -0
- package/dist/gzip-DyZLtgJJ.js.map +1 -0
- package/dist/index.cjs +120 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -3
- package/dist/index.d.ts +50 -3
- package/dist/index.js +90 -9
- package/dist/index.js.map +1 -1
- package/dist/keypath-Bvv_cfHt.js +75 -0
- package/dist/keypath-Bvv_cfHt.js.map +1 -0
- package/dist/keypath-pzm_YIfN.cjs +116 -0
- package/dist/keypath-pzm_YIfN.cjs.map +1 -0
- package/dist/{messages-17Oup0-Z.js → messages--XbVef_k.js} +39 -3
- package/dist/messages--XbVef_k.js.map +1 -0
- package/dist/{messages-BzcdWlg1.cjs → messages-orAQ52CI.cjs} +44 -2
- package/dist/messages-orAQ52CI.cjs.map +1 -0
- package/dist/{shared-B8Wc7ViU.js → shared-Bbgejrus.js} +2 -73
- package/dist/shared-Bbgejrus.js.map +1 -0
- package/dist/{shared-nISrEktU.cjs → shared-Cu2yynP9.cjs} +13 -114
- package/dist/shared-Cu2yynP9.cjs.map +1 -0
- package/dist/{solana-DdEn24X4.cjs → solana-BoQBy0hu.cjs} +6 -5
- package/dist/{solana-DdEn24X4.cjs.map → solana-BoQBy0hu.cjs.map} +1 -1
- package/dist/{solana-C7JQEAec.js → solana-BukH3AI3.js} +3 -2
- package/dist/{solana-C7JQEAec.js.map → solana-BukH3AI3.js.map} +1 -1
- package/dist/solana.cjs +2 -2
- package/dist/solana.js +2 -2
- package/dist/sui-6WX6VPlW.d.cts +49 -0
- package/dist/sui-BtbPG6Xt.js +71 -0
- package/dist/sui-BtbPG6Xt.js.map +1 -0
- package/dist/sui-CYRn331O.cjs +82 -0
- package/dist/sui-CYRn331O.cjs.map +1 -0
- package/dist/sui-DI0ruW7E.d.ts +49 -0
- package/dist/sui.cjs +10 -0
- package/dist/sui.d.cts +3 -0
- package/dist/sui.d.ts +3 -0
- package/dist/sui.js +3 -0
- package/dist/{ton-5Uvi5ifg.js → ton-BSPKU5B9.js} +3 -2
- package/dist/{ton-5Uvi5ifg.js.map → ton-BSPKU5B9.js.map} +1 -1
- package/dist/{ton-DUJGXdGa.cjs → ton-CI2s9puH.cjs} +6 -5
- package/dist/{ton-DUJGXdGa.cjs.map → ton-CI2s9puH.cjs.map} +1 -1
- package/dist/ton.cjs +2 -2
- package/dist/ton.js +2 -2
- package/dist/{tron-Bo9HnvVE.js → tron-BpUEYTPT.js} +5 -67
- package/dist/tron-BpUEYTPT.js.map +1 -0
- package/dist/{tron-CQIEqjCA.cjs → tron-DYPOg5cm.cjs} +10 -72
- package/dist/{tron-Bo9HnvVE.js.map → tron-DYPOg5cm.cjs.map} +1 -1
- package/dist/tron.cjs +3 -3
- package/dist/tron.js +3 -3
- package/dist/verify.cjs +414 -24
- package/dist/verify.cjs.map +1 -1
- package/dist/verify.d.cts +120 -1
- package/dist/verify.d.ts +120 -1
- package/dist/verify.js +408 -24
- package/dist/verify.js.map +1 -1
- package/dist/xrp-BXAeK4iH.d.cts +32 -0
- package/dist/xrp-BrHXUnX5.cjs +52 -0
- package/dist/xrp-BrHXUnX5.cjs.map +1 -0
- package/dist/xrp-C8LJO5b-.js +47 -0
- package/dist/xrp-C8LJO5b-.js.map +1 -0
- package/dist/xrp-DqCXGYEk.d.ts +32 -0
- package/dist/xrp.cjs +9 -0
- package/dist/xrp.d.cts +3 -0
- package/dist/xrp.d.ts +3 -0
- package/dist/xrp.js +3 -0
- package/package.json +49 -1
- package/sui/package.json +6 -0
- package/xrp/package.json +6 -0
- package/dist/btc-Fr6Jz4Fi.cjs.map +0 -1
- package/dist/btc-VyJKXq7d.js.map +0 -1
- package/dist/derive-C4JdycUh.js.map +0 -1
- package/dist/derive-CuILJRPT.cjs.map +0 -1
- package/dist/messages-17Oup0-Z.js.map +0 -1
- package/dist/messages-BzcdWlg1.cjs.map +0 -1
- package/dist/shared-B8Wc7ViU.js.map +0 -1
- package/dist/shared-nISrEktU.cjs.map +0 -1
- package/dist/tron-CQIEqjCA.cjs.map +0 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { A as utf8Encode, B as cbMap, H as cbText, K as EraSdkError, L as cbArray, N as asBytes, U as cbUint, V as cbTag, W as mapGet, _ as Ur, c as resolveRequestId, h as normalizeRequestId, i as requireRequestIdEcho, l as toUr, n as makeSignRequest, o as requireUrType, r as requireReplyMap, s as resolveContext, x as cborEncode, z as cbBytes } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { i as parsePath, n as keypath304, r as normalizeXfp } from "./keypath-Bvv_cfHt.js";
|
|
3
|
+
//#region src/chains/cosmos.ts
|
|
4
|
+
/** `cosmos-sign-request` dataType (CBOR key 3). */
|
|
5
|
+
const CosmosDataType = {
|
|
6
|
+
/** SIGN_MODE_LEGACY_AMINO_JSON — `signData` is the canonical JSON (UTF-8 bytes). */
|
|
7
|
+
amino: 1,
|
|
8
|
+
/** SIGN_MODE_DIRECT — `signData` is the protobuf-encoded SignDoc. */
|
|
9
|
+
direct: 2,
|
|
10
|
+
/** SIGN_MODE_TEXTUAL (rare). */
|
|
11
|
+
textual: 3,
|
|
12
|
+
/** ADR-036 arbitrary-message signing. */
|
|
13
|
+
message: 4
|
|
14
|
+
};
|
|
15
|
+
const COSMOS_REPLY_TYPES = ["cosmos-signature"];
|
|
16
|
+
const ETHERMINT_REPLY_TYPES = ["evm-signature"];
|
|
17
|
+
/** EvmSignDataType on the wire: 2 = Amino SignDoc, 3 = Direct SignDoc. */
|
|
18
|
+
const ETHERMINT_WIRE_TYPE = {
|
|
19
|
+
1: 2,
|
|
20
|
+
2: 3
|
|
21
|
+
};
|
|
22
|
+
var CosmosChain = class {
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.context = resolveContext(config);
|
|
25
|
+
}
|
|
26
|
+
/** Build a `cosmos-sign-request` (4101). Reply: `cosmos-signature` (4102). */
|
|
27
|
+
generateSignRequest(props) {
|
|
28
|
+
const requestId = resolveRequestId(this.context, props.requestId);
|
|
29
|
+
const path = parsePath(props.path);
|
|
30
|
+
const xfp = normalizeXfp(props.xfp);
|
|
31
|
+
if (props.signData.length === 0) throw new EraSdkError("invalid-props", "signData must not be empty");
|
|
32
|
+
const entries = [
|
|
33
|
+
[1, cbTag(37, cbBytes(requestId))],
|
|
34
|
+
[2, cbBytes(props.signData)],
|
|
35
|
+
[3, cbUint(props.dataType)],
|
|
36
|
+
[4, cbArray([keypath304(path, xfp)])]
|
|
37
|
+
];
|
|
38
|
+
if (props.address !== void 0) entries.push([5, cbArray([cbText(props.address)])]);
|
|
39
|
+
entries.push([6, cbText(props.origin ?? this.context.origin)]);
|
|
40
|
+
const ur = new Ur("cosmos-sign-request", cborEncode(cbMap(entries)));
|
|
41
|
+
return makeSignRequest({
|
|
42
|
+
ur,
|
|
43
|
+
requestId,
|
|
44
|
+
replyTypes: COSMOS_REPLY_TYPES,
|
|
45
|
+
context: this.context,
|
|
46
|
+
parse: (reply) => parseCosmosSignature(reply, requestId, [...COSMOS_REPLY_TYPES])
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build an `evm-sign-request` (4101, the Ethermint shape) for
|
|
51
|
+
* Injective/Evmos/Dymension-style chains. Reply: `evm-signature` (4102).
|
|
52
|
+
* The digest on these chains is keccak-256 — see `verifyCosmosSignature`.
|
|
53
|
+
*/
|
|
54
|
+
generateEthermintSignRequest(props) {
|
|
55
|
+
const requestId = resolveRequestId(this.context, props.requestId);
|
|
56
|
+
const path = parsePath(props.path);
|
|
57
|
+
const xfp = normalizeXfp(props.xfp);
|
|
58
|
+
if (props.signData.length === 0) throw new EraSdkError("invalid-props", "signData must not be empty");
|
|
59
|
+
const wireType = ETHERMINT_WIRE_TYPE[props.dataType];
|
|
60
|
+
if (wireType === void 0) throw new EraSdkError("invalid-props", "Ethermint requests are Amino or Direct only");
|
|
61
|
+
const entries = [
|
|
62
|
+
[1, cbTag(37, cbBytes(requestId))],
|
|
63
|
+
[2, cbBytes(props.signData)],
|
|
64
|
+
[3, cbUint(wireType)],
|
|
65
|
+
[4, cbUint(0)],
|
|
66
|
+
[5, keypath304(path, xfp)]
|
|
67
|
+
];
|
|
68
|
+
if (props.address !== void 0) entries.push([6, cbBytes(utf8Encode(props.address))]);
|
|
69
|
+
entries.push([7, cbText(props.origin ?? this.context.origin)]);
|
|
70
|
+
const ur = new Ur("evm-sign-request", cborEncode(cbMap(entries)));
|
|
71
|
+
return makeSignRequest({
|
|
72
|
+
ur,
|
|
73
|
+
requestId,
|
|
74
|
+
replyTypes: ETHERMINT_REPLY_TYPES,
|
|
75
|
+
context: this.context,
|
|
76
|
+
parse: (reply) => parseCosmosSignature(reply, requestId, [...ETHERMINT_REPLY_TYPES])
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Parse a `cosmos-signature`/`evm-signature` standalone. */
|
|
80
|
+
parseSignature(input, expect) {
|
|
81
|
+
return parseCosmosSignature(toUr(input), expect?.requestId === void 0 ? void 0 : normalizeRequestId(expect.requestId), ["cosmos-signature", "evm-signature"]);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
CosmosChain.DataType = CosmosDataType;
|
|
85
|
+
function parseCosmosSignature(ur, expectedRequestId, replyTypes) {
|
|
86
|
+
requireUrType(ur, replyTypes, "cosmos-signature");
|
|
87
|
+
const map = requireReplyMap(ur, ur.type);
|
|
88
|
+
const requestId = requireRequestIdEcho(map, 1, expectedRequestId, ur.type);
|
|
89
|
+
const signature = asBytes(mapGet(map, 2));
|
|
90
|
+
if (!signature || signature.length !== 64) throw new EraSdkError("malformed-reply", `${ur.type} signature is ${signature?.length ?? 0} bytes, expected 64 (compact r||s)`);
|
|
91
|
+
const publicKey = asBytes(mapGet(map, 3));
|
|
92
|
+
if (publicKey !== void 0 && publicKey.length !== 33) throw new EraSdkError("malformed-reply", `${ur.type} public key is not 33 bytes`);
|
|
93
|
+
return {
|
|
94
|
+
requestId,
|
|
95
|
+
signature,
|
|
96
|
+
publicKey
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
export { CosmosDataType as n, CosmosChain as t };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=cosmos-jUHNxgWC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosmos-jUHNxgWC.js","names":["UrValue"],"sources":["../src/chains/cosmos.ts"],"sourcesContent":["import { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { asBytes, cbArray, cbBytes, cbMap, cbTag, cbText, cbUint, mapGet } from '../cbor/model';\nimport { utf8Encode } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { normalizeRequestId } from '../core/rand';\nimport { keypath304, normalizeXfp, parsePath } from '../registry/keypath';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\nimport type { ChainContext, EraConnectConfig, ExpectedReply, SignRequest } from './shared';\nimport {\n makeSignRequest,\n requireReplyMap,\n requireRequestIdEcho,\n requireUrType,\n resolveContext,\n resolveRequestId,\n toUr,\n} from './shared';\n\n/** `cosmos-sign-request` dataType (CBOR key 3). */\nexport const CosmosDataType = {\n /** SIGN_MODE_LEGACY_AMINO_JSON — `signData` is the canonical JSON (UTF-8 bytes). */\n amino: 1,\n /** SIGN_MODE_DIRECT — `signData` is the protobuf-encoded SignDoc. */\n direct: 2,\n /** SIGN_MODE_TEXTUAL (rare). */\n textual: 3,\n /** ADR-036 arbitrary-message signing. */\n message: 4,\n} as const;\nexport type CosmosDataType = (typeof CosmosDataType)[keyof typeof CosmosDataType];\n\nexport interface CosmosSignRequestProps {\n readonly requestId?: Uint8Array | string;\n /** SignDoc bytes: canonical Amino JSON (UTF-8) or protobuf SignDoc. */\n readonly signData: Uint8Array;\n readonly dataType: CosmosDataType;\n /** Full signing path, e.g. `m/44'/118'/0'/0/0`. */\n readonly path: string;\n readonly xfp: string | number;\n /** Bech32 signer address — device display. */\n readonly address?: string;\n readonly origin?: string;\n}\n\n/**\n * Ethermint-family chains (Injective, Evmos, Dymension, …) sign with\n * keccak-256 over Ethereum-style keys (`m/44'/60'/...`) and travel as an\n * `evm-sign-request` instead.\n */\nexport interface EthermintSignRequestProps {\n readonly requestId?: Uint8Array | string;\n readonly signData: Uint8Array;\n /** Amino or Direct — the SignDoc encoding. */\n readonly dataType: typeof CosmosDataType.amino | typeof CosmosDataType.direct;\n /** e.g. `m/44'/60'/0'/0/0`. */\n readonly path: string;\n readonly xfp: string | number;\n /** The `0x…` signer address string — travels as its ASCII bytes on this wire. */\n readonly address?: string;\n readonly origin?: string;\n}\n\nexport interface CosmosSignatureResult {\n readonly requestId: Uint8Array;\n /** 64-byte compact secp256k1 signature (r || s). */\n readonly signature: Uint8Array;\n /** 33-byte compressed public key (absent on the `evm-signature` reply shape). */\n readonly publicKey: Uint8Array | undefined;\n}\n\nconst COSMOS_REPLY_TYPES = ['cosmos-signature'] as const;\nconst ETHERMINT_REPLY_TYPES = ['evm-signature'] as const;\n\n/** EvmSignDataType on the wire: 2 = Amino SignDoc, 3 = Direct SignDoc. */\nconst ETHERMINT_WIRE_TYPE: Record<number, number> = { 1: 2, 2: 3 };\n\nexport class CosmosChain {\n static readonly DataType = CosmosDataType;\n\n private readonly context: ChainContext;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n /** Build a `cosmos-sign-request` (4101). Reply: `cosmos-signature` (4102). */\n generateSignRequest(props: CosmosSignRequestProps): SignRequest<CosmosSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n if (props.signData.length === 0) {\n throw new EraSdkError('invalid-props', 'signData must not be empty');\n }\n\n const entries: [number, CborValue][] = [\n [1, cbTag(37, cbBytes(requestId))],\n [2, cbBytes(props.signData)],\n [3, cbUint(props.dataType)],\n [4, cbArray([keypath304(path, xfp)])],\n ];\n if (props.address !== undefined) entries.push([5, cbArray([cbText(props.address)])]);\n entries.push([6, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('cosmos-sign-request', cborEncode(cbMap(entries)));\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: COSMOS_REPLY_TYPES,\n context: this.context,\n parse: (reply) => parseCosmosSignature(reply, requestId, [...COSMOS_REPLY_TYPES]),\n });\n }\n\n /**\n * Build an `evm-sign-request` (4101, the Ethermint shape) for\n * Injective/Evmos/Dymension-style chains. Reply: `evm-signature` (4102).\n * The digest on these chains is keccak-256 — see `verifyCosmosSignature`.\n */\n generateEthermintSignRequest(\n props: EthermintSignRequestProps,\n ): SignRequest<CosmosSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n if (props.signData.length === 0) {\n throw new EraSdkError('invalid-props', 'signData must not be empty');\n }\n const wireType = ETHERMINT_WIRE_TYPE[props.dataType];\n if (wireType === undefined) {\n throw new EraSdkError('invalid-props', 'Ethermint requests are Amino or Direct only');\n }\n\n const entries: [number, CborValue][] = [\n [1, cbTag(37, cbBytes(requestId))],\n [2, cbBytes(props.signData)],\n [3, cbUint(wireType)],\n [4, cbUint(0)], // customChainId — 0, the chain resolves from the SignDoc\n [5, keypath304(path, xfp)],\n ];\n if (props.address !== undefined) {\n entries.push([6, cbBytes(utf8Encode(props.address))]); // ASCII of the 0x string\n }\n entries.push([7, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('evm-sign-request', cborEncode(cbMap(entries)));\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: ETHERMINT_REPLY_TYPES,\n context: this.context,\n parse: (reply) => parseCosmosSignature(reply, requestId, [...ETHERMINT_REPLY_TYPES]),\n });\n }\n\n /** Parse a `cosmos-signature`/`evm-signature` standalone. */\n parseSignature(input: Ur | string, expect?: ExpectedReply): CosmosSignatureResult {\n return parseCosmosSignature(\n toUr(input),\n expect?.requestId === undefined ? undefined : normalizeRequestId(expect.requestId),\n ['cosmos-signature', 'evm-signature'],\n );\n }\n}\n\nfunction parseCosmosSignature(\n ur: Ur,\n expectedRequestId: Uint8Array | undefined,\n replyTypes: string[],\n): CosmosSignatureResult {\n requireUrType(ur, replyTypes, 'cosmos-signature');\n const map = requireReplyMap(ur, ur.type);\n const requestId = requireRequestIdEcho(map, 1, expectedRequestId, ur.type);\n const signature = asBytes(mapGet(map, 2));\n if (!signature || signature.length !== 64) {\n throw new EraSdkError(\n 'malformed-reply',\n `${ur.type} signature is ${signature?.length ?? 0} bytes, expected 64 (compact r||s)`,\n );\n }\n const publicKey = asBytes(mapGet(map, 3));\n if (publicKey !== undefined && publicKey.length !== 33) {\n throw new EraSdkError('malformed-reply', `${ur.type} public key is not 33 bytes`);\n }\n return { requestId, signature, publicKey };\n}\n"],"mappings":"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"}
|
package/dist/cosmos.cjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_shared = require("./shared-Cu2yynP9.cjs");
|
|
3
|
+
const require_cosmos = require("./cosmos-DDsgtUki.cjs");
|
|
4
|
+
exports.AnimatedUr = require_shared.AnimatedUr;
|
|
5
|
+
exports.CosmosChain = require_cosmos.CosmosChain;
|
|
6
|
+
exports.CosmosDataType = require_cosmos.CosmosDataType;
|
|
7
|
+
exports.EraSdkError = require_shared.EraSdkError;
|
|
8
|
+
exports.TypedUrScanner = require_shared.TypedUrScanner;
|
|
9
|
+
exports.Ur = require_shared.Ur;
|
|
10
|
+
exports.UrScanner = require_shared.UrScanner;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { _ as Ur, a as SignRequest, c as TypedUrScanner, d as EraErrorCode, f as EraSdkError, i as ExpectedReply, l as UrScanner, p as AnimatedUr, r as EraConnectConfig } from "./shared-CI8zhQiE.cjs";
|
|
2
|
+
import { a as EthermintSignRequestProps, i as CosmosSignatureResult, n as CosmosDataType, r as CosmosSignRequestProps, t as CosmosChain } from "./cosmos-BYrhIqRk.cjs";
|
|
3
|
+
export { AnimatedUr, CosmosChain, CosmosDataType, type CosmosSignRequestProps, type CosmosSignatureResult, type EraConnectConfig, type EraErrorCode, EraSdkError, type EthermintSignRequestProps, type ExpectedReply, type SignRequest, TypedUrScanner, Ur, UrScanner };
|
package/dist/cosmos.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { _ as Ur, a as SignRequest, c as TypedUrScanner, d as EraErrorCode, f as EraSdkError, i as ExpectedReply, l as UrScanner, p as AnimatedUr, r as EraConnectConfig } from "./shared-CI8zhQiE.js";
|
|
2
|
+
import { a as EthermintSignRequestProps, i as CosmosSignatureResult, n as CosmosDataType, r as CosmosSignRequestProps, t as CosmosChain } from "./cosmos-DqyjA6lg.js";
|
|
3
|
+
export { AnimatedUr, CosmosChain, CosmosDataType, type CosmosSignRequestProps, type CosmosSignatureResult, type EraConnectConfig, type EraErrorCode, EraSdkError, type EthermintSignRequestProps, type ExpectedReply, type SignRequest, TypedUrScanner, Ur, UrScanner };
|
package/dist/cosmos.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { K as EraSdkError, _ as Ur, d as UrScanner, f as AnimatedUr, u as TypedUrScanner } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { n as CosmosDataType, t as CosmosChain } from "./cosmos-jUHNxgWC.js";
|
|
3
|
+
export { AnimatedUr, CosmosChain, CosmosDataType, EraSdkError, TypedUrScanner, Ur, UrScanner };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as EraSdkError, O as u32be, T as concatBytes, w as bytesToHex } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { r as encodeCashAddr } from "./cashaddr-BIzawizX.js";
|
|
2
3
|
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
4
|
+
import { blake2b } from "@noble/hashes/blake2b";
|
|
3
5
|
import { ripemd160 } from "@noble/hashes/ripemd160";
|
|
4
6
|
import { sha256, sha512 } from "@noble/hashes/sha2";
|
|
5
7
|
import { keccak_256 } from "@noble/hashes/sha3";
|
|
@@ -36,6 +38,10 @@ function evmAddressFromPublicKey(publicKey33) {
|
|
|
36
38
|
function hash160(data) {
|
|
37
39
|
return ripemd160(sha256(data));
|
|
38
40
|
}
|
|
41
|
+
/** CashAddr P2PKH address (Bitcoin Cash) from a compressed public key. */
|
|
42
|
+
function bchAddressFromPublicKey(publicKey33, options) {
|
|
43
|
+
return encodeCashAddr("p2pkh", hash160(publicKey33), { withPrefix: options?.withPrefix });
|
|
44
|
+
}
|
|
39
45
|
/** P2WPKH (witness v0) bech32 address. */
|
|
40
46
|
function btcP2wpkhAddressFromPublicKey(publicKey33, hrp = "bc") {
|
|
41
47
|
return bech32.encode(hrp, [0, ...bech32.toWords(hash160(publicKey33))]);
|
|
@@ -54,6 +60,11 @@ function tronAddressFromPublicKey(publicKey33) {
|
|
|
54
60
|
const hash = keccak_256(uncompressed(publicKey33).slice(1));
|
|
55
61
|
return base58check.encode(concatBytes(new Uint8Array([65]), hash.slice(12)));
|
|
56
62
|
}
|
|
63
|
+
/** `0x` Sui address: BLAKE2b-256 of the scheme flag (0x00 = Ed25519) plus the public key. */
|
|
64
|
+
function suiAddressFromPublicKey(publicKey32) {
|
|
65
|
+
const digest = blake2b(concatBytes(new Uint8Array([0]), publicKey32), { dkLen: 32 });
|
|
66
|
+
return `0x${bytesToHex(digest)}`;
|
|
67
|
+
}
|
|
57
68
|
/** A Solana address IS the Ed25519 public key, base58. */
|
|
58
69
|
function solanaAddressFromPublicKey(publicKey32) {
|
|
59
70
|
return base58.encode(publicKey32);
|
|
@@ -112,6 +123,6 @@ function cardanoSoftDerivePath(publicKey, chainCode, indices) {
|
|
|
112
123
|
return node.publicKey;
|
|
113
124
|
}
|
|
114
125
|
//#endregion
|
|
115
|
-
export {
|
|
126
|
+
export { btcP2wpkhAddressFromPublicKey as a, evmAddressFromPublicKey as c, suiAddressFromPublicKey as d, tronAddressFromPublicKey as f, btcP2pkhAddressFromPublicKey as i, serializeExtendedPublicKey as l, bchAddressFromPublicKey as n, cardanoSoftDerivePath as o, btcNestedSegwitAddressFromPublicKey as r, derivePublicKey as s, ZPUB_VERSION as t, solanaAddressFromPublicKey as u };
|
|
116
127
|
|
|
117
|
-
//# sourceMappingURL=derive-
|
|
128
|
+
//# sourceMappingURL=derive-00JUOkmn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-00JUOkmn.js","names":[],"sources":["../src/accounts/derive.ts"],"sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1';\nimport { blake2b } from '@noble/hashes/blake2b';\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 { encodeCashAddr } from '../chains/cashaddr';\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/** CashAddr P2PKH address (Bitcoin Cash) from a compressed public key. */\nexport function bchAddressFromPublicKey(\n publicKey33: Uint8Array,\n options?: { withPrefix?: boolean },\n): string {\n return encodeCashAddr('p2pkh', hash160(publicKey33), { withPrefix: options?.withPrefix });\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/** `0x` Sui address: BLAKE2b-256 of the scheme flag (0x00 = Ed25519) plus the public key. */\nexport function suiAddressFromPublicKey(publicKey32: Uint8Array): string {\n const digest = blake2b(concatBytes(new Uint8Array([0x00]), publicKey32), { dkLen: 32 });\n return `0x${bytesToHex(digest)}`;\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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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const require_shared = require("./shared-
|
|
1
|
+
const require_shared = require("./shared-Cu2yynP9.cjs");
|
|
2
|
+
const require_cashaddr = require("./cashaddr-Ci0_8ITN.cjs");
|
|
2
3
|
let _noble_curves_secp256k1 = require("@noble/curves/secp256k1");
|
|
4
|
+
let _noble_hashes_blake2b = require("@noble/hashes/blake2b");
|
|
3
5
|
let _noble_hashes_ripemd160 = require("@noble/hashes/ripemd160");
|
|
4
6
|
let _noble_hashes_sha2 = require("@noble/hashes/sha2");
|
|
5
7
|
let _noble_hashes_sha3 = require("@noble/hashes/sha3");
|
|
@@ -36,6 +38,10 @@ function evmAddressFromPublicKey(publicKey33) {
|
|
|
36
38
|
function hash160(data) {
|
|
37
39
|
return (0, _noble_hashes_ripemd160.ripemd160)((0, _noble_hashes_sha2.sha256)(data));
|
|
38
40
|
}
|
|
41
|
+
/** CashAddr P2PKH address (Bitcoin Cash) from a compressed public key. */
|
|
42
|
+
function bchAddressFromPublicKey(publicKey33, options) {
|
|
43
|
+
return require_cashaddr.encodeCashAddr("p2pkh", hash160(publicKey33), { withPrefix: options?.withPrefix });
|
|
44
|
+
}
|
|
39
45
|
/** P2WPKH (witness v0) bech32 address. */
|
|
40
46
|
function btcP2wpkhAddressFromPublicKey(publicKey33, hrp = "bc") {
|
|
41
47
|
return _scure_base.bech32.encode(hrp, [0, ..._scure_base.bech32.toWords(hash160(publicKey33))]);
|
|
@@ -54,6 +60,11 @@ function tronAddressFromPublicKey(publicKey33) {
|
|
|
54
60
|
const hash = (0, _noble_hashes_sha3.keccak_256)(uncompressed(publicKey33).slice(1));
|
|
55
61
|
return base58check.encode(require_shared.concatBytes(new Uint8Array([65]), hash.slice(12)));
|
|
56
62
|
}
|
|
63
|
+
/** `0x` Sui address: BLAKE2b-256 of the scheme flag (0x00 = Ed25519) plus the public key. */
|
|
64
|
+
function suiAddressFromPublicKey(publicKey32) {
|
|
65
|
+
const digest = (0, _noble_hashes_blake2b.blake2b)(require_shared.concatBytes(new Uint8Array([0]), publicKey32), { dkLen: 32 });
|
|
66
|
+
return `0x${require_shared.bytesToHex(digest)}`;
|
|
67
|
+
}
|
|
57
68
|
/** A Solana address IS the Ed25519 public key, base58. */
|
|
58
69
|
function solanaAddressFromPublicKey(publicKey32) {
|
|
59
70
|
return _scure_base.base58.encode(publicKey32);
|
|
@@ -118,6 +129,12 @@ Object.defineProperty(exports, "ZPUB_VERSION", {
|
|
|
118
129
|
return ZPUB_VERSION;
|
|
119
130
|
}
|
|
120
131
|
});
|
|
132
|
+
Object.defineProperty(exports, "bchAddressFromPublicKey", {
|
|
133
|
+
enumerable: true,
|
|
134
|
+
get: function() {
|
|
135
|
+
return bchAddressFromPublicKey;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
121
138
|
Object.defineProperty(exports, "btcNestedSegwitAddressFromPublicKey", {
|
|
122
139
|
enumerable: true,
|
|
123
140
|
get: function() {
|
|
@@ -166,6 +183,12 @@ Object.defineProperty(exports, "solanaAddressFromPublicKey", {
|
|
|
166
183
|
return solanaAddressFromPublicKey;
|
|
167
184
|
}
|
|
168
185
|
});
|
|
186
|
+
Object.defineProperty(exports, "suiAddressFromPublicKey", {
|
|
187
|
+
enumerable: true,
|
|
188
|
+
get: function() {
|
|
189
|
+
return suiAddressFromPublicKey;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
169
192
|
Object.defineProperty(exports, "tronAddressFromPublicKey", {
|
|
170
193
|
enumerable: true,
|
|
171
194
|
get: function() {
|
|
@@ -173,4 +196,4 @@ Object.defineProperty(exports, "tronAddressFromPublicKey", {
|
|
|
173
196
|
}
|
|
174
197
|
});
|
|
175
198
|
|
|
176
|
-
//# sourceMappingURL=derive-
|
|
199
|
+
//# sourceMappingURL=derive-BuNsfWlg.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive-BuNsfWlg.cjs","names":["createBase58check","sha256","HDKey","EraSdkError","secp256k1","keccak_256","bytesToHex","ripemd160","encodeCashAddr","bech32","concatBytes","blake2b","base58","u32be","hmac","sha512","ed25519"],"sources":["../src/accounts/derive.ts"],"sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1';\nimport { blake2b } from '@noble/hashes/blake2b';\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 { encodeCashAddr } from '../chains/cashaddr';\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/** CashAddr P2PKH address (Bitcoin Cash) from a compressed public key. */\nexport function bchAddressFromPublicKey(\n publicKey33: Uint8Array,\n options?: { withPrefix?: boolean },\n): string {\n return encodeCashAddr('p2pkh', hash160(publicKey33), { withPrefix: options?.withPrefix });\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/** `0x` Sui address: BLAKE2b-256 of the scheme flag (0x00 = Ed25519) plus the public key. */\nexport function suiAddressFromPublicKey(publicKey32: Uint8Array): string {\n const digest = blake2b(concatBytes(new Uint8Array([0x00]), publicKey32), { dkLen: 32 });\n return `0x${bytesToHex(digest)}`;\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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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as cbMap, C as bytesToBigint, D as hexToBytes, H as cbText, K as EraSdkError, U as cbUint, W as mapGet, _ as Ur, a as requireSignatureBytes, c as resolveRequestId, h as normalizeRequestId, i as requireRequestIdEcho, l as toUr, n as makeSignRequest, o as requireUrType, r as requireReplyMap, s as resolveContext, x as cborEncode, z as cbBytes } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { i as parsePath, n as keypath304, r as normalizeXfp } from "./keypath-Bvv_cfHt.js";
|
|
2
3
|
//#region src/chains/evm.ts
|
|
3
4
|
/** `eth-sign-request` dataType (CBOR key 3). */
|
|
4
5
|
const EvmDataType = {
|
|
@@ -114,4 +115,4 @@ function foldRecoveryId(v) {
|
|
|
114
115
|
//#endregion
|
|
115
116
|
export { EvmDataType as n, foldRecoveryId as r, EvmChain as t };
|
|
116
117
|
|
|
117
|
-
//# sourceMappingURL=evm-
|
|
118
|
+
//# sourceMappingURL=evm-CI1cuZsp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evm-kJb3-oiR.js","names":["UrValue"],"sources":["../src/chains/evm.ts"],"sourcesContent":["import { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { cbBytes, cbMap, cbText, cbUint, mapGet } from '../cbor/model';\nimport { bytesToBigint, hexToBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { normalizeRequestId } from '../core/rand';\nimport { keypath304, normalizeXfp, parsePath } from '../registry/keypath';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\nimport type { ChainContext, EraConnectConfig, ExpectedReply, SignRequest } from './shared';\nimport {\n makeSignRequest,\n requireReplyMap,\n requireRequestIdEcho,\n requireSignatureBytes,\n requireUrType,\n resolveContext,\n resolveRequestId,\n toUr,\n} from './shared';\n\n/** `eth-sign-request` dataType (CBOR key 3). */\nexport const EvmDataType = {\n /** RLP-encoded transaction (the device sniffs EIP-1559/2930/legacy from the leading byte). */\n transaction: 1,\n /** EIP-712 typed data JSON (UTF-8 bytes). */\n typedData: 2,\n /** personal_sign / raw message bytes (EIP-191 prefix applied by the device). */\n personalMessage: 3,\n /** Typed (EIP-2718) transaction bytes — treated identically to `transaction`. */\n typedTransaction: 4,\n} as const;\nexport type EvmDataType = (typeof EvmDataType)[keyof typeof EvmDataType];\n\nexport interface EvmSignRequestProps {\n /** 16 bytes or a UUID string; minted if omitted. */\n readonly requestId?: Uint8Array | string;\n /** RLP tx bytes, typed-data JSON UTF-8, or raw message bytes. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Full signing path, e.g. `m/44'/60'/0'/0/0`. */\n readonly path: string;\n /** The account's source fingerprint from the linked wallet (`EraAccounts.xfpFor(...)`). */\n readonly xfp: string | number;\n /**\n * Required for transactions (it derives the legal reply width). The device\n * reads it as an unsigned 32-bit value — larger chain ids are refused here,\n * because a silently truncated id would sign for a different chain.\n */\n readonly chainId?: number;\n /** 20-byte signer address; recommended (enables verification helpers). */\n readonly address?: Uint8Array | `0x${string}`;\n /** Overrides the SDK-level origin label for this request. */\n readonly origin?: string;\n}\n\nexport interface EvmSignatureResult {\n readonly requestId: Uint8Array;\n /** Raw `r || s || v` exactly as the device sent it (may exceed 65 bytes for legacy EIP-155). */\n readonly signature: Uint8Array;\n readonly r: Uint8Array;\n readonly s: Uint8Array;\n /**\n * The recovery value AS SENT: parity (0/1) for typed transactions, 27/28\n * for messages, already-EIP-155-encoded (`parity + chainId*2 + 35`) for\n * legacy transactions. Do NOT re-apply the EIP-155 formula.\n */\n readonly v: bigint;\n /** `v` folded to a plain 0/1 recovery id, whichever of the three forms it arrived in. */\n readonly recoveryId: 0 | 1;\n}\n\n/** Over this size the device skips transaction decoding and falls back to blind signing. */\nconst BLIND_SIGN_THRESHOLD = 32 * 1024;\n\nconst REPLY_TYPES = ['eth-signature', 'evm-signature'] as const;\n\nexport class EvmChain {\n static readonly DataType = EvmDataType;\n\n private readonly context: ChainContext;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n /** Build an `eth-sign-request` (401). Reply: `eth-signature` (402). */\n generateSignRequest(props: EvmSignRequestProps): SignRequest<EvmSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n const isTransaction =\n props.dataType === EvmDataType.transaction || props.dataType === EvmDataType.typedTransaction;\n\n if (isTransaction && props.chainId === undefined) {\n throw new EraSdkError('invalid-props', 'chainId is required for transaction sign requests');\n }\n if (props.chainId !== undefined) {\n if (!Number.isSafeInteger(props.chainId) || props.chainId < 0) {\n throw new EraSdkError('invalid-props', 'chainId must be a non-negative integer');\n }\n if (props.chainId > 0xffffffff) {\n throw new EraSdkError(\n 'invalid-props',\n `chainId ${props.chainId} exceeds the device's unsigned 32-bit range; ` +\n 'a truncated id would produce a signature for a different chain',\n { chainId: props.chainId },\n );\n }\n }\n\n const entries: [number, CborValue][] = [\n [1, cbBytes(requestId)],\n [2, cbBytes(props.signData)],\n [3, cbUint(props.dataType)],\n ];\n if (props.chainId !== undefined) entries.push([4, cbUint(props.chainId)]);\n entries.push([5, keypath304(path, xfp)]);\n if (props.address !== undefined) entries.push([6, cbBytes(normalizeAddress(props.address))]);\n entries.push([7, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('eth-sign-request', cborEncode(cbMap(entries)));\n const warnings: string[] = [];\n if (props.signData.length > BLIND_SIGN_THRESHOLD) warnings.push('blind-sign-threshold');\n\n const maxSigLength = 64 + maxVBytes(props.dataType, props.chainId);\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: REPLY_TYPES,\n warnings,\n context: this.context,\n parse: (reply) => parseEvmSignature(reply, { requestId }, maxSigLength),\n });\n }\n\n /**\n * Parse an `eth-signature` standalone. Without `expect.requestId` the echo\n * is returned but not validated — prefer `SignRequest.scanner().parse()`.\n */\n parseSignature(input: Ur | string, expect?: ExpectedReply): EvmSignatureResult {\n const expected =\n expect?.requestId === undefined\n ? undefined\n : { requestId: normalizeRequestId(expect.requestId) };\n return parseEvmSignature(toUr(input), expected, 64 + 8);\n }\n}\n\nfunction normalizeAddress(address: Uint8Array | `0x${string}`): Uint8Array {\n const bytes = address instanceof Uint8Array ? address : hexToBytes(address);\n if (bytes.length !== 20) {\n throw new EraSdkError('invalid-props', 'EVM address must be 20 bytes');\n }\n return bytes;\n}\n\n/**\n * Width of the widest `v` the device can legitimately return.\n *\n * For a legacy EIP-155 transaction `v = parity + chainId*2 + 35` — 2 bytes\n * past chain id 110, 4 bytes for Aurora. Messages and typed data always\n * answer with one byte (27/28). A flat ceiling either refuses genuine replies\n * on large-id chains or accepts implausibly wide values; the exact bound\n * comes from the request.\n */\nfunction maxVBytes(dataType: EvmDataType, chainId: number | undefined): number {\n if (dataType !== EvmDataType.transaction && dataType !== EvmDataType.typedTransaction) return 1;\n if (chainId === undefined) return 8;\n let widest = BigInt(chainId) * 2n + 36n;\n if (widest < 28n) widest = 28n;\n let bytes = 0;\n while (widest > 0n) {\n bytes += 1;\n widest >>= 8n;\n }\n return bytes;\n}\n\nfunction parseEvmSignature(\n ur: Ur,\n expect: { requestId: Uint8Array } | undefined,\n maxSigLength: number,\n): EvmSignatureResult {\n requireUrType(ur, [...REPLY_TYPES], 'eth-signature');\n const map = requireReplyMap(ur, 'eth-signature');\n const requestId = requireRequestIdEcho(map, 1, expect?.requestId, 'eth-signature');\n const signature = requireSignatureBytes(mapGet(map, 2), 'eth-signature', 65, maxSigLength);\n\n const r = signature.slice(0, 32);\n const s = signature.slice(32, 64);\n const v = bytesToBigint(signature.slice(64));\n const recoveryId = foldRecoveryId(v);\n if (recoveryId !== 0 && recoveryId !== 1) {\n throw new EraSdkError(\n 'malformed-reply',\n `eth-signature carries an implausible recovery value ${v}`,\n );\n }\n return { requestId, signature, r, s, v, recoveryId };\n}\n\n/** Fold parity / 27-28 / EIP-155 forms of `v` to a 0/1 recovery id. */\nexport function foldRecoveryId(v: bigint): number {\n if (v >= 35n) return Number((v - 35n) & 1n);\n if (v >= 27n) return Number(v - 27n);\n return Number(v);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"evm-CI1cuZsp.js","names":["UrValue"],"sources":["../src/chains/evm.ts"],"sourcesContent":["import { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { cbBytes, cbMap, cbText, cbUint, mapGet } from '../cbor/model';\nimport { bytesToBigint, hexToBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { normalizeRequestId } from '../core/rand';\nimport { keypath304, normalizeXfp, parsePath } from '../registry/keypath';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\nimport type { ChainContext, EraConnectConfig, ExpectedReply, SignRequest } from './shared';\nimport {\n makeSignRequest,\n requireReplyMap,\n requireRequestIdEcho,\n requireSignatureBytes,\n requireUrType,\n resolveContext,\n resolveRequestId,\n toUr,\n} from './shared';\n\n/** `eth-sign-request` dataType (CBOR key 3). */\nexport const EvmDataType = {\n /** RLP-encoded transaction (the device sniffs EIP-1559/2930/legacy from the leading byte). */\n transaction: 1,\n /** EIP-712 typed data JSON (UTF-8 bytes). */\n typedData: 2,\n /** personal_sign / raw message bytes (EIP-191 prefix applied by the device). */\n personalMessage: 3,\n /** Typed (EIP-2718) transaction bytes — treated identically to `transaction`. */\n typedTransaction: 4,\n} as const;\nexport type EvmDataType = (typeof EvmDataType)[keyof typeof EvmDataType];\n\nexport interface EvmSignRequestProps {\n /** 16 bytes or a UUID string; minted if omitted. */\n readonly requestId?: Uint8Array | string;\n /** RLP tx bytes, typed-data JSON UTF-8, or raw message bytes. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Full signing path, e.g. `m/44'/60'/0'/0/0`. */\n readonly path: string;\n /** The account's source fingerprint from the linked wallet (`EraAccounts.xfpFor(...)`). */\n readonly xfp: string | number;\n /**\n * Required for transactions (it derives the legal reply width). The device\n * reads it as an unsigned 32-bit value — larger chain ids are refused here,\n * because a silently truncated id would sign for a different chain.\n */\n readonly chainId?: number;\n /** 20-byte signer address; recommended (enables verification helpers). */\n readonly address?: Uint8Array | `0x${string}`;\n /** Overrides the SDK-level origin label for this request. */\n readonly origin?: string;\n}\n\nexport interface EvmSignatureResult {\n readonly requestId: Uint8Array;\n /** Raw `r || s || v` exactly as the device sent it (may exceed 65 bytes for legacy EIP-155). */\n readonly signature: Uint8Array;\n readonly r: Uint8Array;\n readonly s: Uint8Array;\n /**\n * The recovery value AS SENT: parity (0/1) for typed transactions, 27/28\n * for messages, already-EIP-155-encoded (`parity + chainId*2 + 35`) for\n * legacy transactions. Do NOT re-apply the EIP-155 formula.\n */\n readonly v: bigint;\n /** `v` folded to a plain 0/1 recovery id, whichever of the three forms it arrived in. */\n readonly recoveryId: 0 | 1;\n}\n\n/** Over this size the device skips transaction decoding and falls back to blind signing. */\nconst BLIND_SIGN_THRESHOLD = 32 * 1024;\n\nconst REPLY_TYPES = ['eth-signature', 'evm-signature'] as const;\n\nexport class EvmChain {\n static readonly DataType = EvmDataType;\n\n private readonly context: ChainContext;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n /** Build an `eth-sign-request` (401). Reply: `eth-signature` (402). */\n generateSignRequest(props: EvmSignRequestProps): SignRequest<EvmSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n const isTransaction =\n props.dataType === EvmDataType.transaction || props.dataType === EvmDataType.typedTransaction;\n\n if (isTransaction && props.chainId === undefined) {\n throw new EraSdkError('invalid-props', 'chainId is required for transaction sign requests');\n }\n if (props.chainId !== undefined) {\n if (!Number.isSafeInteger(props.chainId) || props.chainId < 0) {\n throw new EraSdkError('invalid-props', 'chainId must be a non-negative integer');\n }\n if (props.chainId > 0xffffffff) {\n throw new EraSdkError(\n 'invalid-props',\n `chainId ${props.chainId} exceeds the device's unsigned 32-bit range; ` +\n 'a truncated id would produce a signature for a different chain',\n { chainId: props.chainId },\n );\n }\n }\n\n const entries: [number, CborValue][] = [\n [1, cbBytes(requestId)],\n [2, cbBytes(props.signData)],\n [3, cbUint(props.dataType)],\n ];\n if (props.chainId !== undefined) entries.push([4, cbUint(props.chainId)]);\n entries.push([5, keypath304(path, xfp)]);\n if (props.address !== undefined) entries.push([6, cbBytes(normalizeAddress(props.address))]);\n entries.push([7, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('eth-sign-request', cborEncode(cbMap(entries)));\n const warnings: string[] = [];\n if (props.signData.length > BLIND_SIGN_THRESHOLD) warnings.push('blind-sign-threshold');\n\n const maxSigLength = 64 + maxVBytes(props.dataType, props.chainId);\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: REPLY_TYPES,\n warnings,\n context: this.context,\n parse: (reply) => parseEvmSignature(reply, { requestId }, maxSigLength),\n });\n }\n\n /**\n * Parse an `eth-signature` standalone. Without `expect.requestId` the echo\n * is returned but not validated — prefer `SignRequest.scanner().parse()`.\n */\n parseSignature(input: Ur | string, expect?: ExpectedReply): EvmSignatureResult {\n const expected =\n expect?.requestId === undefined\n ? undefined\n : { requestId: normalizeRequestId(expect.requestId) };\n return parseEvmSignature(toUr(input), expected, 64 + 8);\n }\n}\n\nfunction normalizeAddress(address: Uint8Array | `0x${string}`): Uint8Array {\n const bytes = address instanceof Uint8Array ? address : hexToBytes(address);\n if (bytes.length !== 20) {\n throw new EraSdkError('invalid-props', 'EVM address must be 20 bytes');\n }\n return bytes;\n}\n\n/**\n * Width of the widest `v` the device can legitimately return.\n *\n * For a legacy EIP-155 transaction `v = parity + chainId*2 + 35` — 2 bytes\n * past chain id 110, 4 bytes for Aurora. Messages and typed data always\n * answer with one byte (27/28). A flat ceiling either refuses genuine replies\n * on large-id chains or accepts implausibly wide values; the exact bound\n * comes from the request.\n */\nfunction maxVBytes(dataType: EvmDataType, chainId: number | undefined): number {\n if (dataType !== EvmDataType.transaction && dataType !== EvmDataType.typedTransaction) return 1;\n if (chainId === undefined) return 8;\n let widest = BigInt(chainId) * 2n + 36n;\n if (widest < 28n) widest = 28n;\n let bytes = 0;\n while (widest > 0n) {\n bytes += 1;\n widest >>= 8n;\n }\n return bytes;\n}\n\nfunction parseEvmSignature(\n ur: Ur,\n expect: { requestId: Uint8Array } | undefined,\n maxSigLength: number,\n): EvmSignatureResult {\n requireUrType(ur, [...REPLY_TYPES], 'eth-signature');\n const map = requireReplyMap(ur, 'eth-signature');\n const requestId = requireRequestIdEcho(map, 1, expect?.requestId, 'eth-signature');\n const signature = requireSignatureBytes(mapGet(map, 2), 'eth-signature', 65, maxSigLength);\n\n const r = signature.slice(0, 32);\n const s = signature.slice(32, 64);\n const v = bytesToBigint(signature.slice(64));\n const recoveryId = foldRecoveryId(v);\n if (recoveryId !== 0 && recoveryId !== 1) {\n throw new EraSdkError(\n 'malformed-reply',\n `eth-signature carries an implausible recovery value ${v}`,\n );\n }\n return { requestId, signature, r, s, v, recoveryId };\n}\n\n/** Fold parity / 27-28 / EIP-155 forms of `v` to a 0/1 recovery id. */\nexport function foldRecoveryId(v: bigint): number {\n if (v >= 35n) return Number((v - 35n) & 1n);\n if (v >= 27n) return Number(v - 27n);\n return Number(v);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const require_shared = require("./shared-
|
|
1
|
+
const require_shared = require("./shared-Cu2yynP9.cjs");
|
|
2
|
+
const require_keypath = require("./keypath-pzm_YIfN.cjs");
|
|
2
3
|
//#region src/chains/evm.ts
|
|
3
4
|
/** `eth-sign-request` dataType (CBOR key 3). */
|
|
4
5
|
const EvmDataType = {
|
|
@@ -21,8 +22,8 @@ var EvmChain = class {
|
|
|
21
22
|
/** Build an `eth-sign-request` (401). Reply: `eth-signature` (402). */
|
|
22
23
|
generateSignRequest(props) {
|
|
23
24
|
const requestId = require_shared.resolveRequestId(this.context, props.requestId);
|
|
24
|
-
const path =
|
|
25
|
-
const xfp =
|
|
25
|
+
const path = require_keypath.parsePath(props.path);
|
|
26
|
+
const xfp = require_keypath.normalizeXfp(props.xfp);
|
|
26
27
|
if ((props.dataType === EvmDataType.transaction || props.dataType === EvmDataType.typedTransaction) && props.chainId === void 0) throw new require_shared.EraSdkError("invalid-props", "chainId is required for transaction sign requests");
|
|
27
28
|
if (props.chainId !== void 0) {
|
|
28
29
|
if (!Number.isSafeInteger(props.chainId) || props.chainId < 0) throw new require_shared.EraSdkError("invalid-props", "chainId must be a non-negative integer");
|
|
@@ -34,7 +35,7 @@ var EvmChain = class {
|
|
|
34
35
|
[3, require_shared.cbUint(props.dataType)]
|
|
35
36
|
];
|
|
36
37
|
if (props.chainId !== void 0) entries.push([4, require_shared.cbUint(props.chainId)]);
|
|
37
|
-
entries.push([5,
|
|
38
|
+
entries.push([5, require_keypath.keypath304(path, xfp)]);
|
|
38
39
|
if (props.address !== void 0) entries.push([6, require_shared.cbBytes(normalizeAddress(props.address))]);
|
|
39
40
|
entries.push([7, require_shared.cbText(props.origin ?? this.context.origin)]);
|
|
40
41
|
const ur = new require_shared.Ur("eth-sign-request", require_shared.cborEncode(require_shared.cbMap(entries)));
|
|
@@ -131,4 +132,4 @@ Object.defineProperty(exports, "foldRecoveryId", {
|
|
|
131
132
|
}
|
|
132
133
|
});
|
|
133
134
|
|
|
134
|
-
//# sourceMappingURL=evm-
|
|
135
|
+
//# sourceMappingURL=evm-yfKOc2dy.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evm-BHj_2OTG.cjs","names":["resolveContext","resolveRequestId","parsePath","normalizeXfp","EraSdkError","cbBytes","cbUint","keypath304","cbText","UrValue","cborEncode","cbMap","makeSignRequest","normalizeRequestId","toUr","hexToBytes","requireReplyMap","requireRequestIdEcho","requireSignatureBytes","mapGet","bytesToBigint"],"sources":["../src/chains/evm.ts"],"sourcesContent":["import { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { cbBytes, cbMap, cbText, cbUint, mapGet } from '../cbor/model';\nimport { bytesToBigint, hexToBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { normalizeRequestId } from '../core/rand';\nimport { keypath304, normalizeXfp, parsePath } from '../registry/keypath';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\nimport type { ChainContext, EraConnectConfig, ExpectedReply, SignRequest } from './shared';\nimport {\n makeSignRequest,\n requireReplyMap,\n requireRequestIdEcho,\n requireSignatureBytes,\n requireUrType,\n resolveContext,\n resolveRequestId,\n toUr,\n} from './shared';\n\n/** `eth-sign-request` dataType (CBOR key 3). */\nexport const EvmDataType = {\n /** RLP-encoded transaction (the device sniffs EIP-1559/2930/legacy from the leading byte). */\n transaction: 1,\n /** EIP-712 typed data JSON (UTF-8 bytes). */\n typedData: 2,\n /** personal_sign / raw message bytes (EIP-191 prefix applied by the device). */\n personalMessage: 3,\n /** Typed (EIP-2718) transaction bytes — treated identically to `transaction`. */\n typedTransaction: 4,\n} as const;\nexport type EvmDataType = (typeof EvmDataType)[keyof typeof EvmDataType];\n\nexport interface EvmSignRequestProps {\n /** 16 bytes or a UUID string; minted if omitted. */\n readonly requestId?: Uint8Array | string;\n /** RLP tx bytes, typed-data JSON UTF-8, or raw message bytes. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Full signing path, e.g. `m/44'/60'/0'/0/0`. */\n readonly path: string;\n /** The account's source fingerprint from the linked wallet (`EraAccounts.xfpFor(...)`). */\n readonly xfp: string | number;\n /**\n * Required for transactions (it derives the legal reply width). The device\n * reads it as an unsigned 32-bit value — larger chain ids are refused here,\n * because a silently truncated id would sign for a different chain.\n */\n readonly chainId?: number;\n /** 20-byte signer address; recommended (enables verification helpers). */\n readonly address?: Uint8Array | `0x${string}`;\n /** Overrides the SDK-level origin label for this request. */\n readonly origin?: string;\n}\n\nexport interface EvmSignatureResult {\n readonly requestId: Uint8Array;\n /** Raw `r || s || v` exactly as the device sent it (may exceed 65 bytes for legacy EIP-155). */\n readonly signature: Uint8Array;\n readonly r: Uint8Array;\n readonly s: Uint8Array;\n /**\n * The recovery value AS SENT: parity (0/1) for typed transactions, 27/28\n * for messages, already-EIP-155-encoded (`parity + chainId*2 + 35`) for\n * legacy transactions. Do NOT re-apply the EIP-155 formula.\n */\n readonly v: bigint;\n /** `v` folded to a plain 0/1 recovery id, whichever of the three forms it arrived in. */\n readonly recoveryId: 0 | 1;\n}\n\n/** Over this size the device skips transaction decoding and falls back to blind signing. */\nconst BLIND_SIGN_THRESHOLD = 32 * 1024;\n\nconst REPLY_TYPES = ['eth-signature', 'evm-signature'] as const;\n\nexport class EvmChain {\n static readonly DataType = EvmDataType;\n\n private readonly context: ChainContext;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n /** Build an `eth-sign-request` (401). Reply: `eth-signature` (402). */\n generateSignRequest(props: EvmSignRequestProps): SignRequest<EvmSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n const isTransaction =\n props.dataType === EvmDataType.transaction || props.dataType === EvmDataType.typedTransaction;\n\n if (isTransaction && props.chainId === undefined) {\n throw new EraSdkError('invalid-props', 'chainId is required for transaction sign requests');\n }\n if (props.chainId !== undefined) {\n if (!Number.isSafeInteger(props.chainId) || props.chainId < 0) {\n throw new EraSdkError('invalid-props', 'chainId must be a non-negative integer');\n }\n if (props.chainId > 0xffffffff) {\n throw new EraSdkError(\n 'invalid-props',\n `chainId ${props.chainId} exceeds the device's unsigned 32-bit range; ` +\n 'a truncated id would produce a signature for a different chain',\n { chainId: props.chainId },\n );\n }\n }\n\n const entries: [number, CborValue][] = [\n [1, cbBytes(requestId)],\n [2, cbBytes(props.signData)],\n [3, cbUint(props.dataType)],\n ];\n if (props.chainId !== undefined) entries.push([4, cbUint(props.chainId)]);\n entries.push([5, keypath304(path, xfp)]);\n if (props.address !== undefined) entries.push([6, cbBytes(normalizeAddress(props.address))]);\n entries.push([7, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('eth-sign-request', cborEncode(cbMap(entries)));\n const warnings: string[] = [];\n if (props.signData.length > BLIND_SIGN_THRESHOLD) warnings.push('blind-sign-threshold');\n\n const maxSigLength = 64 + maxVBytes(props.dataType, props.chainId);\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: REPLY_TYPES,\n warnings,\n context: this.context,\n parse: (reply) => parseEvmSignature(reply, { requestId }, maxSigLength),\n });\n }\n\n /**\n * Parse an `eth-signature` standalone. Without `expect.requestId` the echo\n * is returned but not validated — prefer `SignRequest.scanner().parse()`.\n */\n parseSignature(input: Ur | string, expect?: ExpectedReply): EvmSignatureResult {\n const expected =\n expect?.requestId === undefined\n ? undefined\n : { requestId: normalizeRequestId(expect.requestId) };\n return parseEvmSignature(toUr(input), expected, 64 + 8);\n }\n}\n\nfunction normalizeAddress(address: Uint8Array | `0x${string}`): Uint8Array {\n const bytes = address instanceof Uint8Array ? address : hexToBytes(address);\n if (bytes.length !== 20) {\n throw new EraSdkError('invalid-props', 'EVM address must be 20 bytes');\n }\n return bytes;\n}\n\n/**\n * Width of the widest `v` the device can legitimately return.\n *\n * For a legacy EIP-155 transaction `v = parity + chainId*2 + 35` — 2 bytes\n * past chain id 110, 4 bytes for Aurora. Messages and typed data always\n * answer with one byte (27/28). A flat ceiling either refuses genuine replies\n * on large-id chains or accepts implausibly wide values; the exact bound\n * comes from the request.\n */\nfunction maxVBytes(dataType: EvmDataType, chainId: number | undefined): number {\n if (dataType !== EvmDataType.transaction && dataType !== EvmDataType.typedTransaction) return 1;\n if (chainId === undefined) return 8;\n let widest = BigInt(chainId) * 2n + 36n;\n if (widest < 28n) widest = 28n;\n let bytes = 0;\n while (widest > 0n) {\n bytes += 1;\n widest >>= 8n;\n }\n return bytes;\n}\n\nfunction parseEvmSignature(\n ur: Ur,\n expect: { requestId: Uint8Array } | undefined,\n maxSigLength: number,\n): EvmSignatureResult {\n requireUrType(ur, [...REPLY_TYPES], 'eth-signature');\n const map = requireReplyMap(ur, 'eth-signature');\n const requestId = requireRequestIdEcho(map, 1, expect?.requestId, 'eth-signature');\n const signature = requireSignatureBytes(mapGet(map, 2), 'eth-signature', 65, maxSigLength);\n\n const r = signature.slice(0, 32);\n const s = signature.slice(32, 64);\n const v = bytesToBigint(signature.slice(64));\n const recoveryId = foldRecoveryId(v);\n if (recoveryId !== 0 && recoveryId !== 1) {\n throw new EraSdkError(\n 'malformed-reply',\n `eth-signature carries an implausible recovery value ${v}`,\n );\n }\n return { requestId, signature, r, s, v, recoveryId };\n}\n\n/** Fold parity / 27-28 / EIP-155 forms of `v` to a 0/1 recovery id. */\nexport function foldRecoveryId(v: bigint): number {\n if (v >= 35n) return Number((v - 35n) & 1n);\n if (v >= 27n) return Number(v - 27n);\n return Number(v);\n}\n"],"mappings":";;;AAsBA,MAAa,cAAc;;CAEzB,aAAa;;CAEb,WAAW;;CAEX,iBAAiB;;CAEjB,kBAAkB;AACpB;;AA0CA,MAAM,uBAAuB;AAE7B,MAAM,cAAc,CAAC,iBAAiB,eAAe;AAErD,IAAa,WAAb,MAAsB;CAKpB,YAAY,QAA2B;EACrC,KAAK,UAAUA,eAAAA,eAAe,MAAM;CACtC;;CAGA,oBAAoB,OAA6D;EAC/E,MAAM,YAAYC,eAAAA,iBAAiB,KAAK,SAAS,MAAM,SAAS;EAChE,MAAM,OAAOC,eAAAA,UAAU,MAAM,IAAI;EACjC,MAAM,MAAMC,eAAAA,aAAa,MAAM,GAAG;EAIlC,KAFE,MAAM,aAAa,YAAY,eAAe,MAAM,aAAa,YAAY,qBAE1D,MAAM,YAAY,KAAA,GACrC,MAAM,IAAIC,eAAAA,YAAY,iBAAiB,mDAAmD;EAE5F,IAAI,MAAM,YAAY,KAAA,GAAW;GAC/B,IAAI,CAAC,OAAO,cAAc,MAAM,OAAO,KAAK,MAAM,UAAU,GAC1D,MAAM,IAAIA,eAAAA,YAAY,iBAAiB,wCAAwC;GAEjF,IAAI,MAAM,UAAU,YAClB,MAAM,IAAIA,eAAAA,YACR,iBACA,WAAW,MAAM,QAAQ,8GAEzB,EAAE,SAAS,MAAM,QAAQ,CAC3B;EAEJ;EAEA,MAAM,UAAiC;GACrC,CAAC,GAAGC,eAAAA,QAAQ,SAAS,CAAC;GACtB,CAAC,GAAGA,eAAAA,QAAQ,MAAM,QAAQ,CAAC;GAC3B,CAAC,GAAGC,eAAAA,OAAO,MAAM,QAAQ,CAAC;EAC5B;EACA,IAAI,MAAM,YAAY,KAAA,GAAW,QAAQ,KAAK,CAAC,GAAGA,eAAAA,OAAO,MAAM,OAAO,CAAC,CAAC;EACxE,QAAQ,KAAK,CAAC,GAAGC,eAAAA,WAAW,MAAM,GAAG,CAAC,CAAC;EACvC,IAAI,MAAM,YAAY,KAAA,GAAW,QAAQ,KAAK,CAAC,GAAGF,eAAAA,QAAQ,iBAAiB,MAAM,OAAO,CAAC,CAAC,CAAC;EAC3F,QAAQ,KAAK,CAAC,GAAGG,eAAAA,OAAO,MAAM,UAAU,KAAK,QAAQ,MAAM,CAAC,CAAC;EAE7D,MAAM,KAAK,IAAIC,eAAAA,GAAQ,oBAAoBC,eAAAA,WAAWC,eAAAA,MAAM,OAAO,CAAC,CAAC;EACrE,MAAM,WAAqB,CAAC;EAC5B,IAAI,MAAM,SAAS,SAAS,sBAAsB,SAAS,KAAK,sBAAsB;EAEtF,MAAM,eAAe,KAAK,UAAU,MAAM,UAAU,MAAM,OAAO;EACjE,OAAOC,eAAAA,gBAAgB;GACrB;GACA;GACA,YAAY;GACZ;GACA,SAAS,KAAK;GACd,QAAQ,UAAU,kBAAkB,OAAO,EAAE,UAAU,GAAG,YAAY;EACxE,CAAC;CACH;;;;;CAMA,eAAe,OAAoB,QAA4C;EAC7E,MAAM,WACJ,QAAQ,cAAc,KAAA,IAClB,KAAA,IACA,EAAE,WAAWC,eAAAA,mBAAmB,OAAO,SAAS,EAAE;EACxD,OAAO,kBAAkBC,eAAAA,KAAK,KAAK,GAAG,UAAU,EAAM;CACxD;AACF;AArEE,SAAgB,WAAW;AAuE7B,SAAS,iBAAiB,SAAiD;CACzE,MAAM,QAAQ,mBAAmB,aAAa,UAAUC,eAAAA,WAAW,OAAO;CAC1E,IAAI,MAAM,WAAW,IACnB,MAAM,IAAIX,eAAAA,YAAY,iBAAiB,8BAA8B;CAEvE,OAAO;AACT;;;;;;;;;;AAWA,SAAS,UAAU,UAAuB,SAAqC;CAC7E,IAAI,aAAa,YAAY,eAAe,aAAa,YAAY,kBAAkB,OAAO;CAC9F,IAAI,YAAY,KAAA,GAAW,OAAO;CAClC,IAAI,SAAS,OAAO,OAAO,IAAI,KAAK;CACpC,IAAI,SAAS,KAAK,SAAS;CAC3B,IAAI,QAAQ;CACZ,OAAO,SAAS,IAAI;EAClB,SAAS;EACT,WAAW;CACb;CACA,OAAO;AACT;AAEA,SAAS,kBACP,IACA,QACA,cACoB;CACpB,eAAA,cAAc,IAAI,CAAC,GAAG,WAAW,GAAG,eAAe;CACnD,MAAM,MAAMY,eAAAA,gBAAgB,IAAI,eAAe;CAC/C,MAAM,YAAYC,eAAAA,qBAAqB,KAAK,GAAG,QAAQ,WAAW,eAAe;CACjF,MAAM,YAAYC,eAAAA,sBAAsBC,eAAAA,OAAO,KAAK,CAAC,GAAG,iBAAiB,IAAI,YAAY;CAEzF,MAAM,IAAI,UAAU,MAAM,GAAG,EAAE;CAC/B,MAAM,IAAI,UAAU,MAAM,IAAI,EAAE;CAChC,MAAM,IAAIC,eAAAA,cAAc,UAAU,MAAM,EAAE,CAAC;CAC3C,MAAM,aAAa,eAAe,CAAC;CACnC,IAAI,eAAe,KAAK,eAAe,GACrC,MAAM,IAAIhB,eAAAA,YACR,mBACA,uDAAuD,GACzD;CAEF,OAAO;EAAE;EAAW;EAAW;EAAG;EAAG;EAAG;CAAW;AACrD;;AAGA,SAAgB,eAAe,GAAmB;CAChD,IAAI,KAAK,KAAK,OAAO,OAAQ,IAAI,MAAO,EAAE;CAC1C,IAAI,KAAK,KAAK,OAAO,OAAO,IAAI,GAAG;CACnC,OAAO,OAAO,CAAC;AACjB"}
|
|
1
|
+
{"version":3,"file":"evm-yfKOc2dy.cjs","names":["resolveContext","resolveRequestId","parsePath","normalizeXfp","EraSdkError","cbBytes","cbUint","keypath304","cbText","UrValue","cborEncode","cbMap","makeSignRequest","normalizeRequestId","toUr","hexToBytes","requireReplyMap","requireRequestIdEcho","requireSignatureBytes","mapGet","bytesToBigint"],"sources":["../src/chains/evm.ts"],"sourcesContent":["import { cborEncode } from '../cbor/encode';\nimport type { CborValue } from '../cbor/model';\nimport { cbBytes, cbMap, cbText, cbUint, mapGet } from '../cbor/model';\nimport { bytesToBigint, hexToBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { normalizeRequestId } from '../core/rand';\nimport { keypath304, normalizeXfp, parsePath } from '../registry/keypath';\nimport type { Ur } from '../ur/ur';\nimport { Ur as UrValue } from '../ur/ur';\nimport type { ChainContext, EraConnectConfig, ExpectedReply, SignRequest } from './shared';\nimport {\n makeSignRequest,\n requireReplyMap,\n requireRequestIdEcho,\n requireSignatureBytes,\n requireUrType,\n resolveContext,\n resolveRequestId,\n toUr,\n} from './shared';\n\n/** `eth-sign-request` dataType (CBOR key 3). */\nexport const EvmDataType = {\n /** RLP-encoded transaction (the device sniffs EIP-1559/2930/legacy from the leading byte). */\n transaction: 1,\n /** EIP-712 typed data JSON (UTF-8 bytes). */\n typedData: 2,\n /** personal_sign / raw message bytes (EIP-191 prefix applied by the device). */\n personalMessage: 3,\n /** Typed (EIP-2718) transaction bytes — treated identically to `transaction`. */\n typedTransaction: 4,\n} as const;\nexport type EvmDataType = (typeof EvmDataType)[keyof typeof EvmDataType];\n\nexport interface EvmSignRequestProps {\n /** 16 bytes or a UUID string; minted if omitted. */\n readonly requestId?: Uint8Array | string;\n /** RLP tx bytes, typed-data JSON UTF-8, or raw message bytes. */\n readonly signData: Uint8Array;\n readonly dataType: EvmDataType;\n /** Full signing path, e.g. `m/44'/60'/0'/0/0`. */\n readonly path: string;\n /** The account's source fingerprint from the linked wallet (`EraAccounts.xfpFor(...)`). */\n readonly xfp: string | number;\n /**\n * Required for transactions (it derives the legal reply width). The device\n * reads it as an unsigned 32-bit value — larger chain ids are refused here,\n * because a silently truncated id would sign for a different chain.\n */\n readonly chainId?: number;\n /** 20-byte signer address; recommended (enables verification helpers). */\n readonly address?: Uint8Array | `0x${string}`;\n /** Overrides the SDK-level origin label for this request. */\n readonly origin?: string;\n}\n\nexport interface EvmSignatureResult {\n readonly requestId: Uint8Array;\n /** Raw `r || s || v` exactly as the device sent it (may exceed 65 bytes for legacy EIP-155). */\n readonly signature: Uint8Array;\n readonly r: Uint8Array;\n readonly s: Uint8Array;\n /**\n * The recovery value AS SENT: parity (0/1) for typed transactions, 27/28\n * for messages, already-EIP-155-encoded (`parity + chainId*2 + 35`) for\n * legacy transactions. Do NOT re-apply the EIP-155 formula.\n */\n readonly v: bigint;\n /** `v` folded to a plain 0/1 recovery id, whichever of the three forms it arrived in. */\n readonly recoveryId: 0 | 1;\n}\n\n/** Over this size the device skips transaction decoding and falls back to blind signing. */\nconst BLIND_SIGN_THRESHOLD = 32 * 1024;\n\nconst REPLY_TYPES = ['eth-signature', 'evm-signature'] as const;\n\nexport class EvmChain {\n static readonly DataType = EvmDataType;\n\n private readonly context: ChainContext;\n\n constructor(config?: EraConnectConfig) {\n this.context = resolveContext(config);\n }\n\n /** Build an `eth-sign-request` (401). Reply: `eth-signature` (402). */\n generateSignRequest(props: EvmSignRequestProps): SignRequest<EvmSignatureResult> {\n const requestId = resolveRequestId(this.context, props.requestId);\n const path = parsePath(props.path);\n const xfp = normalizeXfp(props.xfp);\n const isTransaction =\n props.dataType === EvmDataType.transaction || props.dataType === EvmDataType.typedTransaction;\n\n if (isTransaction && props.chainId === undefined) {\n throw new EraSdkError('invalid-props', 'chainId is required for transaction sign requests');\n }\n if (props.chainId !== undefined) {\n if (!Number.isSafeInteger(props.chainId) || props.chainId < 0) {\n throw new EraSdkError('invalid-props', 'chainId must be a non-negative integer');\n }\n if (props.chainId > 0xffffffff) {\n throw new EraSdkError(\n 'invalid-props',\n `chainId ${props.chainId} exceeds the device's unsigned 32-bit range; ` +\n 'a truncated id would produce a signature for a different chain',\n { chainId: props.chainId },\n );\n }\n }\n\n const entries: [number, CborValue][] = [\n [1, cbBytes(requestId)],\n [2, cbBytes(props.signData)],\n [3, cbUint(props.dataType)],\n ];\n if (props.chainId !== undefined) entries.push([4, cbUint(props.chainId)]);\n entries.push([5, keypath304(path, xfp)]);\n if (props.address !== undefined) entries.push([6, cbBytes(normalizeAddress(props.address))]);\n entries.push([7, cbText(props.origin ?? this.context.origin)]);\n\n const ur = new UrValue('eth-sign-request', cborEncode(cbMap(entries)));\n const warnings: string[] = [];\n if (props.signData.length > BLIND_SIGN_THRESHOLD) warnings.push('blind-sign-threshold');\n\n const maxSigLength = 64 + maxVBytes(props.dataType, props.chainId);\n return makeSignRequest({\n ur,\n requestId,\n replyTypes: REPLY_TYPES,\n warnings,\n context: this.context,\n parse: (reply) => parseEvmSignature(reply, { requestId }, maxSigLength),\n });\n }\n\n /**\n * Parse an `eth-signature` standalone. Without `expect.requestId` the echo\n * is returned but not validated — prefer `SignRequest.scanner().parse()`.\n */\n parseSignature(input: Ur | string, expect?: ExpectedReply): EvmSignatureResult {\n const expected =\n expect?.requestId === undefined\n ? undefined\n : { requestId: normalizeRequestId(expect.requestId) };\n return parseEvmSignature(toUr(input), expected, 64 + 8);\n }\n}\n\nfunction normalizeAddress(address: Uint8Array | `0x${string}`): Uint8Array {\n const bytes = address instanceof Uint8Array ? address : hexToBytes(address);\n if (bytes.length !== 20) {\n throw new EraSdkError('invalid-props', 'EVM address must be 20 bytes');\n }\n return bytes;\n}\n\n/**\n * Width of the widest `v` the device can legitimately return.\n *\n * For a legacy EIP-155 transaction `v = parity + chainId*2 + 35` — 2 bytes\n * past chain id 110, 4 bytes for Aurora. Messages and typed data always\n * answer with one byte (27/28). A flat ceiling either refuses genuine replies\n * on large-id chains or accepts implausibly wide values; the exact bound\n * comes from the request.\n */\nfunction maxVBytes(dataType: EvmDataType, chainId: number | undefined): number {\n if (dataType !== EvmDataType.transaction && dataType !== EvmDataType.typedTransaction) return 1;\n if (chainId === undefined) return 8;\n let widest = BigInt(chainId) * 2n + 36n;\n if (widest < 28n) widest = 28n;\n let bytes = 0;\n while (widest > 0n) {\n bytes += 1;\n widest >>= 8n;\n }\n return bytes;\n}\n\nfunction parseEvmSignature(\n ur: Ur,\n expect: { requestId: Uint8Array } | undefined,\n maxSigLength: number,\n): EvmSignatureResult {\n requireUrType(ur, [...REPLY_TYPES], 'eth-signature');\n const map = requireReplyMap(ur, 'eth-signature');\n const requestId = requireRequestIdEcho(map, 1, expect?.requestId, 'eth-signature');\n const signature = requireSignatureBytes(mapGet(map, 2), 'eth-signature', 65, maxSigLength);\n\n const r = signature.slice(0, 32);\n const s = signature.slice(32, 64);\n const v = bytesToBigint(signature.slice(64));\n const recoveryId = foldRecoveryId(v);\n if (recoveryId !== 0 && recoveryId !== 1) {\n throw new EraSdkError(\n 'malformed-reply',\n `eth-signature carries an implausible recovery value ${v}`,\n );\n }\n return { requestId, signature, r, s, v, recoveryId };\n}\n\n/** Fold parity / 27-28 / EIP-155 forms of `v` to a 0/1 recovery id. */\nexport function foldRecoveryId(v: bigint): number {\n if (v >= 35n) return Number((v - 35n) & 1n);\n if (v >= 27n) return Number(v - 27n);\n return Number(v);\n}\n"],"mappings":"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"}
|
package/dist/evm.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_shared = require("./shared-
|
|
3
|
-
const require_evm = require("./evm-
|
|
2
|
+
const require_shared = require("./shared-Cu2yynP9.cjs");
|
|
3
|
+
const require_evm = require("./evm-yfKOc2dy.cjs");
|
|
4
4
|
exports.AnimatedUr = require_shared.AnimatedUr;
|
|
5
5
|
exports.EraSdkError = require_shared.EraSdkError;
|
|
6
6
|
exports.EvmChain = require_evm.EvmChain;
|
package/dist/evm.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as EvmDataType, r as foldRecoveryId, t as EvmChain } from "./evm-
|
|
1
|
+
import { K as EraSdkError, _ as Ur, d as UrScanner, f as AnimatedUr, u as TypedUrScanner } from "./shared-Bbgejrus.js";
|
|
2
|
+
import { n as EvmDataType, r as foldRecoveryId, t as EvmChain } from "./evm-CI1cuZsp.js";
|
|
3
3
|
export { AnimatedUr, EraSdkError, EvmChain, EvmDataType, TypedUrScanner, Ur, UrScanner, foldRecoveryId };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const require_shared = require("./shared-Cu2yynP9.cjs");
|
|
2
|
+
let fflate = require("fflate");
|
|
3
|
+
//#region src/tron-proto/gzip.ts
|
|
4
|
+
/** Smallest possible gzip stream: 10-byte header + 8-byte trailer. */
|
|
5
|
+
const MIN_GZIP_BYTES = 18;
|
|
6
|
+
/** Bytes fed to the inflater per step; bounds the overshoot past the cap. */
|
|
7
|
+
const SLICE_BYTES = 1024;
|
|
8
|
+
/** Deterministic gzip (fixed level, zeroed mtime) for reproducible request bytes. */
|
|
9
|
+
function gzipCompress(data) {
|
|
10
|
+
return (0, fflate.gzipSync)(data, {
|
|
11
|
+
level: 9,
|
|
12
|
+
mtime: 0
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Inflate with a hard output ceiling.
|
|
17
|
+
*
|
|
18
|
+
* A one-shot gunzip allocates the entire output before anyone can refuse it —
|
|
19
|
+
* gzip reaches ~1000:1 in practice, so a few hundred scanned bytes could ask
|
|
20
|
+
* for an arbitrary allocation. The decoder is therefore driven in slices and
|
|
21
|
+
* the output counted as it arrives; the moment the total would pass the cap,
|
|
22
|
+
* feeding stops and the reply is refused.
|
|
23
|
+
*
|
|
24
|
+
* The trailer's ISIZE (declared inflated length) is used twice: as a cheap
|
|
25
|
+
* refusal of honest bombs before any work, and as a truncation check at the
|
|
26
|
+
* end — an inflater hands back a partial buffer for a truncated stream
|
|
27
|
+
* without erroring, and a genuine device reply always declares honestly.
|
|
28
|
+
*/
|
|
29
|
+
function gunzipCapped(data, maxOutputBytes) {
|
|
30
|
+
if (data.length < MIN_GZIP_BYTES) throw new require_shared.EraSdkError("gzip-error", "compressed payload is too short to be a gzip stream");
|
|
31
|
+
if (data[0] !== 31 || data[1] !== 139) throw new require_shared.EraSdkError("gzip-error", "compressed payload is not a gzip stream");
|
|
32
|
+
const n = data.length;
|
|
33
|
+
const isize = (data[n - 4] | data[n - 3] << 8 | data[n - 2] << 16 | data[n - 1] << 24) >>> 0;
|
|
34
|
+
if (isize > maxOutputBytes) throw new require_shared.EraSdkError("gzip-error", `compressed payload declares ${isize} bytes, over the ${maxOutputBytes} byte ceiling`);
|
|
35
|
+
const chunks = [];
|
|
36
|
+
let total = 0;
|
|
37
|
+
let overflowed = false;
|
|
38
|
+
let malformed = null;
|
|
39
|
+
const gunzip = new fflate.Gunzip((chunk) => {
|
|
40
|
+
if (overflowed) return;
|
|
41
|
+
if (total + chunk.length > maxOutputBytes) {
|
|
42
|
+
overflowed = true;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
chunks.push(chunk);
|
|
46
|
+
total += chunk.length;
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
for (let offset = 0; offset < n && !overflowed; offset += SLICE_BYTES) {
|
|
50
|
+
const end = Math.min(offset + SLICE_BYTES, n);
|
|
51
|
+
const isLast = end === n;
|
|
52
|
+
gunzip.push(data.slice(offset, end), isLast);
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
malformed = e.message ?? "inflate error";
|
|
56
|
+
}
|
|
57
|
+
if (overflowed) throw new require_shared.EraSdkError("gzip-error", `compressed payload inflates past the ${maxOutputBytes} byte ceiling`);
|
|
58
|
+
if (malformed !== null) throw new require_shared.EraSdkError("gzip-error", `compressed payload is malformed: ${malformed}`);
|
|
59
|
+
const out = require_shared.concatBytes(...chunks);
|
|
60
|
+
if (out.length !== isize) throw new require_shared.EraSdkError("gzip-error", `compressed payload inflated to ${out.length} bytes but declares ${isize} — truncated or malformed`);
|
|
61
|
+
const declaredCrc = (data[n - 8] | data[n - 7] << 8 | data[n - 6] << 16 | data[n - 5] << 24) >>> 0;
|
|
62
|
+
if (require_shared.crc32(out) !== declaredCrc) throw new require_shared.EraSdkError("gzip-error", "compressed payload is malformed: CRC mismatch");
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
Object.defineProperty(exports, "gunzipCapped", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function() {
|
|
69
|
+
return gunzipCapped;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "gzipCompress", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function() {
|
|
75
|
+
return gzipCompress;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=gzip-CLzDX7AZ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gzip-CLzDX7AZ.cjs","names":["gzipSync","EraSdkError","Gunzip","concatBytes","crc32"],"sources":["../src/tron-proto/gzip.ts"],"sourcesContent":["import { Gunzip, gzipSync } from 'fflate';\nimport { concatBytes } from '../core/bytes';\nimport { EraSdkError } from '../core/errors';\nimport { crc32 } from '../ur/crc32';\n\n/** Smallest possible gzip stream: 10-byte header + 8-byte trailer. */\nconst MIN_GZIP_BYTES = 18;\n\n/** Bytes fed to the inflater per step; bounds the overshoot past the cap. */\nconst SLICE_BYTES = 1024;\n\n/** Deterministic gzip (fixed level, zeroed mtime) for reproducible request bytes. */\nexport function gzipCompress(data: Uint8Array): Uint8Array {\n return gzipSync(data, { level: 9, mtime: 0 });\n}\n\n/**\n * Inflate with a hard output ceiling.\n *\n * A one-shot gunzip allocates the entire output before anyone can refuse it —\n * gzip reaches ~1000:1 in practice, so a few hundred scanned bytes could ask\n * for an arbitrary allocation. The decoder is therefore driven in slices and\n * the output counted as it arrives; the moment the total would pass the cap,\n * feeding stops and the reply is refused.\n *\n * The trailer's ISIZE (declared inflated length) is used twice: as a cheap\n * refusal of honest bombs before any work, and as a truncation check at the\n * end — an inflater hands back a partial buffer for a truncated stream\n * without erroring, and a genuine device reply always declares honestly.\n */\nexport function gunzipCapped(data: Uint8Array, maxOutputBytes: number): Uint8Array {\n if (data.length < MIN_GZIP_BYTES) {\n throw new EraSdkError('gzip-error', 'compressed payload is too short to be a gzip stream');\n }\n if (data[0] !== 0x1f || data[1] !== 0x8b) {\n throw new EraSdkError('gzip-error', 'compressed payload is not a gzip stream');\n }\n const n = data.length;\n const isize =\n (data[n - 4]! | (data[n - 3]! << 8) | (data[n - 2]! << 16) | (data[n - 1]! << 24)) >>> 0;\n if (isize > maxOutputBytes) {\n throw new EraSdkError(\n 'gzip-error',\n `compressed payload declares ${isize} bytes, over the ${maxOutputBytes} byte ceiling`,\n );\n }\n\n const chunks: Uint8Array[] = [];\n let total = 0;\n let overflowed = false;\n let malformed: string | null = null;\n\n const gunzip = new Gunzip((chunk) => {\n if (overflowed) return;\n if (total + chunk.length > maxOutputBytes) {\n overflowed = true;\n return;\n }\n chunks.push(chunk);\n total += chunk.length;\n });\n\n try {\n for (let offset = 0; offset < n && !overflowed; offset += SLICE_BYTES) {\n const end = Math.min(offset + SLICE_BYTES, n);\n const isLast = end === n;\n gunzip.push(data.slice(offset, end), isLast);\n }\n } catch (e) {\n malformed = (e as Error).message ?? 'inflate error';\n }\n\n if (overflowed) {\n throw new EraSdkError(\n 'gzip-error',\n `compressed payload inflates past the ${maxOutputBytes} byte ceiling`,\n );\n }\n if (malformed !== null) {\n throw new EraSdkError('gzip-error', `compressed payload is malformed: ${malformed}`);\n }\n const out = concatBytes(...chunks);\n if (out.length !== isize) {\n throw new EraSdkError(\n 'gzip-error',\n `compressed payload inflated to ${out.length} bytes but declares ${isize} — truncated or malformed`,\n );\n }\n // The trailer CRC32 (little-endian, bytes n-8..n-5) must cover the inflated\n // output. The streaming inflater does not verify it, and the reference\n // implementation's native decoder does — without this check a corrupted\n // stream, or a CONCATENATED multi-member stream (whose final member's CRC\n // cannot cover the whole output), would be accepted here and refused there.\n const declaredCrc =\n (data[n - 8]! | (data[n - 7]! << 8) | (data[n - 6]! << 16) | (data[n - 5]! << 24)) >>> 0;\n if (crc32(out) !== declaredCrc) {\n throw new EraSdkError('gzip-error', 'compressed payload is malformed: CRC mismatch');\n }\n return out;\n}\n"],"mappings":";;;;AAMA,MAAM,iBAAiB;;AAGvB,MAAM,cAAc;;AAGpB,SAAgB,aAAa,MAA8B;CACzD,QAAA,GAAOA,OAAAA,SAAAA,CAAS,MAAM;EAAE,OAAO;EAAG,OAAO;CAAE,CAAC;AAC9C;;;;;;;;;;;;;;;AAgBA,SAAgB,aAAa,MAAkB,gBAAoC;CACjF,IAAI,KAAK,SAAS,gBAChB,MAAM,IAAIC,eAAAA,YAAY,cAAc,qDAAqD;CAE3F,IAAI,KAAK,OAAO,MAAQ,KAAK,OAAO,KAClC,MAAM,IAAIA,eAAAA,YAAY,cAAc,yCAAyC;CAE/E,MAAM,IAAI,KAAK;CACf,MAAM,SACH,KAAK,IAAI,KAAO,KAAK,IAAI,MAAO,IAAM,KAAK,IAAI,MAAO,KAAO,KAAK,IAAI,MAAO,QAAS;CACzF,IAAI,QAAQ,gBACV,MAAM,IAAIA,eAAAA,YACR,cACA,+BAA+B,MAAM,mBAAmB,eAAe,cACzE;CAGF,MAAM,SAAuB,CAAC;CAC9B,IAAI,QAAQ;CACZ,IAAI,aAAa;CACjB,IAAI,YAA2B;CAE/B,MAAM,SAAS,IAAIC,OAAAA,QAAQ,UAAU;EACnC,IAAI,YAAY;EAChB,IAAI,QAAQ,MAAM,SAAS,gBAAgB;GACzC,aAAa;GACb;EACF;EACA,OAAO,KAAK,KAAK;EACjB,SAAS,MAAM;CACjB,CAAC;CAED,IAAI;EACF,KAAK,IAAI,SAAS,GAAG,SAAS,KAAK,CAAC,YAAY,UAAU,aAAa;GACrE,MAAM,MAAM,KAAK,IAAI,SAAS,aAAa,CAAC;GAC5C,MAAM,SAAS,QAAQ;GACvB,OAAO,KAAK,KAAK,MAAM,QAAQ,GAAG,GAAG,MAAM;EAC7C;CACF,SAAS,GAAG;EACV,YAAa,EAAY,WAAW;CACtC;CAEA,IAAI,YACF,MAAM,IAAID,eAAAA,YACR,cACA,wCAAwC,eAAe,cACzD;CAEF,IAAI,cAAc,MAChB,MAAM,IAAIA,eAAAA,YAAY,cAAc,oCAAoC,WAAW;CAErF,MAAM,MAAME,eAAAA,YAAY,GAAG,MAAM;CACjC,IAAI,IAAI,WAAW,OACjB,MAAM,IAAIF,eAAAA,YACR,cACA,kCAAkC,IAAI,OAAO,sBAAsB,MAAM,0BAC3E;CAOF,MAAM,eACH,KAAK,IAAI,KAAO,KAAK,IAAI,MAAO,IAAM,KAAK,IAAI,MAAO,KAAO,KAAK,IAAI,MAAO,QAAS;CACzF,IAAIG,eAAAA,MAAM,GAAG,MAAM,aACjB,MAAM,IAAIH,eAAAA,YAAY,cAAc,+CAA+C;CAErF,OAAO;AACT"}
|