@ledgerhq/hw-app-eth 7.0.0-nightly.2 → 7.0.0-nightly.20251121023744

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 (134) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/.unimportedrc.json +3 -28
  3. package/CHANGELOG.md +994 -17
  4. package/README.md +100 -0
  5. package/jest.config.ts +18 -0
  6. package/lib/Eth.d.ts +3 -18
  7. package/lib/Eth.d.ts.map +1 -1
  8. package/lib/Eth.js +160 -198
  9. package/lib/Eth.js.map +1 -1
  10. package/lib/errors.d.ts +3 -0
  11. package/lib/errors.d.ts.map +1 -1
  12. package/lib/errors.js +2 -1
  13. package/lib/errors.js.map +1 -1
  14. package/lib/modules/Domains/index.js +6 -15
  15. package/lib/modules/Domains/index.js.map +1 -1
  16. package/lib/modules/EIP712/index.d.ts.map +1 -1
  17. package/lib/modules/EIP712/index.js +112 -125
  18. package/lib/modules/EIP712/index.js.map +1 -1
  19. package/lib/modules/EIP712/types.d.ts +1 -0
  20. package/lib/modules/EIP712/types.d.ts.map +1 -1
  21. package/lib/modules/EIP712/utils.d.ts +1 -0
  22. package/lib/modules/EIP712/utils.d.ts.map +1 -1
  23. package/lib/modules/EIP712/utils.js +14 -24
  24. package/lib/modules/EIP712/utils.js.map +1 -1
  25. package/lib/modules/Uniswap/constants.d.ts.map +1 -1
  26. package/lib/modules/Uniswap/constants.js +1 -0
  27. package/lib/modules/Uniswap/constants.js.map +1 -1
  28. package/lib/modules/Uniswap/decoders.d.ts.map +1 -1
  29. package/lib/modules/Uniswap/decoders.js +8 -3
  30. package/lib/modules/Uniswap/decoders.js.map +1 -1
  31. package/lib/modules/Uniswap/index.d.ts +2 -1
  32. package/lib/modules/Uniswap/index.d.ts.map +1 -1
  33. package/lib/modules/Uniswap/index.js +11 -20
  34. package/lib/modules/Uniswap/index.js.map +1 -1
  35. package/lib/modules/Uniswap/types.d.ts +1 -1
  36. package/lib/modules/Uniswap/types.d.ts.map +1 -1
  37. package/lib/services/ledger/contracts.js +4 -13
  38. package/lib/services/ledger/contracts.js.map +1 -1
  39. package/lib/services/ledger/erc20.d.ts +2 -1
  40. package/lib/services/ledger/erc20.d.ts.map +1 -1
  41. package/lib/services/ledger/erc20.js +16 -32
  42. package/lib/services/ledger/erc20.js.map +1 -1
  43. package/lib/services/ledger/index.d.ts.map +1 -1
  44. package/lib/services/ledger/index.js +34 -32
  45. package/lib/services/ledger/index.js.map +1 -1
  46. package/lib/services/ledger/loadConfig.d.ts.map +1 -1
  47. package/lib/services/ledger/loadConfig.js +7 -1
  48. package/lib/services/ledger/loadConfig.js.map +1 -1
  49. package/lib/services/ledger/nfts.js +9 -19
  50. package/lib/services/ledger/nfts.js.map +1 -1
  51. package/lib/services/types.d.ts +3 -0
  52. package/lib/services/types.d.ts.map +1 -1
  53. package/lib/utils.d.ts +56 -9
  54. package/lib/utils.d.ts.map +1 -1
  55. package/lib/utils.js +175 -81
  56. package/lib/utils.js.map +1 -1
  57. package/lib-es/Eth.d.ts +3 -18
  58. package/lib-es/Eth.d.ts.map +1 -1
  59. package/lib-es/Eth.js +160 -198
  60. package/lib-es/Eth.js.map +1 -1
  61. package/lib-es/errors.d.ts +3 -0
  62. package/lib-es/errors.d.ts.map +1 -1
  63. package/lib-es/errors.js +1 -0
  64. package/lib-es/errors.js.map +1 -1
  65. package/lib-es/modules/Domains/index.js +6 -15
  66. package/lib-es/modules/Domains/index.js.map +1 -1
  67. package/lib-es/modules/EIP712/index.d.ts.map +1 -1
  68. package/lib-es/modules/EIP712/index.js +112 -125
  69. package/lib-es/modules/EIP712/index.js.map +1 -1
  70. package/lib-es/modules/EIP712/types.d.ts +1 -0
  71. package/lib-es/modules/EIP712/types.d.ts.map +1 -1
  72. package/lib-es/modules/EIP712/utils.d.ts +1 -0
  73. package/lib-es/modules/EIP712/utils.d.ts.map +1 -1
  74. package/lib-es/modules/EIP712/utils.js +14 -24
  75. package/lib-es/modules/EIP712/utils.js.map +1 -1
  76. package/lib-es/modules/Uniswap/constants.d.ts.map +1 -1
  77. package/lib-es/modules/Uniswap/constants.js +1 -0
  78. package/lib-es/modules/Uniswap/constants.js.map +1 -1
  79. package/lib-es/modules/Uniswap/decoders.d.ts.map +1 -1
  80. package/lib-es/modules/Uniswap/decoders.js +8 -3
  81. package/lib-es/modules/Uniswap/decoders.js.map +1 -1
  82. package/lib-es/modules/Uniswap/index.d.ts +2 -1
  83. package/lib-es/modules/Uniswap/index.d.ts.map +1 -1
  84. package/lib-es/modules/Uniswap/index.js +11 -20
  85. package/lib-es/modules/Uniswap/index.js.map +1 -1
  86. package/lib-es/modules/Uniswap/types.d.ts +1 -1
  87. package/lib-es/modules/Uniswap/types.d.ts.map +1 -1
  88. package/lib-es/services/ledger/contracts.js +4 -13
  89. package/lib-es/services/ledger/contracts.js.map +1 -1
  90. package/lib-es/services/ledger/erc20.d.ts +2 -1
  91. package/lib-es/services/ledger/erc20.d.ts.map +1 -1
  92. package/lib-es/services/ledger/erc20.js +16 -32
  93. package/lib-es/services/ledger/erc20.js.map +1 -1
  94. package/lib-es/services/ledger/index.d.ts.map +1 -1
  95. package/lib-es/services/ledger/index.js +34 -32
  96. package/lib-es/services/ledger/index.js.map +1 -1
  97. package/lib-es/services/ledger/loadConfig.d.ts.map +1 -1
  98. package/lib-es/services/ledger/loadConfig.js +7 -1
  99. package/lib-es/services/ledger/loadConfig.js.map +1 -1
  100. package/lib-es/services/ledger/nfts.js +9 -19
  101. package/lib-es/services/ledger/nfts.js.map +1 -1
  102. package/lib-es/services/types.d.ts +3 -0
  103. package/lib-es/services/types.d.ts.map +1 -1
  104. package/lib-es/utils.d.ts +56 -9
  105. package/lib-es/utils.d.ts.map +1 -1
  106. package/lib-es/utils.js +148 -81
  107. package/lib-es/utils.js.map +1 -1
  108. package/package.json +19 -15
  109. package/src/Eth.ts +51 -82
  110. package/src/errors.ts +3 -0
  111. package/src/modules/EIP712/index.ts +17 -4
  112. package/src/modules/Uniswap/constants.ts +1 -0
  113. package/src/modules/Uniswap/decoders.ts +10 -3
  114. package/src/modules/Uniswap/index.ts +9 -8
  115. package/src/modules/Uniswap/types.ts +2 -1
  116. package/src/services/ledger/erc20.ts +16 -19
  117. package/src/services/ledger/index.ts +50 -22
  118. package/src/services/ledger/loadConfig.ts +4 -1
  119. package/src/services/ledger/nfts.ts +1 -1
  120. package/src/services/types.ts +12 -0
  121. package/src/utils.ts +170 -85
  122. package/tests/EIP712/filtered-signMessage.unit.test.ts +28 -116
  123. package/tests/EIP712/noFilter-signMessage.unit.test.ts +0 -2
  124. package/tests/ERC20/ERC20-CAL-KO.unit.test.ts +14 -25
  125. package/tests/ERC20/ERC20-CAL-OK.unit.test.ts +15 -10
  126. package/tests/Eth.unit.test.ts +242 -314
  127. package/tests/Uniswap/decoders.unit.test.ts +10 -0
  128. package/tests/Uniswap/index.unit.test.ts +17 -26
  129. package/tests/fixtures/messages/15-permit.json +3 -3
  130. package/tests/fixtures/messages/16-permit2.json +3 -3
  131. package/tests/fixtures/messages/17-uniswapx.json +5 -5
  132. package/tests/fixtures/utils.ts +17 -18
  133. package/tests/ledgerService.unit.test.ts +5 -7
  134. package/tests/utils.unit.test.ts +341 -0
