@ledgerhq/hw-app-eth 6.22.1 → 6.23.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 +15 -0
- package/lib/Eth.d.ts +16 -0
- package/lib/Eth.d.ts.map +1 -1
- package/lib/Eth.js +11 -21
- package/lib/Eth.js.map +1 -1
- package/lib/errors.d.ts +7 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +7 -0
- package/lib/errors.js.map +1 -0
- package/lib/services/ledger/index.d.ts.map +1 -1
- package/lib/services/ledger/index.js +89 -54
- package/lib/services/ledger/index.js.map +1 -1
- package/lib/services/ledger/nfts.d.ts.map +1 -1
- package/lib/services/ledger/nfts.js +24 -9
- package/lib/services/ledger/nfts.js.map +1 -1
- package/lib/services/types.d.ts +10 -1
- package/lib/services/types.d.ts.map +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +4 -6
- package/lib/utils.js.map +1 -1
- package/lib-es/Eth.d.ts +16 -0
- package/lib-es/Eth.d.ts.map +1 -1
- package/lib-es/Eth.js +11 -21
- package/lib-es/Eth.js.map +1 -1
- package/lib-es/errors.d.ts +7 -0
- package/lib-es/errors.d.ts.map +1 -0
- package/lib-es/errors.js +4 -0
- package/lib-es/errors.js.map +1 -0
- package/lib-es/services/ledger/index.d.ts.map +1 -1
- package/lib-es/services/ledger/index.js +89 -54
- package/lib-es/services/ledger/index.js.map +1 -1
- package/lib-es/services/ledger/nfts.d.ts.map +1 -1
- package/lib-es/services/ledger/nfts.js +24 -9
- package/lib-es/services/ledger/nfts.js.map +1 -1
- package/lib-es/services/types.d.ts +10 -1
- package/lib-es/services/types.d.ts.map +1 -1
- package/lib-es/utils.d.ts.map +1 -1
- package/lib-es/utils.js +4 -6
- package/lib-es/utils.js.map +1 -1
- package/package.json +6 -5
- package/src/Eth.ts +17 -5
- package/src/errors.ts +8 -0
- package/src/services/ledger/index.ts +24 -18
- package/src/services/ledger/nfts.ts +26 -5
- package/src/services/types.ts +15 -1
- package/src/utils.ts +4 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/services/types.ts"],"names":[],"mappings":"AAAA,oBAAY,8BAA8B,GAAG;IAE3C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpB,cAAc,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE9D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,oBAAY,UAAU,GAAG;IACvB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAInC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,YAAY,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,oBAAY,2BAA2B,GAAG;IACxC,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/services/types.ts"],"names":[],"mappings":"AAAA,oBAAY,8BAA8B,GAAG;IAE3C,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE3B,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAEpB,cAAc,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE9D,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,oBAAY,UAAU,GAAG;IACvB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAInC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,YAAY,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,oBAAY,gBAAgB,GAAG;IAE7B,GAAG,CAAC,EAAE,OAAO,CAAC;IAEd,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,oBAAY,2BAA2B,GAAG;IACxC,kBAAkB,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,UAAU,EACtB,gBAAgB,EAAE,gBAAgB,KAC/B,OAAO,CAAC,8BAA8B,CAAC,CAAC;CAC9C,CAAC"}
|
package/lib-es/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM;;;;;;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM;;;;;;EAyEzC"}
|
package/lib-es/utils.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { encode, decode } from "@ethersproject/rlp";
|
|
2
2
|
import { BigNumber } from "bignumber.js";
|
|
3
3
|
export function decodeTxInfo(rawTx) {
|
|
4
4
|
var VALID_TYPES = [1, 2];
|
|
5
5
|
var txType = VALID_TYPES.includes(rawTx[0]) ? rawTx[0] : null;
|
|
6
6
|
var rlpData = txType === null ? rawTx : rawTx.slice(1);
|
|
7
|
-
var rlpTx =
|
|
8
|
-
return Buffer.from(hex.slice(2), "hex");
|
|
9
|
-
});
|
|
7
|
+
var rlpTx = decode(rlpData).map(function (hex) { return Buffer.from(hex.slice(2), "hex"); });
|
|
10
8
|
var chainIdTruncated = 0;
|
|
11
|
-
var rlpDecoded =
|
|
9
|
+
var rlpDecoded = decode(rlpData);
|
|
12
10
|
var decodedTx;
|
|
13
11
|
if (txType === 2) {
|
|
14
12
|
// EIP1559
|
|
@@ -51,7 +49,7 @@ export function decodeTxInfo(rawTx) {
|
|
|
51
49
|
}
|
|
52
50
|
var vrsOffset = 0;
|
|
53
51
|
if (txType === null && rlpTx.length > 6) {
|
|
54
|
-
var rlpVrs = Buffer.from(
|
|
52
|
+
var rlpVrs = Buffer.from(encode(rlpTx.slice(-3)).slice(2), "hex");
|
|
55
53
|
vrsOffset = rawTx.length - (rlpVrs.length - 1);
|
|
56
54
|
// First byte > 0xf7 means the length of the list length doesn't fit in a single byte.
|
|
57
55
|
if (rlpVrs[0] > 0xf7) {
|
package/lib-es/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,
|
|
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": "6.
|
|
3
|
+
"version": "6.23.0",
|
|
4
4
|
"description": "Ledger Hardware Wallet Ethereum Application API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -27,13 +27,14 @@
|
|
|
27
27
|
"types": "lib/Eth.d.ts",
|
|
28
28
|
"license": "Apache-2.0",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@
|
|
30
|
+
"@ethersproject/abi": "^5.5.0",
|
|
31
|
+
"@ethersproject/rlp": "^5.5.0",
|
|
32
|
+
"@ledgerhq/cryptoassets": "^6.23.0",
|
|
31
33
|
"@ledgerhq/errors": "^6.10.0",
|
|
32
34
|
"@ledgerhq/hw-transport": "^6.20.0",
|
|
33
35
|
"@ledgerhq/logs": "^6.10.0",
|
|
34
36
|
"axios": "^0.24.0",
|
|
35
|
-
"bignumber.js": "^9.0.2"
|
|
36
|
-
"ethers": "^5.5.2"
|
|
37
|
+
"bignumber.js": "^9.0.2"
|
|
37
38
|
},
|
|
38
39
|
"scripts": {
|
|
39
40
|
"clean": "bash ../../script/clean.sh",
|
|
@@ -41,5 +42,5 @@
|
|
|
41
42
|
"watch": "bash ../../script/watch.sh",
|
|
42
43
|
"doc": "bash ../../script/doc.sh"
|
|
43
44
|
},
|
|
44
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "aa41abf0cb3c375d677f9c2739956b3a2566d852"
|
|
45
46
|
}
|
package/src/Eth.ts
CHANGED
|
@@ -15,13 +15,16 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
********************************************************************************/
|
|
17
17
|
// FIXME drop:
|
|
18
|
-
import { EthAppPleaseEnableContractData } from "@ledgerhq/errors";
|
|
19
18
|
import type Transport from "@ledgerhq/hw-transport";
|
|
20
19
|
import { BigNumber } from "bignumber.js";
|
|
21
20
|
import { decodeTxInfo } from "./utils";
|
|
22
21
|
// NB: these are temporary import for the deprecated fallback mechanism
|
|
23
22
|
import { LedgerEthTransactionResolution, LoadConfig } from "./services/types";
|
|
24
23
|
import ledgerService from "./services/ledger";
|
|
24
|
+
import {
|
|
25
|
+
EthAppNftNotSupported,
|
|
26
|
+
EthAppPleaseEnableContractData,
|
|
27
|
+
} from "./errors";
|
|
25
28
|
|
|
26
29
|
export type StarkQuantizationType =
|
|
27
30
|
| "eth"
|
|
@@ -213,8 +216,17 @@ export default class Eth {
|
|
|
213
216
|
" + const resolution = await ledgerService.resolveTransaction(rawTxHex);"
|
|
214
217
|
);
|
|
215
218
|
resolution = await ledgerService
|
|
216
|
-
.resolveTransaction(rawTxHex, this.loadConfig
|
|
217
|
-
|
|
219
|
+
.resolveTransaction(rawTxHex, this.loadConfig, {
|
|
220
|
+
externalPlugins: true,
|
|
221
|
+
erc20: true,
|
|
222
|
+
})
|
|
223
|
+
.catch((e) => {
|
|
224
|
+
console.warn(
|
|
225
|
+
"an error occurred in resolveTransaction => fallback to blind signing: " +
|
|
226
|
+
String(e)
|
|
227
|
+
);
|
|
228
|
+
return null;
|
|
229
|
+
});
|
|
218
230
|
}
|
|
219
231
|
|
|
220
232
|
// provide to the device resolved information to make it clear sign the signature
|
|
@@ -1178,8 +1190,8 @@ function provideNFTInformation(
|
|
|
1178
1190
|
return false;
|
|
1179
1191
|
}
|
|
1180
1192
|
if (e && e.statusCode === 0x6d00) {
|
|
1181
|
-
//
|
|
1182
|
-
|
|
1193
|
+
// older version of ETH app => error because we don't allow blind sign when NFT is explicitly requested to be resolved.
|
|
1194
|
+
throw new EthAppNftNotSupported();
|
|
1183
1195
|
}
|
|
1184
1196
|
throw e;
|
|
1185
1197
|
}
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
2
|
+
|
|
3
|
+
export const EthAppPleaseEnableContractData = createCustomErrorClass(
|
|
4
|
+
"EthAppPleaseEnableContractData"
|
|
5
|
+
);
|
|
6
|
+
export const EthAppNftNotSupported = createCustomErrorClass(
|
|
7
|
+
"EthAppNftNotSupported"
|
|
8
|
+
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// This implements the resolution of a Transaction using Ledger's own API
|
|
2
2
|
import { log } from "@ledgerhq/logs";
|
|
3
|
-
import {
|
|
3
|
+
import { Interface } from "@ethersproject/abi";
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
LedgerEthTransactionResolution,
|
|
@@ -12,7 +12,7 @@ import { getNFTInfo, loadNftPlugin } from "./nfts";
|
|
|
12
12
|
import { decodeTxInfo } from "../../utils";
|
|
13
13
|
|
|
14
14
|
const ledgerService: LedgerEthTransactionService = {
|
|
15
|
-
resolveTransaction: async (rawTxHex, loadConfig) => {
|
|
15
|
+
resolveTransaction: async (rawTxHex, loadConfig, resolutionConfig) => {
|
|
16
16
|
const resolution: LedgerEthTransactionResolution = {
|
|
17
17
|
erc20Tokens: [],
|
|
18
18
|
nfts: [],
|
|
@@ -36,7 +36,9 @@ const ledgerService: LedgerEthTransactionService = {
|
|
|
36
36
|
const rawTx = Buffer.from(rawTxHex, "hex");
|
|
37
37
|
const { decodedTx, chainIdTruncated } = decodeTxInfo(rawTx);
|
|
38
38
|
const provideForContract = async (address) => {
|
|
39
|
-
const nftInfo =
|
|
39
|
+
const nftInfo = resolutionConfig.nft
|
|
40
|
+
? await getNFTInfo(address, chainIdTruncated, loadConfig)
|
|
41
|
+
: null;
|
|
40
42
|
if (nftInfo) {
|
|
41
43
|
log(
|
|
42
44
|
"ethereum",
|
|
@@ -68,22 +70,26 @@ const ledgerService: LedgerEthTransactionService = {
|
|
|
68
70
|
|
|
69
71
|
if (decodedTx.data.length >= 10) {
|
|
70
72
|
const selector = decodedTx.data.substring(0, 10);
|
|
71
|
-
const nftPluginPayload =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const nftPluginPayload = resolutionConfig.nft
|
|
74
|
+
? await loadNftPlugin(
|
|
75
|
+
decodedTx.to,
|
|
76
|
+
selector,
|
|
77
|
+
chainIdTruncated,
|
|
78
|
+
loadConfig
|
|
79
|
+
)
|
|
80
|
+
: null;
|
|
77
81
|
|
|
78
82
|
if (nftPluginPayload) {
|
|
79
83
|
setPlugin(nftPluginPayload);
|
|
80
84
|
} else {
|
|
81
|
-
const infos =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
const infos = resolutionConfig.externalPlugins
|
|
86
|
+
? await loadInfosForContractMethod(
|
|
87
|
+
decodedTx.to,
|
|
88
|
+
selector,
|
|
89
|
+
chainIdTruncated,
|
|
90
|
+
loadConfig
|
|
91
|
+
)
|
|
92
|
+
: null;
|
|
87
93
|
|
|
88
94
|
if (infos) {
|
|
89
95
|
const { plugin, payload, signature, erc20OfInterest, abi } = infos;
|
|
@@ -93,7 +99,7 @@ const ledgerService: LedgerEthTransactionService = {
|
|
|
93
99
|
setExternalPlugin(payload, signature);
|
|
94
100
|
}
|
|
95
101
|
if (erc20OfInterest && erc20OfInterest.length && abi) {
|
|
96
|
-
const contract = new
|
|
102
|
+
const contract = new Interface(abi);
|
|
97
103
|
const args = contract.parseTransaction(decodedTx).args;
|
|
98
104
|
for (const path of erc20OfInterest) {
|
|
99
105
|
const address = path.split(".").reduce((value, seg) => {
|
|
@@ -102,14 +108,14 @@ const ledgerService: LedgerEthTransactionService = {
|
|
|
102
108
|
}
|
|
103
109
|
return value[seg];
|
|
104
110
|
}, args);
|
|
105
|
-
provideForContract(address);
|
|
111
|
+
await provideForContract(address);
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
114
|
} else {
|
|
109
115
|
log("ethereum", "no infos for selector " + selector);
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
|
-
provideForContract(decodedTx.to);
|
|
118
|
+
await provideForContract(decodedTx.to);
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
return resolution;
|
|
@@ -12,6 +12,12 @@ type BackendResponse = {
|
|
|
12
12
|
payload: string;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
function axiosErrorHandling(e) {
|
|
16
|
+
if (!e || !e.status) throw e;
|
|
17
|
+
if (e.status === 404) return null;
|
|
18
|
+
throw e;
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
export const getNFTInfo = async (
|
|
16
22
|
contractAddress: string,
|
|
17
23
|
chainId: number,
|
|
@@ -20,15 +26,27 @@ export const getNFTInfo = async (
|
|
|
20
26
|
const { nftExplorerBaseURL } = getLoadConfig(userLoadConfig);
|
|
21
27
|
if (!nftExplorerBaseURL) return;
|
|
22
28
|
const url = `${nftExplorerBaseURL}/${chainId}/contracts/${contractAddress}`;
|
|
23
|
-
const response = await axios
|
|
29
|
+
const response = await axios
|
|
30
|
+
.get<BackendResponse>(url)
|
|
31
|
+
.then((r) => r.data)
|
|
32
|
+
.catch(axiosErrorHandling);
|
|
24
33
|
if (!response) return;
|
|
25
34
|
|
|
35
|
+
// APDU response specification: https://ledgerhq.atlassian.net/wiki/spaces/WALLETCO/pages/3269984297/NFT-1+NFT+Backend+design#NFT-Metadata-BLOB
|
|
26
36
|
const payload = response["payload"];
|
|
27
|
-
|
|
28
|
-
const
|
|
37
|
+
// Collection name length position: 3rd byte -> caracter 4 to 6
|
|
38
|
+
const collectionNameLength = parseInt(payload.slice(4, 6), 16);
|
|
39
|
+
const collectionNameHex = payload.substr(6, collectionNameLength * 2);
|
|
40
|
+
const collectionName = collectionNameHex
|
|
41
|
+
.match(/.{2}/g) // split every 2 characters
|
|
42
|
+
?.reduce(
|
|
43
|
+
(acc, curr) => (acc += String.fromCharCode(parseInt(curr, 16))),
|
|
44
|
+
""
|
|
45
|
+
); // convert hex to string
|
|
46
|
+
|
|
29
47
|
return {
|
|
30
48
|
contractAddress: contractAddress,
|
|
31
|
-
collectionName: collectionName,
|
|
49
|
+
collectionName: collectionName || "",
|
|
32
50
|
data: payload,
|
|
33
51
|
};
|
|
34
52
|
};
|
|
@@ -43,7 +61,10 @@ export const loadNftPlugin = async (
|
|
|
43
61
|
if (!nftExplorerBaseURL) return;
|
|
44
62
|
const url = `${nftExplorerBaseURL}/${chainId}/contracts/${contractAddress}/plugin-selector/${selector}`;
|
|
45
63
|
|
|
46
|
-
const response = await axios
|
|
64
|
+
const response = await axios
|
|
65
|
+
.get<BackendResponse>(url)
|
|
66
|
+
.then((r) => r.data)
|
|
67
|
+
.catch(axiosErrorHandling);
|
|
47
68
|
if (!response) return;
|
|
48
69
|
|
|
49
70
|
const payload = response["payload"];
|
package/src/services/types.ts
CHANGED
|
@@ -20,9 +20,23 @@ export type LoadConfig = {
|
|
|
20
20
|
extraPlugins?: any | null;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Allows to configure precisely what the service need to resolve.
|
|
25
|
+
* for instance you can set nft:true if you need clear signing on NFTs. If you set it and it is not a NFT transaction, it should still work but will do a useless service resolution.
|
|
26
|
+
*/
|
|
27
|
+
export type ResolutionConfig = {
|
|
28
|
+
// NFT resolution service
|
|
29
|
+
nft?: boolean;
|
|
30
|
+
// external plugins resolution service (e.G. LIDO)
|
|
31
|
+
externalPlugins?: boolean;
|
|
32
|
+
// ERC20 resolution service (to clear sign erc20 transfers & other actions)
|
|
33
|
+
erc20?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
23
36
|
export type LedgerEthTransactionService = {
|
|
24
37
|
resolveTransaction: (
|
|
25
38
|
rawTxHex: string,
|
|
26
|
-
loadConfig: LoadConfig
|
|
39
|
+
loadConfig: LoadConfig,
|
|
40
|
+
resolutionConfig: ResolutionConfig
|
|
27
41
|
) => Promise<LedgerEthTransactionResolution>;
|
|
28
42
|
};
|
package/src/utils.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { encode, decode } from "@ethersproject/rlp";
|
|
2
2
|
import { BigNumber } from "bignumber.js";
|
|
3
3
|
|
|
4
4
|
export function decodeTxInfo(rawTx: Buffer) {
|
|
5
5
|
const VALID_TYPES = [1, 2];
|
|
6
6
|
const txType = VALID_TYPES.includes(rawTx[0]) ? rawTx[0] : null;
|
|
7
7
|
const rlpData = txType === null ? rawTx : rawTx.slice(1);
|
|
8
|
-
const rlpTx =
|
|
9
|
-
Buffer.from(hex.slice(2), "hex")
|
|
10
|
-
);
|
|
8
|
+
const rlpTx = decode(rlpData).map((hex) => Buffer.from(hex.slice(2), "hex"));
|
|
11
9
|
let chainIdTruncated = 0;
|
|
12
|
-
const rlpDecoded =
|
|
10
|
+
const rlpDecoded = decode(rlpData);
|
|
13
11
|
|
|
14
12
|
let decodedTx;
|
|
15
13
|
if (txType === 2) {
|
|
@@ -52,10 +50,7 @@ export function decodeTxInfo(rawTx: Buffer) {
|
|
|
52
50
|
|
|
53
51
|
let vrsOffset = 0;
|
|
54
52
|
if (txType === null && rlpTx.length > 6) {
|
|
55
|
-
const rlpVrs = Buffer.from(
|
|
56
|
-
ethers.utils.RLP.encode(rlpTx.slice(-3)).slice(2),
|
|
57
|
-
"hex"
|
|
58
|
-
);
|
|
53
|
+
const rlpVrs = Buffer.from(encode(rlpTx.slice(-3)).slice(2), "hex");
|
|
59
54
|
|
|
60
55
|
vrsOffset = rawTx.length - (rlpVrs.length - 1);
|
|
61
56
|
|