@ledgerhq/hw-app-eth 7.0.0-next.0 → 7.0.0-nightly.1
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/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +35 -3
- package/CHANGELOG.md +21 -5
- package/README.md +2 -1
- package/lib/Eth.d.ts.map +1 -1
- package/lib/Eth.js +1 -0
- package/lib/Eth.js.map +1 -1
- package/lib/modules/Uniswap/constants.d.ts +24 -0
- package/lib/modules/Uniswap/constants.d.ts.map +1 -0
- package/lib/modules/Uniswap/constants.js +59 -0
- package/lib/modules/Uniswap/constants.js.map +1 -0
- package/lib/modules/Uniswap/decoders.d.ts +3 -0
- package/lib/modules/Uniswap/decoders.d.ts.map +1 -0
- package/lib/modules/Uniswap/decoders.js +46 -0
- package/lib/modules/Uniswap/decoders.js.map +1 -0
- package/lib/modules/Uniswap/index.d.ts +44 -0
- package/lib/modules/Uniswap/index.d.ts.map +1 -0
- package/lib/modules/Uniswap/index.js +143 -0
- package/lib/modules/Uniswap/index.js.map +1 -0
- package/lib/modules/Uniswap/types.d.ts +3 -0
- package/lib/modules/Uniswap/types.d.ts.map +1 -0
- package/lib/modules/Uniswap/types.js +3 -0
- package/lib/modules/Uniswap/types.js.map +1 -0
- package/lib/services/ledger/index.d.ts.map +1 -1
- package/lib/services/ledger/index.js +20 -5
- package/lib/services/ledger/index.js.map +1 -1
- package/lib/services/types.d.ts +1 -0
- package/lib/services/types.d.ts.map +1 -1
- package/lib/utils.js +1 -1
- package/lib/utils.js.map +1 -1
- package/lib-es/Eth.d.ts.map +1 -1
- package/lib-es/Eth.js +1 -0
- package/lib-es/Eth.js.map +1 -1
- package/lib-es/modules/Uniswap/constants.d.ts +24 -0
- package/lib-es/modules/Uniswap/constants.d.ts.map +1 -0
- package/lib-es/modules/Uniswap/constants.js +56 -0
- package/lib-es/modules/Uniswap/constants.js.map +1 -0
- package/lib-es/modules/Uniswap/decoders.d.ts +3 -0
- package/lib-es/modules/Uniswap/decoders.d.ts.map +1 -0
- package/lib-es/modules/Uniswap/decoders.js +43 -0
- package/lib-es/modules/Uniswap/decoders.js.map +1 -0
- package/lib-es/modules/Uniswap/index.d.ts +44 -0
- package/lib-es/modules/Uniswap/index.d.ts.map +1 -0
- package/lib-es/modules/Uniswap/index.js +137 -0
- package/lib-es/modules/Uniswap/index.js.map +1 -0
- package/lib-es/modules/Uniswap/types.d.ts +3 -0
- package/lib-es/modules/Uniswap/types.d.ts.map +1 -0
- package/lib-es/modules/Uniswap/types.js +2 -0
- package/lib-es/modules/Uniswap/types.js.map +1 -0
- package/lib-es/services/ledger/index.d.ts.map +1 -1
- package/lib-es/services/ledger/index.js +20 -5
- package/lib-es/services/ledger/index.js.map +1 -1
- package/lib-es/services/types.d.ts +1 -0
- package/lib-es/services/types.d.ts.map +1 -1
- package/lib-es/utils.js +1 -1
- package/lib-es/utils.js.map +1 -1
- package/package.json +10 -5
- package/src/Eth.ts +1 -0
- package/src/modules/Uniswap/constants.ts +60 -0
- package/src/modules/Uniswap/decoders.ts +62 -0
- package/src/modules/Uniswap/index.ts +168 -0
- package/src/modules/Uniswap/types.ts +14 -0
- package/src/services/ledger/index.ts +22 -5
- package/src/services/types.ts +2 -0
- package/src/utils.ts +1 -1
- package/tests/Eth.unit.test.ts +65 -3
- package/tests/Uniswap/decoders.unit.test.ts +101 -0
- package/tests/Uniswap/index.unit.test.ts +188 -0
- package/tests/fixtures/utils.ts +8 -1
- package/tests/ledgerService.unit.test.ts +113 -19
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import nock from "nock";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
import {
|
|
4
|
+
getCommandsAndTokensFromUniswapCalldata,
|
|
5
|
+
isSupported,
|
|
6
|
+
loadInfosForUniswap,
|
|
7
|
+
} from "../../src/modules/Uniswap";
|
|
8
|
+
import {
|
|
9
|
+
UNISWAP_EXECUTE_SELECTOR,
|
|
10
|
+
UNISWAP_UNIVERSAL_ROUTER_ADDRESS,
|
|
11
|
+
} from "../../src/modules/Uniswap/constants";
|
|
12
|
+
import SignatureCALEth from "../fixtures/SignatureCALEth";
|
|
13
|
+
|
|
14
|
+
nock.disableNetConnect();
|
|
15
|
+
jest.mock("@ledgerhq/cryptoassets-evm-signatures/data/evm/index", () => ({
|
|
16
|
+
get signatures() {
|
|
17
|
+
return {
|
|
18
|
+
1: SignatureCALEth,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
describe("Uniswap", () => {
|
|
24
|
+
describe("index", () => {
|
|
25
|
+
describe("isSupported", () => {
|
|
26
|
+
it("should return false for a non-Uniswap transaction", () => {
|
|
27
|
+
expect(isSupported("0x", ethers.constants.AddressZero, 1, [])).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should return false for a Uniswap transaction with an invalid selector", () => {
|
|
31
|
+
expect(isSupported("0x123456", UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [])).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should return false for a Uniswap transaction with no commands", () => {
|
|
35
|
+
expect(isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [])).toBe(
|
|
36
|
+
false,
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should return false for a transaction of multiple hops with different pool versions", () => {
|
|
41
|
+
expect(
|
|
42
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
43
|
+
["V2_SWAP_EXACT_IN", ["0x1", "0x2"]],
|
|
44
|
+
["V3_SWAP_EXACT_IN", ["0x2", "0x3"]],
|
|
45
|
+
]),
|
|
46
|
+
).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should return false for a transaction of multiple hops with non chained assets", () => {
|
|
50
|
+
expect(
|
|
51
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
52
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
53
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0C"]],
|
|
54
|
+
]),
|
|
55
|
+
).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should return false for a transaction of multiple hops with non chained assets", () => {
|
|
59
|
+
expect(
|
|
60
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
61
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
62
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0C"]],
|
|
63
|
+
]),
|
|
64
|
+
).toBe(false);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should return true for a valid Uniswap transaction", () => {
|
|
68
|
+
expect(
|
|
69
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
70
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
71
|
+
["V2_SWAP_EXACT_IN", ["0x0B", "0x0C"]],
|
|
72
|
+
]),
|
|
73
|
+
).toBe(true);
|
|
74
|
+
expect(
|
|
75
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
76
|
+
["V3_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
77
|
+
["V3_SWAP_EXACT_IN", ["0x0B", "0x0C"]],
|
|
78
|
+
]),
|
|
79
|
+
).toBe(true);
|
|
80
|
+
expect(
|
|
81
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
82
|
+
["V3_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
83
|
+
["V3_SWAP_EXACT_OUT", ["0x0B", "0x0C"]],
|
|
84
|
+
]),
|
|
85
|
+
).toBe(true);
|
|
86
|
+
expect(
|
|
87
|
+
isSupported(UNISWAP_EXECUTE_SELECTOR, UNISWAP_UNIVERSAL_ROUTER_ADDRESS, 1, [
|
|
88
|
+
["V2_SWAP_EXACT_IN", ["0x0A", "0x0B"]],
|
|
89
|
+
["V2_SWAP_EXACT_OUT", ["0x0B", "0x0C"]],
|
|
90
|
+
]),
|
|
91
|
+
).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
describe("getCommandsAndTokensFromUniswapCalldata", () => {
|
|
96
|
+
it("should return the commands and tokens from a Uniswap calldata", () => {
|
|
97
|
+
// see tx 0xc4df7ccc0527541d0e80856a8f38deedc48c84825e9355469ba02d873502ce2f
|
|
98
|
+
const calldata =
|
|
99
|
+
"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000030a010c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066c32b0d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000410d756f55acf289e9754faf91bba0a704b5c7c0aa4b1dfd551115ccbe4c7f290234e1a14265e1da0bc872a23627d997fe37a689c290d519f7b8c9bdde1b79108e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000030ba49cbff5a00000000000000000000000000000000000000000000000089677c957272141800000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000030ba49cbff5a000";
|
|
100
|
+
|
|
101
|
+
expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([
|
|
102
|
+
["PERMIT2_PERMIT", []],
|
|
103
|
+
[
|
|
104
|
+
"V3_SWAP_EXACT_OUT",
|
|
105
|
+
[
|
|
106
|
+
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
107
|
+
"0x55747be9f9f5beb232ad59fe7af013b81d95fd5e",
|
|
108
|
+
],
|
|
109
|
+
],
|
|
110
|
+
["UNWRAP_ETH", ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]],
|
|
111
|
+
]);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should return an undefined command for unsupported commands by the Uniswap plugin", () => {
|
|
115
|
+
// see tx 0xc0668eb799ba8b73a396529a183b67e7905c0f70143680915ee5802b3036257b
|
|
116
|
+
const calldata =
|
|
117
|
+
"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9f4700000000000000000000000000000000000000000000000000000000000000030b000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000004fdf8403a58c8000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000ff436c9cd1052265be510e00a661f432c539080000000000000000000000000000000000000000000000000004fdf8403a58c80000000000000000000000000000000000000000000ac736c3566d2e76b2c5978300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20027103ffeea07a27fab7ad1df5297fa75e77a43cb5790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f0279540eed3fb666e8aaa4571a47e7478b6e9d000000000000000000000000000000000000000000000000000ce8a624ca9800";
|
|
118
|
+
|
|
119
|
+
expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([
|
|
120
|
+
["WRAP_ETH", ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]],
|
|
121
|
+
[
|
|
122
|
+
"V3_SWAP_EXACT_IN",
|
|
123
|
+
[
|
|
124
|
+
"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
125
|
+
"0x3ffeea07a27fab7ad1df5297fa75e77a43cb5790",
|
|
126
|
+
],
|
|
127
|
+
],
|
|
128
|
+
[undefined, []],
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should return an empty array for an invalid selector", () => {
|
|
133
|
+
const calldata =
|
|
134
|
+
"0x123456000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000030a010c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066c32b0d0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000669b9ec100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000410d756f55acf289e9754faf91bba0a704b5c7c0aa4b1dfd551115ccbe4c7f290234e1a14265e1da0bc872a23627d997fe37a689c290d519f7b8c9bdde1b79108e1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000030ba49cbff5a00000000000000000000000000000000000000000000000089677c957272141800000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000030ba49cbff5a000";
|
|
135
|
+
expect(getCommandsAndTokensFromUniswapCalldata(calldata, 1)).toEqual([]);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("loadInfosForUniswap", () => {
|
|
140
|
+
it("should return ERC20 & plugin descriptors for a valid Uniswap transaction", async () => {
|
|
141
|
+
// see tx 0x88a065f47c82545b0620378d6cb2231713464dd58c0a2b8d6e9485740807b573
|
|
142
|
+
const calldata =
|
|
143
|
+
"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669bad2800000000000000000000000000000000000000000000000000000000000000040a08060c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000bdaa645097ef80f9d475f341d0d107a45b3a000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000687ce06c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000687ce06c00000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000004142794d71565541a435d1bc910db84510c4d31ad35ff8c046222b2c232fcd99a6256a8f1abe7d42a44f3d92d65f9232db76df2fbef3dfa76eca64b034ed4df5321c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000001bffcca36d953d12266cb000000000000000000000000000000000000000000000000027c3dea3f90dafd00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000bdaa645097ef80f9d475f341d0d107a45b3a000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006eb940753b4b52fbec8d33c418133fdb0d4405e6000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000400000000000000000000000001dc813a4ee4410f144ae2122051c1cfc436f24a00000000000000000000000000000000000000000000000000275e122c92b911e";
|
|
144
|
+
|
|
145
|
+
const transaction: ethers.Transaction = {
|
|
146
|
+
to: UNISWAP_UNIVERSAL_ROUTER_ADDRESS,
|
|
147
|
+
data: calldata,
|
|
148
|
+
gasLimit: ethers.BigNumber.from(21_000),
|
|
149
|
+
nonce: 0,
|
|
150
|
+
value: ethers.BigNumber.from(0),
|
|
151
|
+
chainId: 1,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const res = await loadInfosForUniswap(transaction, 1);
|
|
155
|
+
expect(res).toEqual({
|
|
156
|
+
pluginData: Buffer.from(
|
|
157
|
+
"07556e69737761703fc91a3afd70395cd496c647d5a6cc9d4b2b7fad3593564c3044022014391e8f355867a57fe88f6a5a4dbcb8bf8f888a9db3ff3449caf72d120396bd02200c13d9c3f79400fe0aa0434ac54d59b79503c9964a4abc3e8cd22763e0242935",
|
|
158
|
+
"hex",
|
|
159
|
+
),
|
|
160
|
+
tokenDescriptors: [
|
|
161
|
+
Buffer.from(
|
|
162
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
163
|
+
"hex",
|
|
164
|
+
),
|
|
165
|
+
Buffer.from(
|
|
166
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
167
|
+
"hex",
|
|
168
|
+
),
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("should return an empty object for an unsupported Uniswap transaction", async () => {
|
|
174
|
+
const transaction: ethers.Transaction = {
|
|
175
|
+
to: ethers.constants.AddressZero,
|
|
176
|
+
data: "0x",
|
|
177
|
+
gasLimit: ethers.BigNumber.from(21_000),
|
|
178
|
+
nonce: 0,
|
|
179
|
+
value: ethers.BigNumber.from(0),
|
|
180
|
+
chainId: 1,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const res = await loadInfosForUniswap(transaction, 1);
|
|
184
|
+
expect(res).toEqual({});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
});
|
package/tests/fixtures/utils.ts
CHANGED
|
@@ -17,6 +17,7 @@ export const transactionContracts = {
|
|
|
17
17
|
paraswap: "0xdef171fe48cf0115b1d80b88dc8eab59176fee57",
|
|
18
18
|
random: "0xc3f95102D5c8F2c83e49Ce3Acfb905eDfb7f37dE", // jesus.eth
|
|
19
19
|
random2: "0xc3f95102D5c8F2c83e49Ce3Acfb905eDfb7f37dE", // satan.eth
|
|
20
|
+
uniswapUniversaRouter: "0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD",
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export const transactionData = {
|
|
@@ -92,9 +93,15 @@ export const transactionData = {
|
|
|
92
93
|
["0x4de55ce50407b614daff085522d476c5ec5e93a00afb"],
|
|
93
94
|
]),
|
|
94
95
|
},
|
|
96
|
+
uniswap: {
|
|
97
|
+
["permit2>swap-out-v3>unwrap"]:
|
|
98
|
+
"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669ba25a00000000000000000000000000000000000000000000000000000000000000030a010c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000016000000000000000000000000055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000066c32ea60000000000000000000000000000000000000000000000000000000000000006000000000000000000000000ef1c6e67703c7bd7107eed8303fbe6ec2554bf6b00000000000000000000000000000000000000000000000000000000669ba25a00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000413cbf00ab90b6d1b17401cbf49e00c40f98bcb3f39461ca65e26009f9e9f77029279a4587efa2d792ea61ede56e0fbd7c1305007bc59d09bc60eaba46efa23edd1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000233a3559d9da00000000000000000000000000000000000000000000000062e76d8ff4b926e800000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000233a3559d9da000",
|
|
99
|
+
["wrap>swap-in-v3"]:
|
|
100
|
+
"0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000669bbbd800000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000019c1d62a9f2000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000019c1d62a9f200000000000000000000000000000000000000000000000004227ffe925d0fc0000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc200271055747be9f9f5beb232ad59fe7af013b81d95fd5e000000000000000000000000000000000000000000",
|
|
101
|
+
},
|
|
95
102
|
};
|
|
96
103
|
|
|
97
|
-
export const
|
|
104
|
+
export const getSerializedTransaction = (to: string, data: string): string =>
|
|
98
105
|
ethers.utils
|
|
99
106
|
.serializeTransaction({
|
|
100
107
|
to,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
import {
|
|
2
|
+
import { getSerializedTransaction, transactionData, transactionContracts } from "./fixtures/utils";
|
|
3
3
|
import { ERC1155_CLEAR_SIGNED_SELECTORS, ERC721_CLEAR_SIGNED_SELECTORS } from "../src/utils";
|
|
4
4
|
import partialPluginResponse from "./fixtures/REST/Paraswap-Plugin.json";
|
|
5
5
|
import * as contractServices from "../src/services/ledger/contracts";
|
|
6
6
|
import { getLoadConfig } from "../src/services/ledger/loadConfig";
|
|
7
7
|
import * as erc20Services from "../src/services/ledger/erc20";
|
|
8
8
|
import * as nftServices from "../src/services/ledger/nfts";
|
|
9
|
+
import signatureCALEth from "./fixtures/SignatureCALEth";
|
|
10
|
+
import * as uniswapModule from "../src/modules/Uniswap";
|
|
9
11
|
import { ResolutionConfig } from "../src/services/types";
|
|
10
12
|
import { ledgerService } from "../src/Eth";
|
|
11
13
|
|
|
@@ -14,6 +16,7 @@ const resolutionConfig: ResolutionConfig = {
|
|
|
14
16
|
nft: true,
|
|
15
17
|
erc20: true,
|
|
16
18
|
externalPlugins: true,
|
|
19
|
+
uniswapV3: true,
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
jest.mock("axios");
|
|
@@ -23,6 +26,8 @@ jest.spyOn(nftServices, "loadNftPlugin");
|
|
|
23
26
|
jest.spyOn(nftServices, "getNFTInfo");
|
|
24
27
|
jest.spyOn(erc20Services, "findERC20SignaturesInfo");
|
|
25
28
|
jest.spyOn(erc20Services, "byContractAddressAndChainId");
|
|
29
|
+
jest.spyOn(uniswapModule, "loadInfosForUniswap");
|
|
30
|
+
jest.spyOn(uniswapModule, "getCommandsAndTokensFromUniswapCalldata");
|
|
26
31
|
|
|
27
32
|
describe("Ledger Service", () => {
|
|
28
33
|
describe("Transaction resolution", () => {
|
|
@@ -34,7 +39,7 @@ describe("Ledger Service", () => {
|
|
|
34
39
|
it("should resolve an ERC20 approve", async () => {
|
|
35
40
|
// @ts-expect-error not casted as jest mock
|
|
36
41
|
axios.get.mockImplementation(async () => null);
|
|
37
|
-
const txHash =
|
|
42
|
+
const txHash = getSerializedTransaction(
|
|
38
43
|
transactionContracts.erc20,
|
|
39
44
|
transactionData.erc20.approve,
|
|
40
45
|
);
|
|
@@ -63,7 +68,7 @@ describe("Ledger Service", () => {
|
|
|
63
68
|
it("should resolve an ERC20 transfer", async () => {
|
|
64
69
|
// @ts-expect-error not casted as jest mock
|
|
65
70
|
axios.get.mockImplementation(async () => null);
|
|
66
|
-
const txHash =
|
|
71
|
+
const txHash = getSerializedTransaction(
|
|
67
72
|
transactionContracts.erc20,
|
|
68
73
|
transactionData.erc20.transfer,
|
|
69
74
|
);
|
|
@@ -92,7 +97,7 @@ describe("Ledger Service", () => {
|
|
|
92
97
|
it("should not resolve an approve with a non ERC20 or NFT contract", async () => {
|
|
93
98
|
// @ts-expect-error not casted as jest mock
|
|
94
99
|
axios.get.mockImplementation(async () => null);
|
|
95
|
-
const txHash =
|
|
100
|
+
const txHash = getSerializedTransaction(
|
|
96
101
|
transactionContracts.random,
|
|
97
102
|
transactionData.erc20.approve,
|
|
98
103
|
);
|
|
@@ -119,7 +124,7 @@ describe("Ledger Service", () => {
|
|
|
119
124
|
it("should not resolve a transfer with a non ERC20 or NFT contract", async () => {
|
|
120
125
|
// @ts-expect-error not casted as jest mock
|
|
121
126
|
axios.get.mockImplementation(async () => null);
|
|
122
|
-
const txHash =
|
|
127
|
+
const txHash = getSerializedTransaction(
|
|
123
128
|
transactionContracts.random,
|
|
124
129
|
transactionData.erc20.transfer,
|
|
125
130
|
);
|
|
@@ -177,7 +182,7 @@ describe("Ledger Service", () => {
|
|
|
177
182
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.APPROVE),
|
|
178
183
|
);
|
|
179
184
|
|
|
180
|
-
const txHash =
|
|
185
|
+
const txHash = getSerializedTransaction(
|
|
181
186
|
transactionContracts.erc721,
|
|
182
187
|
transactionData.erc721.approve,
|
|
183
188
|
);
|
|
@@ -207,7 +212,7 @@ describe("Ledger Service", () => {
|
|
|
207
212
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.SET_APPROVAL_FOR_ALL),
|
|
208
213
|
);
|
|
209
214
|
|
|
210
|
-
const txHash =
|
|
215
|
+
const txHash = getSerializedTransaction(
|
|
211
216
|
transactionContracts.erc721,
|
|
212
217
|
transactionData.erc721.setApprovalForAll,
|
|
213
218
|
);
|
|
@@ -237,7 +242,7 @@ describe("Ledger Service", () => {
|
|
|
237
242
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.TRANSFER_FROM),
|
|
238
243
|
);
|
|
239
244
|
|
|
240
|
-
const txHash =
|
|
245
|
+
const txHash = getSerializedTransaction(
|
|
241
246
|
transactionContracts.erc721,
|
|
242
247
|
transactionData.erc721.transferFrom,
|
|
243
248
|
);
|
|
@@ -267,7 +272,7 @@ describe("Ledger Service", () => {
|
|
|
267
272
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
268
273
|
);
|
|
269
274
|
|
|
270
|
-
const txHash =
|
|
275
|
+
const txHash = getSerializedTransaction(
|
|
271
276
|
transactionContracts.erc721,
|
|
272
277
|
transactionData.erc721.safeTransferFrom,
|
|
273
278
|
);
|
|
@@ -297,7 +302,7 @@ describe("Ledger Service", () => {
|
|
|
297
302
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM_WITH_DATA),
|
|
298
303
|
);
|
|
299
304
|
|
|
300
|
-
const txHash =
|
|
305
|
+
const txHash = getSerializedTransaction(
|
|
301
306
|
transactionContracts.erc721,
|
|
302
307
|
transactionData.erc721.safeTransferFromWithData,
|
|
303
308
|
);
|
|
@@ -327,7 +332,7 @@ describe("Ledger Service", () => {
|
|
|
327
332
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
328
333
|
);
|
|
329
334
|
|
|
330
|
-
const txHash =
|
|
335
|
+
const txHash = getSerializedTransaction(
|
|
331
336
|
transactionContracts.erc20,
|
|
332
337
|
transactionData.erc721.safeTransferFrom,
|
|
333
338
|
);
|
|
@@ -357,7 +362,7 @@ describe("Ledger Service", () => {
|
|
|
357
362
|
nftAxiosMocker(url, ERC721_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
358
363
|
);
|
|
359
364
|
|
|
360
|
-
const txHash =
|
|
365
|
+
const txHash = getSerializedTransaction(
|
|
361
366
|
transactionContracts.random,
|
|
362
367
|
transactionData.erc721.safeTransferFrom,
|
|
363
368
|
);
|
|
@@ -415,7 +420,7 @@ describe("Ledger Service", () => {
|
|
|
415
420
|
nftAxiosMocker(url, ERC1155_CLEAR_SIGNED_SELECTORS.SET_APPROVAL_FOR_ALL),
|
|
416
421
|
);
|
|
417
422
|
|
|
418
|
-
const txHash =
|
|
423
|
+
const txHash = getSerializedTransaction(
|
|
419
424
|
transactionContracts.erc1155,
|
|
420
425
|
transactionData.erc1155.setApprovalForAll,
|
|
421
426
|
);
|
|
@@ -445,7 +450,7 @@ describe("Ledger Service", () => {
|
|
|
445
450
|
nftAxiosMocker(url, ERC1155_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
446
451
|
);
|
|
447
452
|
|
|
448
|
-
const txHash =
|
|
453
|
+
const txHash = getSerializedTransaction(
|
|
449
454
|
transactionContracts.erc1155,
|
|
450
455
|
transactionData.erc1155.safeTransferFrom,
|
|
451
456
|
);
|
|
@@ -475,7 +480,7 @@ describe("Ledger Service", () => {
|
|
|
475
480
|
nftAxiosMocker(url, ERC1155_CLEAR_SIGNED_SELECTORS.SAFE_BATCH_TRANSFER_FROM),
|
|
476
481
|
);
|
|
477
482
|
|
|
478
|
-
const txHash =
|
|
483
|
+
const txHash = getSerializedTransaction(
|
|
479
484
|
transactionContracts.erc1155,
|
|
480
485
|
transactionData.erc1155.safeBatchTransferFrom,
|
|
481
486
|
);
|
|
@@ -505,7 +510,7 @@ describe("Ledger Service", () => {
|
|
|
505
510
|
nftAxiosMocker(url, ERC1155_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
506
511
|
);
|
|
507
512
|
|
|
508
|
-
const txHash =
|
|
513
|
+
const txHash = getSerializedTransaction(
|
|
509
514
|
transactionContracts.erc20,
|
|
510
515
|
transactionData.erc1155.safeTransferFrom,
|
|
511
516
|
);
|
|
@@ -535,7 +540,7 @@ describe("Ledger Service", () => {
|
|
|
535
540
|
nftAxiosMocker(url, ERC1155_CLEAR_SIGNED_SELECTORS.SAFE_TRANSFER_FROM),
|
|
536
541
|
);
|
|
537
542
|
|
|
538
|
-
const txHash =
|
|
543
|
+
const txHash = getSerializedTransaction(
|
|
539
544
|
transactionContracts.random,
|
|
540
545
|
transactionData.erc1155.safeTransferFrom,
|
|
541
546
|
);
|
|
@@ -571,7 +576,7 @@ describe("Ledger Service", () => {
|
|
|
571
576
|
return null;
|
|
572
577
|
});
|
|
573
578
|
|
|
574
|
-
const txHash =
|
|
579
|
+
const txHash = getSerializedTransaction(
|
|
575
580
|
transactionContracts.paraswap,
|
|
576
581
|
transactionData.paraswap.simpleSwap,
|
|
577
582
|
);
|
|
@@ -613,7 +618,7 @@ describe("Ledger Service", () => {
|
|
|
613
618
|
return null;
|
|
614
619
|
});
|
|
615
620
|
|
|
616
|
-
const txHash =
|
|
621
|
+
const txHash = getSerializedTransaction(
|
|
617
622
|
transactionContracts.paraswap,
|
|
618
623
|
transactionData.paraswap.swapOnUniswapV2Fork,
|
|
619
624
|
);
|
|
@@ -646,5 +651,94 @@ describe("Ledger Service", () => {
|
|
|
646
651
|
});
|
|
647
652
|
});
|
|
648
653
|
});
|
|
654
|
+
|
|
655
|
+
describe("UNISWAP", () => {
|
|
656
|
+
it("should resolve a Uniswap universal router transaction (permit2>swap-out-v3>unwrap)", async () => {
|
|
657
|
+
// @ts-expect-error not casted as jest mock
|
|
658
|
+
axios.get.mockImplementation(async (uri: string) => {
|
|
659
|
+
if (uri.endsWith("evm/1/erc20-signatures.json")) {
|
|
660
|
+
return { data: signatureCALEth };
|
|
661
|
+
}
|
|
662
|
+
return null;
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
const txHash = getSerializedTransaction(
|
|
666
|
+
transactionContracts.uniswapUniversaRouter,
|
|
667
|
+
transactionData.uniswap["permit2>swap-out-v3>unwrap"],
|
|
668
|
+
);
|
|
669
|
+
const resolution = await ledgerService.resolveTransaction(
|
|
670
|
+
txHash,
|
|
671
|
+
loadConfig,
|
|
672
|
+
resolutionConfig,
|
|
673
|
+
);
|
|
674
|
+
|
|
675
|
+
expect(resolution).toEqual({
|
|
676
|
+
domains: [],
|
|
677
|
+
erc20Tokens: [
|
|
678
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
679
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
680
|
+
],
|
|
681
|
+
nfts: [],
|
|
682
|
+
externalPlugin: [
|
|
683
|
+
{
|
|
684
|
+
payload:
|
|
685
|
+
"07556e69737761703fc91a3afd70395cd496c647d5a6cc9d4b2b7fad3593564c3044022014391e8f355867a57fe88f6a5a4dbcb8bf8f888a9db3ff3449caf72d120396bd02200c13d9c3f79400fe0aa0434ac54d59b79503c9964a4abc3e8cd22763e0242935",
|
|
686
|
+
signature: "",
|
|
687
|
+
},
|
|
688
|
+
],
|
|
689
|
+
plugin: [],
|
|
690
|
+
});
|
|
691
|
+
expect(contractServices.loadInfosForContractMethod).toHaveBeenCalledTimes(0);
|
|
692
|
+
expect(erc20Services.findERC20SignaturesInfo).toHaveBeenCalledTimes(3);
|
|
693
|
+
expect(erc20Services.byContractAddressAndChainId).toHaveBeenCalledTimes(3);
|
|
694
|
+
expect(uniswapModule.loadInfosForUniswap).toHaveBeenCalledTimes(1);
|
|
695
|
+
expect(uniswapModule.getCommandsAndTokensFromUniswapCalldata).toHaveBeenCalledTimes(1);
|
|
696
|
+
expect(nftServices.getNFTInfo).not.toHaveBeenCalled();
|
|
697
|
+
expect(nftServices.loadNftPlugin).not.toHaveBeenCalled();
|
|
698
|
+
});
|
|
699
|
+
it("should resolve a Uniswap universal router transaction (wrap>swap-in-v3)", async () => {
|
|
700
|
+
// @ts-expect-error not casted as jest mock
|
|
701
|
+
axios.get.mockImplementation(async (uri: string) => {
|
|
702
|
+
if (uri.endsWith("evm/1/erc20-signatures.json")) {
|
|
703
|
+
return { data: signatureCALEth };
|
|
704
|
+
}
|
|
705
|
+
return null;
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
const txHash = getSerializedTransaction(
|
|
709
|
+
transactionContracts.uniswapUniversaRouter,
|
|
710
|
+
transactionData.uniswap["wrap>swap-in-v3"],
|
|
711
|
+
);
|
|
712
|
+
const resolution = await ledgerService.resolveTransaction(
|
|
713
|
+
txHash,
|
|
714
|
+
loadConfig,
|
|
715
|
+
resolutionConfig,
|
|
716
|
+
);
|
|
717
|
+
|
|
718
|
+
expect(resolution).toEqual({
|
|
719
|
+
domains: [],
|
|
720
|
+
erc20Tokens: [
|
|
721
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
722
|
+
"0457455448c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000012000000013045022100b47ee8551c15a2cf681c649651e987d7e527c481d27c38da1f971a8242792bd3022069c3f688ac5493a23dab5798e3c9b07484765069e1d4be14321aae4d92cb8cbe",
|
|
723
|
+
],
|
|
724
|
+
nfts: [],
|
|
725
|
+
externalPlugin: [
|
|
726
|
+
{
|
|
727
|
+
payload:
|
|
728
|
+
"07556e69737761703fc91a3afd70395cd496c647d5a6cc9d4b2b7fad3593564c3044022014391e8f355867a57fe88f6a5a4dbcb8bf8f888a9db3ff3449caf72d120396bd02200c13d9c3f79400fe0aa0434ac54d59b79503c9964a4abc3e8cd22763e0242935",
|
|
729
|
+
signature: "",
|
|
730
|
+
},
|
|
731
|
+
],
|
|
732
|
+
plugin: [],
|
|
733
|
+
});
|
|
734
|
+
expect(contractServices.loadInfosForContractMethod).toHaveBeenCalledTimes(0);
|
|
735
|
+
expect(erc20Services.findERC20SignaturesInfo).toHaveBeenCalledTimes(3);
|
|
736
|
+
expect(erc20Services.byContractAddressAndChainId).toHaveBeenCalledTimes(3);
|
|
737
|
+
expect(uniswapModule.loadInfosForUniswap).toHaveBeenCalledTimes(1);
|
|
738
|
+
expect(uniswapModule.getCommandsAndTokensFromUniswapCalldata).toHaveBeenCalledTimes(1);
|
|
739
|
+
expect(nftServices.getNFTInfo).not.toHaveBeenCalled();
|
|
740
|
+
expect(nftServices.loadNftPlugin).not.toHaveBeenCalled();
|
|
741
|
+
});
|
|
742
|
+
});
|
|
649
743
|
});
|
|
650
744
|
});
|