package/lib-es/utils.js CHANGED
@@ -1,26 +1,29 @@
1
1
  import { BigNumber } from "bignumber.js";
2
- import { ERC20_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS, ERC1155_CLEAR_SIGNED_SELECTORS, } from "@ledgerhq/evm-tools/selectors/index";
3
- import { encode, decode } from "@ethersproject/rlp";
4
- export { ERC20_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS, ERC1155_CLEAR_SIGNED_SELECTORS, };
2
+ import * as rlp from "@ethersproject/rlp";
3
+ import { ERC20_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS, ERC1155_CLEAR_SIGNED_SELECTORS, DAPP_SELECTORS, } from "@ledgerhq/evm-tools/selectors/index";
4
+ export { ERC20_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS, ERC1155_CLEAR_SIGNED_SELECTORS, DAPP_SELECTORS, };
5
5
  export const padHexString = (str) => {
6
6
  return str.length % 2 ? "0" + str : str;
7
7
  };
8
8
  export function splitPath(path) {
9
- const result = [];
10
- const components = path.split("/");
11
- components.forEach(element => {
12
- let number = parseInt(element, 10);
13
- if (isNaN(number)) {
9
+ const splittedPath = [];
10
+ const paths = path.split("/");
11
+ paths.forEach(path => {
12
+ let value = parseInt(path, 10);
13
+ if (isNaN(value)) {
14
14
  return; // FIXME shouldn't it throws instead?
15
15
  }
16
- if (element.length > 1 && element[element.length - 1] === "'") {
17
- number += 0x80000000;
16
+ // Detect hardened paths
17
+ if (path.length > 1 && path[path.length - 1] === "'") {
18
+ value += 0x80000000;
18
19
  }
19
- result.push(number);
20
+ splittedPath.push(value);
20
21
  });
21
- return result;
22
+ return splittedPath;
22
23
  }
23
24
  export function hexBuffer(str) {
25
+ if (!str)
26
+ return Buffer.alloc(0);
24
27
  const strWithoutPrefix = str.startsWith("0x") ? str.slice(2) : str;
25
28
  return Buffer.from(padHexString(strWithoutPrefix), "hex");
26
29
  }
@@ -29,75 +32,6 @@ export function maybeHexBuffer(str) {
29
32
  return null;
30
33
  return hexBuffer(str);
31
34
  }
32
- export const decodeTxInfo = (rawTx) => {
33
- const VALID_TYPES = [1, 2];
34
- const txType = VALID_TYPES.includes(rawTx[0]) ? rawTx[0] : null;
35
- const rlpData = txType === null ? rawTx : rawTx.slice(1);
36
- const rlpTx = decode(rlpData).map(hex => Buffer.from(hex.slice(2), "hex"));
37
- let chainIdTruncated = 0;
38
- const rlpDecoded = decode(rlpData);
39
- let decodedTx;
40
- if (txType === 2) {
41
- // EIP1559
42
- decodedTx = {
43
- data: rlpDecoded[7],
44
- to: rlpDecoded[5],
45
- chainId: rlpTx[0],
46
- };
47
- }
48
- else if (txType === 1) {
49
- // EIP2930
50
- decodedTx = {
51
- data: rlpDecoded[6],
52
- to: rlpDecoded[4],
53
- chainId: rlpTx[0],
54
- };
55
- }
56
- else {
57
- // Legacy tx
58
- decodedTx = {
59
- data: rlpDecoded[5],
60
- to: rlpDecoded[3],
61
- // Default to 1 for non EIP 155 txs
62
- chainId: rlpTx.length > 6 ? rlpTx[6] : Buffer.from("01", "hex"),
63
- };
64
- }
65
- const chainIdSrc = decodedTx.chainId;
66
- let chainId = new BigNumber(0);
67
- if (chainIdSrc) {
68
- // Using BigNumber because chainID could be any uint256.
69
- chainId = new BigNumber(chainIdSrc.toString("hex"), 16);
70
- const chainIdTruncatedBuf = Buffer.alloc(4);
71
- if (chainIdSrc.length > 4) {
72
- chainIdSrc.copy(chainIdTruncatedBuf);
73
- }
74
- else {
75
- chainIdSrc.copy(chainIdTruncatedBuf, 4 - chainIdSrc.length);
76
- }
77
- chainIdTruncated = chainIdTruncatedBuf.readUInt32BE(0);
78
- }
79
- let vrsOffset = 0;
80
- if (txType === null && rlpTx.length > 6) {
81
- const rlpVrs = Buffer.from(encode(rlpTx.slice(-3)).slice(2), "hex");
82
- vrsOffset = rawTx.length - (rlpVrs.length - 1);
83
- // First byte > 0xf7 means the length of the list length doesn't fit in a single byte.
84
- if (rlpVrs[0] > 0xf7) {
85
- // Increment vrsOffset to account for that extra byte.
86
- vrsOffset++;
87
- // Compute size of the list length.
88
- const sizeOfListLen = rlpVrs[0] - 0xf7;
89
- // Increase rlpOffset by the size of the list length.
90
- vrsOffset += sizeOfListLen - 1;
91
- }
92
- }
93
- return {
94
- decodedTx,
95
- txType,
96
- chainId,
97
- chainIdTruncated,
98
- vrsOffset,
99
- };
100
- };
101
35
  /**
102
36
  * @ignore for the README
103
37
  *
@@ -129,4 +63,137 @@ export const mergeResolutions = (resolutionsArray) => {
129
63
  }
130
64
  return mergedResolutions;
131
65
  };
66
+ /**
67
+ * @ignore for the README
68
+ *
69
+ * Ledger devices are returning v with potentially EIP-155 already applied when using legacy transactions.
70
+ * Because that v value is only represented as a single byte, we need to replicate what would be the
71
+ * overflow happening on the device while applying EIP-155 and recover the original parity.
72
+ *
73
+ * @param vFromDevice
74
+ * @param chainIdUint32
75
+ * @returns
76
+ */
77
+ export const getParity = (vFromDevice, chainId, transactionType) => {
78
+ if (transactionType)
79
+ return vFromDevice;
80
+ // The device use a 4 bytes integer to represent the chainId and keeps the highest bytes
81
+ const chainIdUint32 = getChainIdAsUint32(chainId);
82
+ // Then applies EIP-155 to this chainId
83
+ const chainIdWithEIP155 = chainIdUint32 * 2 + 35;
84
+ // Since it's a single byte, we need to apply the overflow after reaching the max 0xff value and starting again to 0x00
85
+ // for both possible values, the chainId with EIP155 and a 0 or 1 parity included
86
+ const chainIdWithOverflowZero = chainIdWithEIP155 % 256;
87
+ const chainIdWithOverflowOne = (chainIdWithEIP155 + 1) % 256;
88
+ if (chainIdWithOverflowZero === vFromDevice) {
89
+ return 0;
90
+ }
91
+ else if (chainIdWithOverflowOne === vFromDevice) {
92
+ return 1;
93
+ }
94
+ throw new Error("Invalid v value");
95
+ };
96
+ /**
97
+ * @ignore for the README
98
+ *
99
+ * Helper to convert a chainId from a BigNumber to a 4 bytes integer.
100
+ * ChainIds are uint256, but the device limits them to 4 bytes
101
+ *
102
+ * @param {Number|BigNumber} chainId
103
+ * @returns {Number}
104
+ */
105
+ export const getChainIdAsUint32 = (chainId) => {
106
+ const chainIdBuff = Buffer.from(padHexString(new BigNumber(chainId).toString(16)), "hex");
107
+ const chainIdUint32 = chainIdBuff.subarray(0, 4);
108
+ return parseInt(chainIdUint32.toString("hex"), 16);
109
+ };
110
+ /**
111
+ * @ignore for the README
112
+ *
113
+ * Depending on the transaction type you're trying to sign with the device, the v value will be different.
114
+ * For legacy transactions, the v value is used to store the chainId, and that chainId can be a uint256,
115
+ * and some math operation should be applied to it in order to comply with EIP-155 for replay attacks.
116
+ *
117
+ * In order to prevent breaking changes at the time, the `v` value has been kept as a single byte
118
+ * which forces us to replicate an overflow happening on the device to get the correct `v` value
119
+ *
120
+ * @param {number} vFromDevice
121
+ * @param {BigNumber} chainId
122
+ * @param {Transaction["type"]} transactionType
123
+ * @returns {string} hexa string of the v value
124
+ */
125
+ export const getV = (vFromDevice, chainId, transactionType) => {
126
+ if (chainId.isZero())
127
+ return vFromDevice.toString(16);
128
+ const parity = getParity(vFromDevice, chainId, transactionType);
129
+ return !transactionType
130
+ ? // Legacy transactions (type 0) should apply EIP-155
131
+ // EIP-155: rlp[(nonce, gasprice, startgas, to, value, data, chainid, 0, 0)]
132
+ padHexString(chainId.times(2).plus(35).plus(parity).toString(16))
133
+ : // Transactions after type 1 should only use partity (00/01) as their v value
134
+ // EIP-2930: 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, *signatureYParity*, signatureR, signatureS])
135
+ // EIP-1559: 0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, *signature_y_parity*, signature_r, signature_s])
136
+ // EIP-4844: 0x03 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, *y_parity*, r, s])
137
+ // EIP-7702: 0x05 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, value, data, access_list, authorization_list, *signature_y_parity*, signature_r, signature_s])
138
+ padHexString(parity.toString(16));
139
+ };
140
+ /**
141
+ * @ignore for the README
142
+ *
143
+ * In order to prevent the device from considering a transaction RLP as complete before it actually is
144
+ * we need to split the RLP into chunks which could not be mistaken for a complete transaction.
145
+ * This is true for legacy transaction, where the `v` value is used to store the chainId
146
+ *
147
+ * @param {Buffer} transactionRlp
148
+ * @param {Buffer }derivationPath
149
+ * @param {Transaction["type"]} transactionType
150
+ *
151
+ * @returns {Buffer[]}
152
+ */
153
+ export const safeChunkTransaction = (transactionRlp, derivationPath, transactionType) => {
154
+ const maxChunkSize = 255;
155
+ // The full payload is the derivation path + the complete RLP of the transaction
156
+ const payload = Buffer.concat([derivationPath, transactionRlp]);
157
+ if (payload.length <= maxChunkSize)
158
+ return [payload];
159
+ if (transactionType) {
160
+ const chunks = Math.ceil(payload.length / maxChunkSize);
161
+ return new Array(chunks)
162
+ .fill(null)
163
+ .map((_, i) => payload.subarray(i * maxChunkSize, (i + 1) * maxChunkSize));
164
+ }
165
+ // Decode the RLP of the full transaction and keep only the last 3 elements (v, r, s)
166
+ const decodedVrs = rlp.decode(transactionRlp).slice(-3);
167
+ // Encode those values back to RLP in order to get the length of this serialized list
168
+ // Result should be something like [0xc0 + list payload length, list.map(rlp)]
169
+ // since only v can be used to store the chainId in legacy transactions
170
+ const encodedVrs = rlp.encode(decodedVrs);
171
+ // Since chainIds are uint256, the list payload length can be 1B (v rlp description) + 32B (v) + 1B (r) + 1B (s) = 35B max (< 55B)
172
+ // Therefore, the RLP of this vrs list should be prefixed by a value between [0xc1, 0xe3] (0xc0 + 35B = 0xe3 max)
173
+ // @see https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/
174
+ // `encodedVrs` is then everything but the first byte of this serialization
175
+ const encodedVrsBuff = hexBuffer(encodedVrs).subarray(1);
176
+ // Since we want to avoid chunking just before the v,r,s values,
177
+ // we just check the size of that payload and detect
178
+ // if it would fit perfectly in 255B chunks
179
+ // if it does, we chunk smaller parts
180
+ let chunkSize = 0;
181
+ const lastChunkSize = payload.length % maxChunkSize;
182
+ if (lastChunkSize === 0 || lastChunkSize > encodedVrsBuff.length) {
183
+ chunkSize = maxChunkSize;
184
+ }
185
+ else {
186
+ for (let i = 1; i <= maxChunkSize; i++) {
187
+ const lastChunkSize = payload.length % (maxChunkSize - i);
188
+ if (lastChunkSize === 0 || lastChunkSize > encodedVrsBuff.length) {
189
+ chunkSize = maxChunkSize - i;
190
+ break;
191
+ }
192
+ }
193
+ }
194
+ const chunks = Math.ceil(payload.length / chunkSize);
195
+ return new Array(chunks)
196
+ .fill(null)
197
+ .map((_, i) => payload.subarray(i * chunkSize, (i + 1) * chunkSize));
198
+ };
132
199
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/hw-app-eth",
3
- "version": "7.0.0-nightly.2",
3
+ "version": "7.0.0-nightly.20251121023744",
4
4
  "description": "Ledger Hardware Wallet Ethereum Application API",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -26,26 +26,28 @@
26
26
  "types": "lib/Eth.d.ts",
27
27
  "license": "Apache-2.0",
28
28
  "dependencies": {
29
- "@ethersproject/abi": "^5.5.0",
30
- "@ethersproject/rlp": "^5.5.0",
31
- "axios": "1.7.7",
29
+ "@ethersproject/abi": "^5.7.0",
30
+ "@ethersproject/rlp": "^5.7.0",
31
+ "@ethersproject/transactions": "^5.7.0",
32
+ "axios": "1.12.2",
32
33
  "bignumber.js": "^9.1.2",
33
34
  "semver": "^7.3.5",
34
- "@ledgerhq/cryptoassets-evm-signatures": "^14.0.0-nightly.1",
35
- "@ledgerhq/domain-service": "^1.2.6-nightly.2",
36
- "@ledgerhq/errors": "^6.19.1",
37
- "@ledgerhq/evm-tools": "^1.2.3-nightly.1",
38
- "@ledgerhq/hw-transport": "^6.31.4",
39
- "@ledgerhq/hw-transport-mocker": "^6.29.4",
40
- "@ledgerhq/logs": "^6.12.0",
41
- "@ledgerhq/types-live": "^6.52.0-nightly.2"
35
+ "@ledgerhq/domain-service": "^1.4.1-nightly.20251121023744",
36
+ "@ledgerhq/errors": "^6.27.0",
37
+ "@ledgerhq/evm-tools": "^1.8.1-nightly.20251121023744",
38
+ "@ledgerhq/hw-transport": "6.31.13",
39
+ "@ledgerhq/hw-transport-mocker": "^6.29.13",
40
+ "@ledgerhq/logs": "^6.13.0",
41
+ "@ledgerhq/types-live": "^6.89.0-nightly.20251121023744"
42
42
  },
43
43
  "gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
44
44
  "devDependencies": {
45
+ "@ethersproject/bignumber": "^5.7.0",
46
+ "@ethersproject/constants": "^5.7.0",
47
+ "@ethersproject/units": "^5.7.0",
45
48
  "@types/jest": "^29.5.10",
46
- "@types/node": "^20.8.10",
49
+ "@types/node": "^22.10.10",
47
50
  "documentation": "14.0.2",
48
- "ethers": "5.7.2",
49
51
  "jest": "^29.7.0",
50
52
  "nock": "^13.0.5",
51
53
  "rimraf": "^4.4.1",
@@ -60,9 +62,11 @@
60
62
  },
61
63
  "scripts": {
62
64
  "clean": "rimraf lib lib-es",
63
- "build": "tsc && tsc -m ES6 --outDir lib-es",
65
+ "build": "tsc && tsc -m esnext --moduleResolution bundler --outDir lib-es",
66
+ "coverage": "jest --coverage --passWithNoTests",
64
67
  "prewatch": "pnpm build",
65
68
  "watch": "tsc --watch",
69
+ "watch:es": "tsc --watch -m esnext --moduleResolution bundler --outDir lib-es",
66
70
  "doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
67
71
  "lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
68
72
  "lint:fix": "pnpm lint --fix",
package/src/Eth.ts CHANGED
@@ -1,39 +1,28 @@
1
- /********************************************************************************
2
- * Ledger Node JS API
3
- * (c) 2016-2017 Ledger
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- ********************************************************************************/
17
- /* eslint @typescript-eslint/no-duplicate-enum-values: 1 */
18
- // FIXME drop:
19
- import type Transport from "@ledgerhq/hw-transport";
1
+ /* eslint-disable @typescript-eslint/no-duplicate-enum-values */
2
+
3
+ import { log } from "@ledgerhq/logs";
20
4
  import { BigNumber } from "bignumber.js";
21
- // NB: these are temporary import for the deprecated fallback mechanism
5
+ import type Transport from "@ledgerhq/hw-transport";
6
+ import { EIP712Message } from "@ledgerhq/types-live";
7
+ import { parse as parseTransaction } from "@ethersproject/transactions";
22
8
  import { LedgerEthTransactionResolution, LoadConfig, ResolutionConfig } from "./services/types";
23
- import { log } from "@ledgerhq/logs";
24
9
  import {
25
- decodeTxInfo,
10
+ EthAppNftNotSupported,
11
+ EthAppPleaseEnableContractData,
12
+ CeloAppPleaseEnableContractData,
13
+ } from "./errors";
14
+ import { signEIP712HashedMessage, signEIP712Message } from "./modules/EIP712";
15
+ import { domainResolutionFlow } from "./modules/Domains";
16
+ import ledgerService from "./services/ledger";
17
+ import {
18
+ safeChunkTransaction,
19
+ getV,
26
20
  hexBuffer,
27
21
  intAsHexBytes,
28
22
  maybeHexBuffer,
29
23
  padHexString,
30
24
  splitPath,
31
25
  } from "./utils";
32
- import { domainResolutionFlow } from "./modules/Domains";
33
- import ledgerService from "./services/ledger";
34
- import { EthAppNftNotSupported, EthAppPleaseEnableContractData } from "./errors";
35
- import { signEIP712HashedMessage, signEIP712Message } from "./modules/EIP712";
36
- import { EIP712Message } from "@ledgerhq/types-live";
37
26
 
38
27
  export { ledgerService };
39
28
  export * from "./utils";
@@ -47,8 +36,12 @@ const starkQuantizationTypeMap = {
47
36
  erc721mintable: 5,
48
37
  };
49
38
 
50
- const remapTransactionRelatedErrors = e => {
39
+ const remapTransactionRelatedErrors = (e: any, chainId: BigNumber) => {
51
40
  if (e && e.statusCode === 0x6a80) {
41
+ if (chainId.toNumber() === 42220) {
42
+ return new CeloAppPleaseEnableContractData();
43
+ }
44
+
52
45
  return new EthAppPleaseEnableContractData(
53
46
  "Please enable Blind signing or Contract data in the Ethereum app Settings",
54
47
  );
@@ -193,6 +186,14 @@ export default class Eth {
193
186
  v: string;
194
187
  r: string;
195
188
  }> {
189
+ enum APDU_FIELDS {
190
+ CLA = 0xe0,
191
+ INS = 0x04,
192
+ P1_FIRST_CHUNK = 0x00,
193
+ P1_FOLLOWING_CHUNK = 0x80,
194
+ P2 = 0x00,
195
+ }
196
+
196
197
  if (resolution === undefined) {
197
198
  console.warn(
198
199
  "hw-app-eth: signTransaction(path, rawTxHex, resolution): " +
@@ -247,68 +248,36 @@ export default class Eth {
247
248
  }
248
249
 
249
250
  const rawTx = Buffer.from(rawTxHex, "hex");
250
- const { vrsOffset, txType, chainId, chainIdTruncated } = decodeTxInfo(rawTx);
251
+ const parsedTransaction = parseTransaction(`0x${rawTx.toString("hex")}`);
252
+ const chainId = new BigNumber(parsedTransaction.chainId);
251
253
 
252
254
  const paths = splitPath(path);
253
- let response;
254
- let offset = 0;
255
- while (offset !== rawTx.length) {
256
- const first = offset === 0;
257
- const maxChunkSize = first ? 150 - 1 - paths.length * 4 : 150;
258
- let chunkSize = offset + maxChunkSize > rawTx.length ? rawTx.length - offset : maxChunkSize;
259
-
260
- if (vrsOffset != 0 && offset + chunkSize >= vrsOffset) {
261
- // Make sure that the chunk doesn't end right on the EIP 155 marker if set
262
- chunkSize = rawTx.length - offset;
263
- }
264
-
265
- const buffer = Buffer.alloc(first ? 1 + paths.length * 4 + chunkSize : chunkSize);
266
-
267
- if (first) {
268
- buffer[0] = paths.length;
269
- paths.forEach((element, index) => {
270
- buffer.writeUInt32BE(element, 1 + 4 * index);
271
- });
272
- rawTx.copy(buffer, 1 + 4 * paths.length, offset, offset + chunkSize);
273
- } else {
274
- rawTx.copy(buffer, 0, offset, offset + chunkSize);
275
- }
255
+ const derivationPathBuff = Buffer.alloc(1 + paths.length * 4);
256
+ derivationPathBuff[0] = paths.length;
257
+ paths.forEach((element, index) => {
258
+ derivationPathBuff.writeUInt32BE(element, 1 + 4 * index);
259
+ });
276
260
 
261
+ const payloadChunks = safeChunkTransaction(rawTx, derivationPathBuff, parsedTransaction.type);
262
+ let response;
263
+ for (const chunk of payloadChunks) {
264
+ const isFirstChunk = chunk === payloadChunks[0];
277
265
  response = await this.transport
278
- .send(0xe0, 0x04, first ? 0x00 : 0x80, 0x00, buffer)
266
+ .send(
267
+ APDU_FIELDS.CLA,
268
+ APDU_FIELDS.INS,
269
+ isFirstChunk ? APDU_FIELDS.P1_FIRST_CHUNK : APDU_FIELDS.P1_FOLLOWING_CHUNK,
270
+ APDU_FIELDS.P2,
271
+ chunk,
272
+ )
279
273
  .catch(e => {
280
- throw remapTransactionRelatedErrors(e);
274
+ throw remapTransactionRelatedErrors(e, chainId);
281
275
  });
282
-
283
- offset += chunkSize;
284
- }
285
-
286
- const response_byte: number = response[0];
287
- let v = "";
288
-
289
- if (chainId.times(2).plus(35).plus(1).isGreaterThan(255)) {
290
- const oneByteChainId = (chainIdTruncated * 2 + 35) % 256;
291
-
292
- const ecc_parity = Math.abs(response_byte - oneByteChainId);
293
-
294
- if (txType != null) {
295
- // For EIP2930 and EIP1559 tx, v is simply the parity.
296
- v = ecc_parity % 2 == 1 ? "00" : "01";
297
- } else {
298
- // Legacy type transaction with a big chain ID
299
- v = chainId.times(2).plus(35).plus(ecc_parity).toString(16);
300
- }
301
- } else {
302
- v = response_byte.toString(16);
303
- }
304
-
305
- // Make sure v has is prefixed with a 0 if its length is odd ("1" -> "01").
306
- if (v.length % 2 == 1) {
307
- v = "0" + v;
308
276
  }
309
277
 
310
- const r = response.slice(1, 1 + 32).toString("hex");
311
- const s = response.slice(1 + 32, 1 + 32 + 32).toString("hex");
278
+ const v = getV(response[0], chainId, parsedTransaction.type);
279
+ const r = response.subarray(1, 1 + 32).toString("hex");
280
+ const s = response.subarray(1 + 32, 1 + 32 + 32).toString("hex");
312
281
  return { v, r, s };
313
282
  }
314
283
 
package/src/errors.ts CHANGED
@@ -4,3 +4,6 @@ export const EthAppPleaseEnableContractData = createCustomErrorClass(
4
4
  "EthAppPleaseEnableContractData",
5
5
  );
6
6
  export const EthAppNftNotSupported = createCustomErrorClass("EthAppNftNotSupported");
7
+ export const CeloAppPleaseEnableContractData = createCustomErrorClass(
8
+ "CeloAppPleaseEnableContractData",
9
+ );
@@ -120,7 +120,8 @@ const makeRecursiveFieldStructImplem = ({
120
120
  await recursiveFieldStructImplem([typeDescription, restSizes], entry, entryPath);
121
121
  }
122
122
  } else if (isCustomType) {
123
- for (const [fieldName, fieldValue] of Object.entries(data as EIP712Message["message"])) {
123
+ for (const fieldName of Object.keys(typesMap[typeDescription?.name || ""])) {
124
+ const fieldValue = data[fieldName];
124
125
  const fieldType = typesMap[typeDescription?.name || ""]?.[fieldName];
125
126
 
126
127
  if (fieldType) {
@@ -389,7 +390,12 @@ async function sendFilteringInfo(
389
390
  if (isTokenAddress && coinRef !== undefined) {
390
391
  const { token, deviceTokenIndex } = coinRefsTokensMap[coinRef];
391
392
  if (deviceTokenIndex === undefined) {
392
- const payload = await byContractAddressAndChainId(token, chainId, erc20SignaturesBlob);
393
+ const payload = await byContractAddressAndChainId(
394
+ token,
395
+ chainId,
396
+ erc20SignaturesBlob,
397
+ loadConfig,
398
+ );
393
399
  if (payload) {
394
400
  enum PROVIDE_TOKEN_INFOS_APDU_FIELDS {
395
401
  CLA = 0xe0,
@@ -521,14 +527,21 @@ export const signEIP712Message = async (
521
527
  P2_full = 0x01,
522
528
  }
523
529
  const { primaryType, types: unsortedTypes, domain, message } = typedMessage;
524
- const { calServiceURL } = getLoadConfig(loadConfig);
530
+ const { calServiceURL, staticEIP712SignaturesV1, staticEIP712SignaturesV2 } =
531
+ getLoadConfig(loadConfig);
525
532
  // Types are sorted by alphabetical order in order to get the same schema hash no matter the JSON format
526
533
  const types = sortObjectAlphabetically(unsortedTypes) as EIP712MessageTypes;
527
534
 
528
535
  const { version } = await getAppAndVersion(transport);
529
536
  const shouldUseV1Filters = !semver.gte(version, "1.11.1-0", { includePrerelease: true });
530
537
  const shouldUseDiscardedFields = semver.gte(version, "1.12.0-0", { includePrerelease: true });
531
- const filters = await getFiltersForMessage(typedMessage, shouldUseV1Filters, calServiceURL);
538
+ const filters = await getFiltersForMessage(
539
+ typedMessage,
540
+ shouldUseV1Filters,
541
+ calServiceURL,
542
+ staticEIP712SignaturesV1,
543
+ staticEIP712SignaturesV2,
544
+ );
532
545
  const coinRefsTokensMap = getCoinRefTokensMap(filters, shouldUseV1Filters, typedMessage);
533
546
 
534
547
  const typeEntries = Object.entries(types) as [
@@ -50,6 +50,7 @@ export const UNISWAP_COMMANDS: Record<`0x${string}`, UniswapSupportedCommand> =
50
50
  "0x02": "PERMIT2_PERMIT_BATCH",
51
51
  "0x03": "PERMIT2_TRANSFER_FROM_BATCH",
52
52
  "0x06": "PAY_PORTION",
53
+ "0x04": "SWEEP",
53
54
  };
54
55
 
55
56
  export const SWAP_COMMANDS: Partial<UniswapSupportedCommand>[] = [
@@ -1,9 +1,9 @@
1
- import { utils } from "ethers";
1
+ import { defaultAbiCoder } from "@ethersproject/abi";
2
2
  import { WETH_PER_CHAIN_ID } from "./constants";
3
3
  import { UniswapSupportedCommand } from "./types";
4
4
 
5
5
  const swapV2Decoder = (input: `0x${string}`): `0x${string}`[] => {
6
- const [, , , addresses] = utils.defaultAbiCoder.decode(
6
+ const [, , , addresses] = defaultAbiCoder.decode(
7
7
  ["address", "uint256", "uint256", "address[]", "bool"],
8
8
  input,
9
9
  );
@@ -12,7 +12,7 @@ const swapV2Decoder = (input: `0x${string}`): `0x${string}`[] => {
12
12
  };
13
13
 
14
14
  const swapV3Decoder = (input: `0x${string}`): `0x${string}`[] => {
15
- const [, , , path] = utils.defaultAbiCoder.decode(
15
+ const [, , , path] = defaultAbiCoder.decode(
16
16
  ["address", "uint256", "uint256", "bytes", "bool"],
17
17
  input,
18
18
  );
@@ -42,6 +42,12 @@ const wrapEthDecoder = (input: `0x${string}`, chainId: number | string): `0x${st
42
42
  return contract instanceof Error ? [] : [contract.toLowerCase()];
43
43
  };
44
44
 
45
+ const sweepDecoder = (input: `0x${string}`): `0x${string}`[] => {
46
+ const [token] = defaultAbiCoder.decode(["address", "address", "uint256"], input);
47
+
48
+ return [token.toLowerCase()];
49
+ };
50
+
45
51
  const noDecoder = () => [];
46
52
 
47
53
  export const UniswapDecoders: Record<
@@ -59,4 +65,5 @@ export const UniswapDecoders: Record<
59
65
  PERMIT2_PERMIT_BATCH: noDecoder,
60
66
  PERMIT2_TRANSFER_FROM_BATCH: noDecoder,
61
67
  PAY_PORTION: noDecoder,
68
+ SWEEP: sweepDecoder,
62
69
  };