@ledgerhq/coin-evm 0.2.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/.eslintrc.js +57 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/CHANGELOG.md +18 -0
  4. package/jest.config.js +6 -0
  5. package/package.json +102 -0
  6. package/src/__tests__/adapters.unit.test.ts +527 -0
  7. package/src/__tests__/broadcast.unit.test.ts +181 -0
  8. package/src/__tests__/buildOptimisticOperation.unit.test.ts +182 -0
  9. package/src/__tests__/createTransaction.unit.test.ts +52 -0
  10. package/src/__tests__/deviceTransactionConfig.unit.test.ts +245 -0
  11. package/src/__tests__/estimateMaxSpendable.unit.test.ts +123 -0
  12. package/src/__tests__/getTransactionStatus.unit.test.ts +355 -0
  13. package/src/__tests__/hw-getAddress.unit.test.ts +24 -0
  14. package/src/__tests__/logic.unit.test.ts +406 -0
  15. package/src/__tests__/preload.unit.test.ts +139 -0
  16. package/src/__tests__/prepareTransaction.unit.test.ts +394 -0
  17. package/src/__tests__/rpc.unit.test.ts +532 -0
  18. package/src/__tests__/signOperation.unit.test.ts +157 -0
  19. package/src/__tests__/synchronization.unit.test.ts +832 -0
  20. package/src/__tests__/transaction.unit.test.ts +196 -0
  21. package/src/abis/erc20.abi.json +230 -0
  22. package/src/abis/optimismGasPriceOracle.abi.json +252 -0
  23. package/src/adapters.ts +148 -0
  24. package/src/api/etherscan.ts +124 -0
  25. package/src/api/rpc.common.ts +354 -0
  26. package/src/api/rpc.native.ts +5 -0
  27. package/src/api/rpc.ts +2 -0
  28. package/src/bridge/js.ts +77 -0
  29. package/src/bridge.integration.test.ts +93 -0
  30. package/src/broadcast.ts +40 -0
  31. package/src/buildOptimisticOperation.ts +113 -0
  32. package/src/cli-transaction.ts +11 -0
  33. package/src/createTransaction.ts +25 -0
  34. package/src/datasets/ethereum.scanAccounts.1.ts +48 -0
  35. package/src/datasets/ethereum1.ts +20 -0
  36. package/src/datasets/ethereum2.ts +20 -0
  37. package/src/datasets/ethereum_classic.ts +68 -0
  38. package/src/deviceTransactionConfig.ts +64 -0
  39. package/src/errors.ts +5 -0
  40. package/src/estimateMaxSpendable.ts +19 -0
  41. package/src/getTransactionStatus.ts +186 -0
  42. package/src/hw-getAddress.ts +24 -0
  43. package/src/logic.ts +149 -0
  44. package/src/preload.ts +54 -0
  45. package/src/prepareTransaction.ts +176 -0
  46. package/src/signOperation.ts +127 -0
  47. package/src/specs.ts +344 -0
  48. package/src/speculos-deviceActions.ts +83 -0
  49. package/src/synchronization.ts +317 -0
  50. package/src/testUtils.ts +153 -0
  51. package/src/transaction.ts +193 -0
  52. package/src/types.ts +132 -0
  53. package/tsconfig.json +12 -0
@@ -0,0 +1,181 @@
1
+ import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
2
+ import { getCryptoCurrencyById, getTokenById } from "@ledgerhq/cryptoassets";
3
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
4
+ import { Account, TokenAccount } from "@ledgerhq/types-live";
5
+ import BigNumber from "bignumber.js";
6
+ import * as API from "../api/rpc.common";
7
+ import broadcast from "../broadcast";
8
+ import buildOptimisticOperation from "../buildOptimisticOperation";
9
+ import { getEstimatedFees } from "../logic";
10
+ import { makeAccount, makeTokenAccount } from "../testUtils";
11
+ import { Transaction as EvmTransaction } from "../types";
12
+
13
+ const currency: CryptoCurrency = getCryptoCurrencyById("ethereum");
14
+ const tokenCurrency = getTokenById("ethereum/erc20/usd__coin");
15
+ const tokenAccount: TokenAccount = makeTokenAccount(
16
+ "0x055C1e159E345cB4197e3844a86A61E0a801d856", // jacquie.eth
17
+ tokenCurrency
18
+ );
19
+ const account: Account = makeAccount(
20
+ "0x055C1e159E345cB4197e3844a86A61E0a801d856", // jacquie.eth
21
+ currency,
22
+ [tokenAccount]
23
+ );
24
+ const mockedBroadcastResponse = {
25
+ hash: "0xH4sH",
26
+ blockNumber: 420,
27
+ blockHash: "0xBl0cKH4sH",
28
+ timestamp: Date.now() / 1000, // block timestamps are in seconds
29
+ };
30
+
31
+ describe("EVM Family", () => {
32
+ describe("broadcast.ts", () => {
33
+ beforeAll(() => {
34
+ jest
35
+ .spyOn(API, "broadcastTransaction")
36
+ .mockImplementation(async () => mockedBroadcastResponse as any);
37
+ });
38
+
39
+ afterAll(() => {
40
+ jest.restoreAllMocks();
41
+ });
42
+
43
+ describe("broadcast", () => {
44
+ it("should broadcast the coin transaction and fill the blank in the optimistic transaction", async () => {
45
+ const coinTransaction: EvmTransaction = {
46
+ amount: new BigNumber(100),
47
+ useAllAmount: false,
48
+ subAccountId: "id",
49
+ recipient: "0x51DF0aF74a0DBae16cB845B46dAF2a35cB1D4168", // michel.eth
50
+ feesStrategy: "custom",
51
+ family: "evm",
52
+ mode: "send",
53
+ nonce: 0,
54
+ gasLimit: new BigNumber(21000),
55
+ chainId: 1,
56
+ maxFeePerGas: new BigNumber(100),
57
+ maxPriorityFeePerGas: new BigNumber(100),
58
+ type: 2,
59
+ };
60
+ const estimatedFees = getEstimatedFees(coinTransaction);
61
+ const optimisticCoinOperation = buildOptimisticOperation(
62
+ account,
63
+ coinTransaction
64
+ );
65
+
66
+ const finalOperation = await broadcast({
67
+ account,
68
+ signedOperation: {
69
+ operation: optimisticCoinOperation,
70
+ signature: "0xS1gn4tUR3",
71
+ expirationDate: null,
72
+ },
73
+ });
74
+
75
+ expect(API.broadcastTransaction).toBeCalled();
76
+ expect(finalOperation).toEqual({
77
+ id: encodeOperationId(
78
+ account.id,
79
+ mockedBroadcastResponse.hash,
80
+ "OUT"
81
+ ),
82
+ hash: mockedBroadcastResponse.hash,
83
+ blockNumber: mockedBroadcastResponse.blockNumber,
84
+ blockHeight: mockedBroadcastResponse.blockNumber,
85
+ blockHash: mockedBroadcastResponse.blockHash,
86
+ value: coinTransaction.amount.plus(estimatedFees),
87
+ fee: estimatedFees,
88
+ type: "OUT",
89
+ senders: [account.freshAddress],
90
+ recipients: [coinTransaction.recipient],
91
+ accountId: account.id,
92
+ transactionSequenceNumber: 0,
93
+ subOperations: [],
94
+ date: new Date(mockedBroadcastResponse.timestamp * 1000),
95
+ extra: {},
96
+ });
97
+ });
98
+
99
+ it("should broadcast the token transaction and fill the blank in the optimistic transaction", async () => {
100
+ const tokenTransaction: EvmTransaction = {
101
+ amount: new BigNumber(100),
102
+ useAllAmount: false,
103
+ subAccountId: tokenAccount.id,
104
+ recipient: "0x51DF0aF74a0DBae16cB845B46dAF2a35cB1D4168", // michel.eth
105
+ data: Buffer.from(
106
+ "a9059cbb00000000000000000000000059569e96d0e3d9728dc07bf5c1443809e6f237fd0000000000000000000000000000000000000000000000000c06701668d322ac",
107
+ "hex"
108
+ ),
109
+ feesStrategy: "custom",
110
+ family: "evm",
111
+ mode: "send",
112
+ nonce: 0,
113
+ gasLimit: new BigNumber(60000),
114
+ chainId: 1,
115
+ maxFeePerGas: new BigNumber(100),
116
+ maxPriorityFeePerGas: new BigNumber(100),
117
+ type: 2,
118
+ };
119
+ const estimatedFees = getEstimatedFees(tokenTransaction);
120
+ const optimisticTokenOperation = buildOptimisticOperation(
121
+ account,
122
+ tokenTransaction
123
+ );
124
+
125
+ const finalOperation = await broadcast({
126
+ account,
127
+ signedOperation: {
128
+ operation: optimisticTokenOperation,
129
+ signature: "0xS1gn4tUR3",
130
+ expirationDate: null,
131
+ },
132
+ });
133
+
134
+ expect(API.broadcastTransaction).toBeCalled();
135
+ expect(finalOperation).toEqual({
136
+ id: encodeOperationId(
137
+ account.id,
138
+ mockedBroadcastResponse.hash,
139
+ "FEES"
140
+ ),
141
+ hash: mockedBroadcastResponse.hash,
142
+ blockNumber: mockedBroadcastResponse.blockNumber,
143
+ blockHeight: mockedBroadcastResponse.blockNumber,
144
+ blockHash: mockedBroadcastResponse.blockHash,
145
+ value: estimatedFees,
146
+ fee: estimatedFees,
147
+ type: "FEES",
148
+ senders: [account.freshAddress],
149
+ recipients: [tokenCurrency?.contractAddress || ""],
150
+ accountId: account.id,
151
+ transactionSequenceNumber: 0,
152
+ date: new Date(mockedBroadcastResponse.timestamp * 1000),
153
+ subOperations: [
154
+ {
155
+ id: encodeOperationId(
156
+ tokenAccount.id,
157
+ mockedBroadcastResponse.hash,
158
+ "OUT"
159
+ ),
160
+ hash: mockedBroadcastResponse.hash,
161
+ blockNumber: mockedBroadcastResponse.blockNumber,
162
+ blockHeight: mockedBroadcastResponse.blockNumber,
163
+ blockHash: mockedBroadcastResponse.blockHash,
164
+ value: new BigNumber(100),
165
+ fee: estimatedFees,
166
+ type: "OUT",
167
+ senders: [account.freshAddress],
168
+ recipients: [tokenTransaction.recipient],
169
+ accountId: tokenAccount.id,
170
+ transactionSequenceNumber: 0,
171
+ date: new Date(mockedBroadcastResponse.timestamp * 1000),
172
+ contract: tokenAccount.token.contractAddress,
173
+ extra: {},
174
+ },
175
+ ],
176
+ extra: {},
177
+ });
178
+ });
179
+ });
180
+ });
181
+ });
@@ -0,0 +1,182 @@
1
+ import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
2
+ import { getCryptoCurrencyById, getTokenById } from "@ledgerhq/cryptoassets";
3
+ import BigNumber from "bignumber.js";
4
+ import buildOptimisticOperation from "../buildOptimisticOperation";
5
+ import { getEstimatedFees } from "../logic";
6
+ import { makeAccount, makeTokenAccount } from "../testUtils";
7
+ import { Transaction as EvmTransaction } from "../types";
8
+
9
+ const currency = getCryptoCurrencyById("ethereum");
10
+ const tokenCurrency = getTokenById("ethereum/erc20/usd__coin");
11
+ const tokenAccount = {
12
+ ...makeTokenAccount(
13
+ "0x055C1e159E345cB4197e3844a86A61E0a801d856", // jacquie.eth
14
+ tokenCurrency
15
+ ),
16
+ balance: new BigNumber(150),
17
+ spendableBalance: new BigNumber(150),
18
+ };
19
+ const account = makeAccount(
20
+ "0x055C1e159E345cB4197e3844a86A61E0a801d856", // jacquie.eth
21
+ currency,
22
+ [tokenAccount]
23
+ );
24
+
25
+ describe("EVM Family", () => {
26
+ describe("buildOptimisticOperation.ts", () => {
27
+ describe("buildOptimisticOperation", () => {
28
+ it("should create a coin optimistic transaction waiting for the broadcast to be completed", () => {
29
+ const coinTransaction: EvmTransaction = {
30
+ amount: new BigNumber(100),
31
+ useAllAmount: false,
32
+ subAccountId: "id",
33
+ recipient: "0xe2ca7390e76c5A992749bB622087310d2e63ca29", // cortex.eth
34
+ feesStrategy: "custom",
35
+ family: "evm",
36
+ mode: "send",
37
+ nonce: 0,
38
+ gasLimit: new BigNumber(21000),
39
+ chainId: 1,
40
+ maxFeePerGas: new BigNumber(100),
41
+ maxPriorityFeePerGas: new BigNumber(100),
42
+ type: 2,
43
+ };
44
+ const optimistic = buildOptimisticOperation(account, coinTransaction);
45
+ const estimatedFees = getEstimatedFees(coinTransaction);
46
+ const type = "OUT";
47
+
48
+ expect(optimistic).toEqual({
49
+ id: encodeOperationId(account.id, "", type),
50
+ hash: "",
51
+ type,
52
+ value: coinTransaction.amount.plus(estimatedFees),
53
+ fee: estimatedFees,
54
+ blockHash: null,
55
+ blockHeight: null,
56
+ senders: [account.freshAddress],
57
+ recipients: [coinTransaction.recipient],
58
+ accountId: account.id,
59
+ transactionSequenceNumber: 0,
60
+ date: expect.any(Date),
61
+ extra: {},
62
+ });
63
+ });
64
+
65
+ it("should create a token optimistic transaction waiting for the broadcast to be completed", () => {
66
+ const tokenTransaction: EvmTransaction = {
67
+ amount: new BigNumber(100),
68
+ useAllAmount: false,
69
+ subAccountId: tokenAccount.id,
70
+ recipient: "0x51DF0aF74a0DBae16cB845B46dAF2a35cB1D4168", // michel.eth
71
+ data: Buffer.from(
72
+ "a9059cbb00000000000000000000000059569e96d0e3d9728dc07bf5c1443809e6f237fd0000000000000000000000000000000000000000000000000c06701668d322ac",
73
+ "hex"
74
+ ),
75
+ feesStrategy: "custom",
76
+ family: "evm",
77
+ mode: "send",
78
+ nonce: 0,
79
+ gasLimit: new BigNumber(60000),
80
+ chainId: 1,
81
+ maxFeePerGas: new BigNumber(100),
82
+ maxPriorityFeePerGas: new BigNumber(100),
83
+ type: 2,
84
+ };
85
+ const estimatedFees = getEstimatedFees(tokenTransaction);
86
+ const optimistic = buildOptimisticOperation(account, tokenTransaction);
87
+
88
+ expect(optimistic).toEqual({
89
+ id: encodeOperationId(account.id, "", "FEES"),
90
+ hash: "",
91
+ type: "FEES",
92
+ value: estimatedFees,
93
+ fee: estimatedFees,
94
+ blockHash: null,
95
+ blockHeight: null,
96
+ senders: [account.freshAddress],
97
+ recipients: [tokenCurrency.contractAddress],
98
+ accountId: account.id,
99
+ transactionSequenceNumber: 0,
100
+ date: expect.any(Date),
101
+ subOperations: [
102
+ {
103
+ id: encodeOperationId(tokenAccount.id, "", "OUT"),
104
+ hash: "",
105
+ type: "OUT",
106
+ value: tokenTransaction.amount,
107
+ fee: estimatedFees,
108
+ blockHash: null,
109
+ blockHeight: null,
110
+ senders: [account.freshAddress],
111
+ recipients: [tokenTransaction.recipient],
112
+ accountId: tokenAccount.id,
113
+ transactionSequenceNumber: 0,
114
+ date: expect.any(Date),
115
+ contract: tokenAccount.token.contractAddress,
116
+ extra: {},
117
+ },
118
+ ],
119
+ extra: {},
120
+ });
121
+ });
122
+
123
+ it("should create a token optimistic transaction with useAllAmount waiting for the broadcast to be completed", () => {
124
+ const tokenTransaction: EvmTransaction = {
125
+ amount: new BigNumber(0),
126
+ useAllAmount: true,
127
+ subAccountId: tokenAccount.id,
128
+ recipient: "0x51DF0aF74a0DBae16cB845B46dAF2a35cB1D4168", // michel.eth
129
+ data: Buffer.from(
130
+ "a9059cbb00000000000000000000000059569e96d0e3d9728dc07bf5c1443809e6f237fd0000000000000000000000000000000000000000000000000c06701668d322ac",
131
+ "hex"
132
+ ),
133
+ feesStrategy: "custom",
134
+ family: "evm",
135
+ mode: "send",
136
+ nonce: 0,
137
+ gasLimit: new BigNumber(60000),
138
+ chainId: 1,
139
+ maxFeePerGas: new BigNumber(100),
140
+ maxPriorityFeePerGas: new BigNumber(100),
141
+ type: 2,
142
+ };
143
+ const estimatedFees = getEstimatedFees(tokenTransaction);
144
+ const optimistic = buildOptimisticOperation(account, tokenTransaction);
145
+
146
+ expect(optimistic).toEqual({
147
+ id: encodeOperationId(account.id, "", "FEES"),
148
+ hash: "",
149
+ type: "FEES",
150
+ value: estimatedFees,
151
+ fee: estimatedFees,
152
+ blockHash: null,
153
+ blockHeight: null,
154
+ senders: [account.freshAddress],
155
+ recipients: [tokenCurrency.contractAddress],
156
+ accountId: account.id,
157
+ transactionSequenceNumber: 0,
158
+ date: expect.any(Date),
159
+ subOperations: [
160
+ {
161
+ id: encodeOperationId(tokenAccount.id, "", "OUT"),
162
+ hash: "",
163
+ type: "OUT",
164
+ value: account.subAccounts?.[0]?.balance || new BigNumber(150),
165
+ fee: estimatedFees,
166
+ blockHash: null,
167
+ blockHeight: null,
168
+ senders: [account.freshAddress],
169
+ recipients: [tokenTransaction.recipient],
170
+ accountId: tokenAccount.id,
171
+ transactionSequenceNumber: 0,
172
+ date: expect.any(Date),
173
+ contract: tokenAccount.token.contractAddress,
174
+ extra: {},
175
+ },
176
+ ],
177
+ extra: {},
178
+ });
179
+ });
180
+ });
181
+ });
182
+ });
@@ -0,0 +1,52 @@
1
+ import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
2
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
3
+ import BigNumber from "bignumber.js";
4
+ import { createTransaction } from "../createTransaction";
5
+ import { makeAccount } from "../testUtils";
6
+
7
+ const currencyWithChainId = getCryptoCurrencyById("ethereum");
8
+ const currencyWithoutChainId = {
9
+ ...currencyWithChainId,
10
+ ethereumLikeInfo: {},
11
+ } as CryptoCurrency;
12
+ const account1 = makeAccount("0xkvn", currencyWithoutChainId);
13
+ const account2 = makeAccount("0xkvn", currencyWithChainId);
14
+
15
+ describe("EVM Family", () => {
16
+ describe("createTransaction.ts", () => {
17
+ it("should create a valid transaction", () => {
18
+ const transaction1 = createTransaction(account1);
19
+ const transaction2 = createTransaction(account2);
20
+
21
+ expect(transaction1).toEqual({
22
+ family: "evm",
23
+ mode: "send",
24
+ amount: new BigNumber(0),
25
+ useAllAmount: false,
26
+ recipient: "",
27
+ maxFeePerGas: new BigNumber(0),
28
+ maxPriorityFeePerGas: new BigNumber(0),
29
+ gasLimit: new BigNumber(21000),
30
+ nonce: 1,
31
+ chainId: 0,
32
+ feesStrategy: "medium",
33
+ type: 2,
34
+ });
35
+
36
+ expect(transaction2).toEqual({
37
+ family: "evm",
38
+ mode: "send",
39
+ amount: new BigNumber(0),
40
+ useAllAmount: false,
41
+ recipient: "",
42
+ maxFeePerGas: new BigNumber(0),
43
+ maxPriorityFeePerGas: new BigNumber(0),
44
+ gasLimit: new BigNumber(21000),
45
+ nonce: 1,
46
+ chainId: 1,
47
+ feesStrategy: "medium",
48
+ type: 2,
49
+ });
50
+ });
51
+ });
52
+ });
@@ -0,0 +1,245 @@
1
+ import { getCryptoCurrencyById, getTokenById } from "@ledgerhq/cryptoassets";
2
+ import BigNumber from "bignumber.js";
3
+ import getDeviceTransactionConfig from "../deviceTransactionConfig";
4
+ import getTransactionStatus from "../getTransactionStatus";
5
+ import { makeAccount, makeTokenAccount } from "../testUtils";
6
+ import { Transaction as EvmTransaction } from "../types";
7
+
8
+ const currency = getCryptoCurrencyById("ethereum");
9
+ const tokenCurrency = getTokenById("ethereum/erc20/usd__coin");
10
+ const tokenAccount = makeTokenAccount("0xkvn", tokenCurrency);
11
+ const account = makeAccount("0xkvn", currency, [tokenAccount]);
12
+
13
+ describe("EVM Family", () => {
14
+ describe("deviceTransactionConfig.ts", () => {
15
+ describe("getDeviceTransactionConfig", () => {
16
+ it("should return the right fields and infos for a coin transaction without mode'", async () => {
17
+ const coinTransaction: EvmTransaction = {
18
+ amount: new BigNumber(100),
19
+ useAllAmount: false,
20
+ subAccountId: "id",
21
+ recipient: "0x997e135e96114c0E84FFc58754552368E4abf329", // celinedion.eth
22
+ feesStrategy: "custom",
23
+ family: "evm",
24
+ mode: "unknown mode" as any,
25
+ nonce: 0,
26
+ gasLimit: new BigNumber(21000),
27
+ chainId: 1,
28
+ maxFeePerGas: new BigNumber(100),
29
+ maxPriorityFeePerGas: new BigNumber(100),
30
+ type: 2,
31
+ };
32
+
33
+ const status = await getTransactionStatus(account, coinTransaction);
34
+
35
+ expect(
36
+ getDeviceTransactionConfig({
37
+ account,
38
+ parentAccount: undefined,
39
+ transaction: coinTransaction,
40
+ status,
41
+ })
42
+ ).toEqual([
43
+ { type: "amount", label: "Amount" },
44
+ {
45
+ type: "address",
46
+ label: "Address",
47
+ address: coinTransaction.recipient,
48
+ },
49
+ {
50
+ type: "text",
51
+ label: "Network",
52
+ value: currency.name.replace("Lite", "").trim(),
53
+ },
54
+ { type: "fees", label: "Max fees" },
55
+ ]);
56
+ });
57
+
58
+ it("should return the right fields and infos for a coin transaction mode 'send'", async () => {
59
+ const coinTransaction: EvmTransaction = {
60
+ amount: new BigNumber(100),
61
+ useAllAmount: false,
62
+ subAccountId: "id",
63
+ recipient: "0x997e135e96114c0E84FFc58754552368E4abf329", // celinedion.eth
64
+ feesStrategy: "custom",
65
+ family: "evm",
66
+ mode: "send",
67
+ nonce: 0,
68
+ gasLimit: new BigNumber(21000),
69
+ chainId: 1,
70
+ maxFeePerGas: new BigNumber(100),
71
+ maxPriorityFeePerGas: new BigNumber(100),
72
+ type: 2,
73
+ };
74
+
75
+ const status = await getTransactionStatus(account, coinTransaction);
76
+
77
+ expect(
78
+ getDeviceTransactionConfig({
79
+ account,
80
+ parentAccount: undefined,
81
+ transaction: coinTransaction,
82
+ status,
83
+ })
84
+ ).toEqual([
85
+ { type: "amount", label: "Amount" },
86
+ {
87
+ type: "address",
88
+ label: "Address",
89
+ address: coinTransaction.recipient,
90
+ },
91
+ {
92
+ type: "text",
93
+ label: "Network",
94
+ value: currency.name.replace("Lite", "").trim(),
95
+ },
96
+ { type: "fees", label: "Max fees" },
97
+ ]);
98
+ });
99
+
100
+ it("should return the right fields and infos for a coin transaction mode 'send' with domain", async () => {
101
+ const coinTransaction: EvmTransaction = {
102
+ amount: new BigNumber(100),
103
+ useAllAmount: false,
104
+ subAccountId: "id",
105
+ recipient: "0x997e135e96114c0E84FFc58754552368E4abf329", // celinedion.eth
106
+ feesStrategy: "custom",
107
+ family: "evm",
108
+ mode: "send",
109
+ nonce: 0,
110
+ gasLimit: new BigNumber(21000),
111
+ chainId: 1,
112
+ maxFeePerGas: new BigNumber(100),
113
+ maxPriorityFeePerGas: new BigNumber(100),
114
+ type: 2,
115
+ recipientDomain: {
116
+ address: "0x123",
117
+ domain: "vitalik.eth",
118
+ registry: "ens",
119
+ type: "forward",
120
+ },
121
+ };
122
+
123
+ const status = await getTransactionStatus(account, coinTransaction);
124
+
125
+ expect(
126
+ getDeviceTransactionConfig({
127
+ account,
128
+ parentAccount: undefined,
129
+ transaction: coinTransaction,
130
+ status,
131
+ })
132
+ ).toEqual([
133
+ { type: "amount", label: "Amount" },
134
+ {
135
+ type: "text",
136
+ label: "Domain",
137
+ value: coinTransaction.recipientDomain?.domain,
138
+ },
139
+ {
140
+ type: "text",
141
+ label: "Network",
142
+ value: currency.name.replace("Lite", "").trim(),
143
+ },
144
+ { type: "fees", label: "Max fees" },
145
+ ]);
146
+ });
147
+
148
+ it("should return the right fields and infos for a token transaction mode 'send'", async () => {
149
+ const tokenTransaction: EvmTransaction = {
150
+ amount: new BigNumber(100),
151
+ useAllAmount: false,
152
+ subAccountId: tokenAccount.id,
153
+ recipient: "0x997e135e96114c0E84FFc58754552368E4abf329", // celinedion.eth
154
+ data: Buffer.from(
155
+ "a9059cbb00000000000000000000000059569e96d0e3d9728dc07bf5c1443809e6f237fd0000000000000000000000000000000000000000000000000c06701668d322ac",
156
+ "hex"
157
+ ),
158
+ feesStrategy: "custom",
159
+ family: "evm",
160
+ mode: "send",
161
+ nonce: 0,
162
+ gasLimit: new BigNumber(21000),
163
+ chainId: 1,
164
+ maxFeePerGas: new BigNumber(100),
165
+ maxPriorityFeePerGas: new BigNumber(100),
166
+ type: 2,
167
+ };
168
+ const status = await getTransactionStatus(account, tokenTransaction);
169
+
170
+ expect(
171
+ getDeviceTransactionConfig({
172
+ account: tokenAccount,
173
+ parentAccount: account,
174
+ transaction: tokenTransaction,
175
+ status,
176
+ })
177
+ ).toEqual([
178
+ { type: "amount", label: "Amount" },
179
+ {
180
+ type: "address",
181
+ label: "Address",
182
+ address: tokenTransaction.recipient,
183
+ },
184
+ {
185
+ type: "text",
186
+ label: "Network",
187
+ value: currency.name.replace("Lite", "").trim(),
188
+ },
189
+ { type: "fees", label: "Max fees" },
190
+ ]);
191
+ });
192
+
193
+ it("should return the right fields and infos for a token transaction mode 'send' with domain", async () => {
194
+ const tokenTransaction: EvmTransaction = {
195
+ amount: new BigNumber(100),
196
+ useAllAmount: false,
197
+ subAccountId: tokenAccount.id,
198
+ recipient: "0x997e135e96114c0E84FFc58754552368E4abf329", // celinedion.eth
199
+ data: Buffer.from(
200
+ "a9059cbb00000000000000000000000059569e96d0e3d9728dc07bf5c1443809e6f237fd0000000000000000000000000000000000000000000000000c06701668d322ac",
201
+ "hex"
202
+ ),
203
+ feesStrategy: "custom",
204
+ family: "evm",
205
+ mode: "send",
206
+ nonce: 0,
207
+ gasLimit: new BigNumber(21000),
208
+ chainId: 1,
209
+ maxFeePerGas: new BigNumber(100),
210
+ maxPriorityFeePerGas: new BigNumber(100),
211
+ type: 2,
212
+ recipientDomain: {
213
+ address: "0x123",
214
+ domain: "vitalik.eth",
215
+ registry: "ens",
216
+ type: "forward",
217
+ },
218
+ };
219
+ const status = await getTransactionStatus(account, tokenTransaction);
220
+
221
+ expect(
222
+ getDeviceTransactionConfig({
223
+ account: tokenAccount,
224
+ parentAccount: account,
225
+ transaction: tokenTransaction,
226
+ status,
227
+ })
228
+ ).toEqual([
229
+ { type: "amount", label: "Amount" },
230
+ {
231
+ type: "text",
232
+ label: "Domain",
233
+ value: tokenTransaction.recipientDomain?.domain,
234
+ },
235
+ {
236
+ type: "text",
237
+ label: "Network",
238
+ value: currency.name.replace("Lite", "").trim(),
239
+ },
240
+ { type: "fees", label: "Max fees" },
241
+ ]);
242
+ });
243
+ });
244
+ });
245
+ });