@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.
- package/.eslintrc.js +57 -0
- package/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +18 -0
- package/jest.config.js +6 -0
- package/package.json +102 -0
- package/src/__tests__/adapters.unit.test.ts +527 -0
- package/src/__tests__/broadcast.unit.test.ts +181 -0
- package/src/__tests__/buildOptimisticOperation.unit.test.ts +182 -0
- package/src/__tests__/createTransaction.unit.test.ts +52 -0
- package/src/__tests__/deviceTransactionConfig.unit.test.ts +245 -0
- package/src/__tests__/estimateMaxSpendable.unit.test.ts +123 -0
- package/src/__tests__/getTransactionStatus.unit.test.ts +355 -0
- package/src/__tests__/hw-getAddress.unit.test.ts +24 -0
- package/src/__tests__/logic.unit.test.ts +406 -0
- package/src/__tests__/preload.unit.test.ts +139 -0
- package/src/__tests__/prepareTransaction.unit.test.ts +394 -0
- package/src/__tests__/rpc.unit.test.ts +532 -0
- package/src/__tests__/signOperation.unit.test.ts +157 -0
- package/src/__tests__/synchronization.unit.test.ts +832 -0
- package/src/__tests__/transaction.unit.test.ts +196 -0
- package/src/abis/erc20.abi.json +230 -0
- package/src/abis/optimismGasPriceOracle.abi.json +252 -0
- package/src/adapters.ts +148 -0
- package/src/api/etherscan.ts +124 -0
- package/src/api/rpc.common.ts +354 -0
- package/src/api/rpc.native.ts +5 -0
- package/src/api/rpc.ts +2 -0
- package/src/bridge/js.ts +77 -0
- package/src/bridge.integration.test.ts +93 -0
- package/src/broadcast.ts +40 -0
- package/src/buildOptimisticOperation.ts +113 -0
- package/src/cli-transaction.ts +11 -0
- package/src/createTransaction.ts +25 -0
- package/src/datasets/ethereum.scanAccounts.1.ts +48 -0
- package/src/datasets/ethereum1.ts +20 -0
- package/src/datasets/ethereum2.ts +20 -0
- package/src/datasets/ethereum_classic.ts +68 -0
- package/src/deviceTransactionConfig.ts +64 -0
- package/src/errors.ts +5 -0
- package/src/estimateMaxSpendable.ts +19 -0
- package/src/getTransactionStatus.ts +186 -0
- package/src/hw-getAddress.ts +24 -0
- package/src/logic.ts +149 -0
- package/src/preload.ts +54 -0
- package/src/prepareTransaction.ts +176 -0
- package/src/signOperation.ts +127 -0
- package/src/specs.ts +344 -0
- package/src/speculos-deviceActions.ts +83 -0
- package/src/synchronization.ts +317 -0
- package/src/testUtils.ts +153 -0
- package/src/transaction.ts +193 -0
- package/src/types.ts +132 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { FeeTooHigh } from "@ledgerhq/errors";
|
|
2
|
+
import type {
|
|
3
|
+
AccountRaw,
|
|
4
|
+
CurrenciesData,
|
|
5
|
+
DatasetTest,
|
|
6
|
+
} from "@ledgerhq/types-live";
|
|
7
|
+
import { BigNumber } from "bignumber.js";
|
|
8
|
+
import ethereumScanAccounts1 from "./datasets/ethereum.scanAccounts.1";
|
|
9
|
+
import { ethereum1 } from "./datasets/ethereum1";
|
|
10
|
+
import { fromTransactionRaw } from "./transaction";
|
|
11
|
+
import type { Transaction } from "./types";
|
|
12
|
+
|
|
13
|
+
const ethereum: CurrenciesData<Transaction> = {
|
|
14
|
+
scanAccounts: [ethereumScanAccounts1],
|
|
15
|
+
accounts: [
|
|
16
|
+
{
|
|
17
|
+
implementations: ["js"],
|
|
18
|
+
raw: ethereum1 as AccountRaw,
|
|
19
|
+
transactions: [
|
|
20
|
+
{
|
|
21
|
+
name: "Send",
|
|
22
|
+
transaction: fromTransactionRaw({
|
|
23
|
+
family: "evm",
|
|
24
|
+
mode: "send",
|
|
25
|
+
recipient: "0x17733CAb76d9A2112576443F21735789733B1ca3",
|
|
26
|
+
amount: "10000000000000",
|
|
27
|
+
gasPrice: "100000000",
|
|
28
|
+
gasLimit: "21000",
|
|
29
|
+
chainId: 1,
|
|
30
|
+
nonce: 0,
|
|
31
|
+
}),
|
|
32
|
+
expectedStatus: {
|
|
33
|
+
amount: new BigNumber(10000000000000),
|
|
34
|
+
estimatedFees: new BigNumber(2100000000000),
|
|
35
|
+
totalSpent: new BigNumber(12100000000000),
|
|
36
|
+
errors: {},
|
|
37
|
+
warnings: {
|
|
38
|
+
feeTooHigh: new FeeTooHigh(),
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "Send max",
|
|
44
|
+
transaction: fromTransactionRaw({
|
|
45
|
+
family: "evm",
|
|
46
|
+
mode: "send",
|
|
47
|
+
recipient: "0x17733CAb76d9A2112576443F21735789733B1ca3",
|
|
48
|
+
amount: "1",
|
|
49
|
+
gasPrice: "100000000",
|
|
50
|
+
gasLimit: "21000",
|
|
51
|
+
chainId: 1,
|
|
52
|
+
nonce: 0,
|
|
53
|
+
useAllAmount: true,
|
|
54
|
+
}),
|
|
55
|
+
expectedStatus: (account, _, status) => {
|
|
56
|
+
return {
|
|
57
|
+
amount: BigNumber.max(
|
|
58
|
+
account.balance.minus(status.estimatedFees),
|
|
59
|
+
0
|
|
60
|
+
),
|
|
61
|
+
errors: {},
|
|
62
|
+
warnings: {},
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const dataset: DatasetTest<Transaction> = {
|
|
72
|
+
implementations: ["mock", "js"],
|
|
73
|
+
currencies: {
|
|
74
|
+
ethereum,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
describe("EVM bridge", () => {
|
|
79
|
+
test.todo(
|
|
80
|
+
"This is an empty test to make jest command pass. Remove it once there is a real test."
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* NOTE: if tests are added to this file,
|
|
86
|
+
* like done in libs/coin-polkadot/src/bridge.integration.test.ts for example,
|
|
87
|
+
* this file fill need to be imported in ledger-live-common
|
|
88
|
+
* libs/ledger-live-common/src/families/algorand/bridge.integration.test.ts
|
|
89
|
+
* like done for polkadot.
|
|
90
|
+
* cf.
|
|
91
|
+
* - libs/coin-polkadot/src/bridge.integration.test.ts
|
|
92
|
+
* - libs/ledger-live-common/src/families/polkadot/bridge.integration.test.ts
|
|
93
|
+
*/
|
package/src/broadcast.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
2
|
+
import type { AccountBridge, Operation } from "@ledgerhq/types-live";
|
|
3
|
+
import { broadcastTransaction } from "./api/rpc";
|
|
4
|
+
import { Transaction as EvmTransaction } from "./types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Broadcast a transaction and update the operation linked
|
|
8
|
+
*/
|
|
9
|
+
export const broadcast: AccountBridge<EvmTransaction>["broadcast"] = async ({
|
|
10
|
+
account,
|
|
11
|
+
signedOperation: { signature, operation },
|
|
12
|
+
}) => {
|
|
13
|
+
const txResponse = await broadcastTransaction(account.currency, signature);
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
...operation,
|
|
17
|
+
id: encodeOperationId(operation.accountId, txResponse.hash, operation.type),
|
|
18
|
+
hash: txResponse.hash,
|
|
19
|
+
blockNumber: txResponse.blockNumber,
|
|
20
|
+
blockHeight: txResponse.blockNumber,
|
|
21
|
+
blockHash: txResponse.blockHash,
|
|
22
|
+
date: new Date(
|
|
23
|
+
txResponse.timestamp ? txResponse.timestamp * 1000 : Date.now()
|
|
24
|
+
),
|
|
25
|
+
subOperations:
|
|
26
|
+
operation.subOperations?.map((subOp) => ({
|
|
27
|
+
...subOp,
|
|
28
|
+
id: encodeOperationId(subOp.accountId, txResponse.hash, subOp.type),
|
|
29
|
+
hash: txResponse.hash,
|
|
30
|
+
blockNumber: txResponse.blockNumber,
|
|
31
|
+
blockHeight: txResponse.blockNumber,
|
|
32
|
+
blockHash: txResponse.blockHash,
|
|
33
|
+
date: new Date(
|
|
34
|
+
txResponse.timestamp ? txResponse.timestamp * 1000 : Date.now()
|
|
35
|
+
),
|
|
36
|
+
})) || [],
|
|
37
|
+
} as Operation;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default broadcast;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { findSubAccountById } from "@ledgerhq/coin-framework/account/index";
|
|
2
|
+
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
3
|
+
import {
|
|
4
|
+
Account,
|
|
5
|
+
Operation,
|
|
6
|
+
OperationType,
|
|
7
|
+
TokenAccount,
|
|
8
|
+
} from "@ledgerhq/types-live";
|
|
9
|
+
import BigNumber from "bignumber.js";
|
|
10
|
+
import eip55 from "eip55";
|
|
11
|
+
import { getEstimatedFees } from "./logic";
|
|
12
|
+
import { Transaction as EvmTransaction } from "./types";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Build an optimistic operation for the coin of the integration (e.g. Ether for Ethereum)
|
|
16
|
+
*/
|
|
17
|
+
export const buildOptimisticCoinOperation = (
|
|
18
|
+
account: Account,
|
|
19
|
+
transaction: EvmTransaction,
|
|
20
|
+
transactionType?: OperationType
|
|
21
|
+
): Operation => {
|
|
22
|
+
const type = transactionType ?? "OUT";
|
|
23
|
+
const estimatedFees = getEstimatedFees(transaction);
|
|
24
|
+
const value = transaction.amount.plus(estimatedFees);
|
|
25
|
+
|
|
26
|
+
// keys marked with a <-- will be updated by the broadcast method
|
|
27
|
+
const operation: Operation = {
|
|
28
|
+
id: encodeOperationId(account.id, "", type), // <--
|
|
29
|
+
hash: "", // <--
|
|
30
|
+
type,
|
|
31
|
+
value,
|
|
32
|
+
fee: estimatedFees,
|
|
33
|
+
blockHash: null, // <--
|
|
34
|
+
blockHeight: null, // <--
|
|
35
|
+
senders: [eip55.encode(account.freshAddress)],
|
|
36
|
+
recipients: [eip55.encode(transaction.recipient)],
|
|
37
|
+
accountId: account.id,
|
|
38
|
+
transactionSequenceNumber: transaction.nonce,
|
|
39
|
+
date: new Date(), // <--
|
|
40
|
+
extra: {},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return operation;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build an optimistic operation for an ERC20 transaction
|
|
48
|
+
*/
|
|
49
|
+
export const buildOptimisticTokenOperation = (
|
|
50
|
+
account: Account,
|
|
51
|
+
tokenAccount: TokenAccount,
|
|
52
|
+
transaction: EvmTransaction
|
|
53
|
+
): Operation => {
|
|
54
|
+
const type = "OUT";
|
|
55
|
+
const estimatedFees = getEstimatedFees(transaction);
|
|
56
|
+
const value = transaction.useAllAmount
|
|
57
|
+
? tokenAccount.balance
|
|
58
|
+
: transaction.amount;
|
|
59
|
+
|
|
60
|
+
const coinOperation = buildOptimisticCoinOperation(
|
|
61
|
+
account,
|
|
62
|
+
{
|
|
63
|
+
...transaction,
|
|
64
|
+
recipient: tokenAccount.token.contractAddress,
|
|
65
|
+
amount: new BigNumber(0),
|
|
66
|
+
},
|
|
67
|
+
"FEES"
|
|
68
|
+
);
|
|
69
|
+
// keys marked with a <-- will be updated by the broadcast method
|
|
70
|
+
const operation: Operation = {
|
|
71
|
+
...coinOperation,
|
|
72
|
+
subOperations: [
|
|
73
|
+
{
|
|
74
|
+
id: encodeOperationId(tokenAccount.id, "", type), // <--
|
|
75
|
+
hash: "", // <--
|
|
76
|
+
type,
|
|
77
|
+
value,
|
|
78
|
+
fee: estimatedFees,
|
|
79
|
+
blockHash: null, // <--
|
|
80
|
+
blockHeight: null, // <--
|
|
81
|
+
senders: [eip55.encode(account.freshAddress)],
|
|
82
|
+
recipients: [eip55.encode(transaction.recipient)],
|
|
83
|
+
accountId: tokenAccount.id,
|
|
84
|
+
transactionSequenceNumber: transaction.nonce,
|
|
85
|
+
date: new Date(), // <--
|
|
86
|
+
extra: {},
|
|
87
|
+
contract: tokenAccount.token.contractAddress,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
return operation;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Create a temporary operation to use until it's confirmed by the blockchain
|
|
97
|
+
*/
|
|
98
|
+
export const buildOptimisticOperation = (
|
|
99
|
+
account: Account,
|
|
100
|
+
transaction: EvmTransaction
|
|
101
|
+
): Operation => {
|
|
102
|
+
const subAccount = findSubAccountById(
|
|
103
|
+
account,
|
|
104
|
+
transaction?.subAccountId || ""
|
|
105
|
+
);
|
|
106
|
+
const isTokenTransaction = subAccount?.type === "TokenAccount";
|
|
107
|
+
|
|
108
|
+
return isTokenTransaction
|
|
109
|
+
? buildOptimisticTokenOperation(account, subAccount, transaction)
|
|
110
|
+
: buildOptimisticCoinOperation(account, transaction);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default buildOptimisticOperation;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NetworkRequestCall } from "@ledgerhq/coin-framework/network";
|
|
2
|
+
import { LRUCacheFn } from "@ledgerhq/coin-framework/cache";
|
|
3
|
+
|
|
4
|
+
// Needed by sync-families-dispatch script
|
|
5
|
+
// libs/ledger-live-common/scripts/sync-families-dispatch.mjs
|
|
6
|
+
export default function makeCliTools(
|
|
7
|
+
_network: NetworkRequestCall,
|
|
8
|
+
_cache: LRUCacheFn
|
|
9
|
+
) {
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { Account, AccountBridge } from "@ledgerhq/types-live";
|
|
3
|
+
import { Transaction as EvmTransaction } from "./types";
|
|
4
|
+
import { DEFAULT_GAS_LIMIT } from "./transaction";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* EVM Transaction factory.
|
|
8
|
+
* By default the transaction is an EIP-1559 transaction.
|
|
9
|
+
* @see prepareTransaction that will make sure it's compatible or not
|
|
10
|
+
*/
|
|
11
|
+
export const createTransaction: AccountBridge<EvmTransaction>["createTransaction"] =
|
|
12
|
+
(account) => ({
|
|
13
|
+
family: "evm",
|
|
14
|
+
mode: "send",
|
|
15
|
+
amount: new BigNumber(0),
|
|
16
|
+
useAllAmount: false,
|
|
17
|
+
recipient: "",
|
|
18
|
+
maxFeePerGas: new BigNumber(0),
|
|
19
|
+
maxPriorityFeePerGas: new BigNumber(0),
|
|
20
|
+
gasLimit: DEFAULT_GAS_LIMIT,
|
|
21
|
+
nonce: account.operationsCount + 1,
|
|
22
|
+
chainId: (account as Account).currency?.ethereumLikeInfo?.chainId || 0,
|
|
23
|
+
feesStrategy: "medium",
|
|
24
|
+
type: 2,
|
|
25
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
name: "ethereum seed 1",
|
|
3
|
+
unstableAccounts: true, // FIXME LL-9155
|
|
4
|
+
apdus: `
|
|
5
|
+
=> e00200000d038000002c8000003c80000000
|
|
6
|
+
<= 410469877df9567b58e6ef8f6cf1fb8a8e1bf28a327dee31b183a6b9cd1f3da063af0924506a9912793ef31e41df19f8653fa31bb1fecc32d2e41abdddb22ccb621028373561453661383832363036353137343345356546433033373937313136413335363539663638359000
|
|
7
|
+
=> e002000011048000002c8000003c8000000000000000
|
|
8
|
+
<= 4104b7577f404537d1e934a8d2a1fd2552a7f399928b5af0aad714acc17b36865b3f5d1843d6a580c737c051656ac35978283a388a759911d289e9994071247d167528356466304333363936343142384166336337653961653037364535343636654636373833313943649000
|
|
9
|
+
=> e002000011048000002c8000003c8000000000000001
|
|
10
|
+
<= 4104bee21a16156c645d0150e262c40648b9fd938c6462efe3adf9051efe077d30b356c86b8bc8a182e58cdc514e6d0c2670f6626d34f78220187e2d279d661d23f628446336313732383838343733383239324134373236353042624133653936433261344638383739369000
|
|
11
|
+
=> e002000011048000002c8000003c8000000000000002
|
|
12
|
+
<= 410467f77bf213f0de5fd7ae7ac2ca2b6f7ad6cacecbb8688acd0bcf0fcc5b7b58512fe786639619b9f4a513061dd0355590ec5b7d2c4d934c43a37778920bf07e1a28623262344230413836384543326530613162326533314131304142414130393365463032386544389000
|
|
13
|
+
=> e002000011048000002c8000003c8000000000000003
|
|
14
|
+
<= 4104dcce479cd733a7972cea67f0b5bf92d786a1e62a9afe5e50ddd2f7f7c8c1aaff89e28b236f5f1e75c702c3c0116de49dde6b32f06f66937f0b190bdd730bd84e28613563334139333430364465323733666639386244443343653935314232653431423137436443469000
|
|
15
|
+
=> e002000011048000002c8000003c8000000000000004
|
|
16
|
+
<= 4104b60582b8ea13540e5292396949f9d2ed23d9ec4344e2463e9fe7fa36c12372da03a0427c48d653dd59abfcbb7628b323076415f1fd53bc601b8071d82ddd635528393945363561463136626644393139303246623638394163373938343338633042464334373439359000
|
|
17
|
+
=> e002000011048000002c8000003c8000000000000005
|
|
18
|
+
<= 4104126bf90b475158cb8c947dbe47d9ecdff88c34c96c7b7f4fc17a05257dff1024c089fd51f657fa7f5b1041d23bc67d46cd0dd4df86c5318f653486199313e18f28663736394533463933663831313733653836333365354461653646433031426262443163634230389000
|
|
19
|
+
=> e002000011048000002c8000003c8000000000000006
|
|
20
|
+
<= 4104dc7934183510e92e07136e9192da7d5bbd4c3a757b4d9bdf8dcca9baabdf8efddfad24ef74e8a0db52d9e4171516665ff6e4cd152273f460627933df3ced177828463439386638653139323342653437633335343932376445334332313661633341453734666535619000
|
|
21
|
+
=> e002000011048000002c8000003c8000000000000007
|
|
22
|
+
<= 4104b7664a7012f69cee691362377df6d8558b0acfe1541dbf95af90e919d6867ac9d46b3b0b42e98fe8543c15ae501fed3d85869fd0310d9804faed0d07ae3b871628353932393338336336626631624439666533383462423665363162394232413230416637434361429000
|
|
23
|
+
=> e002000011048000002c8000003c8000000000000008
|
|
24
|
+
<= 41045cdb8bc99d890837444698a53d9c18d22c6159e0727e051fee54e7299318282d3fe882b4aa133e7e15529e90b824b4f83ea5242b3ad4651c7d9cca12c796e45428634339303838363541443934303634623733433739663235393861373966393843654544364446619000
|
|
25
|
+
=> e002000011048000002c8000003c8000000000000009
|
|
26
|
+
<= 4104720ec99d2297e627e239764e519be6900d06fc3d9145e306daeace60944c3c6dc14e74f24d27fc98278c0c07de821bae71ed5c95e9a7b95538637e817763609128373731663039424535353143386346393734426141426336373365324232323132643637383236469000
|
|
27
|
+
=> e002000011048000002c8000003c800000000000000a
|
|
28
|
+
<= 41043a98496a4115f61e264bd74ba1ea661729ccfa239e72318ecbd307fb747d2032be5e308e435b24417320a95b719d60b7740b0bf297f926b414b4d3b44d903a9f28384138383238373537353662333831336262613844644631376634304232363064423232466334379000
|
|
29
|
+
=> e002000011048000002c8000003c800000000000000b
|
|
30
|
+
<= 41040f3a6497cdef24c68b895a0d8a9f8b54e16ee84e4905a24236a242a82a900e068cb72ad71f52b57dfa41e00090cd035d1a4205dbe3982ac88189c743edb856a828646431344537456135384533384343316134653737386265663338323831664139413134353232419000
|
|
31
|
+
=> e002000015058000002c8000003c800000000000000000000001
|
|
32
|
+
<= 41040374fb34926a57e184cdd3438109021b3169a9c74ffe726d1abc7a187fa9440a11f071b96f72c8e9e0ea1f82dc2180166bd8c7bae9401cdd3d2466a40e1755ca28304536613732456439323243323338394466303365383666354537394261374336344535343933379000
|
|
33
|
+
=> e002000015058000002c8000003c800000000000000000000000
|
|
34
|
+
<= 410478f6d00bc3be349f69a8b88b3957d569d7ed44d27d0824988107ba1a6117cfcefc22b03b9be870ddadb643eeda4357761d44419cfbdccb19701be086780ff71128304533463062623935313646303166324333346332354530393537353138623861433934313463359000
|
|
35
|
+
=> e002000015058000002c8000003c800000010000000000000000
|
|
36
|
+
<= 4104c20d717f7652a279588b267457c051e387fbeb8648b730cd3daeaa8fa3774f37ab535ab9bd024b87776b77b3409546a0b64e1b14828ea43891b4200318fc90fd28363637463942453934613432343538636235334133413636353131446361313962333937373338649000
|
|
37
|
+
=> e002000015058000002c8000003c800000020000000000000000
|
|
38
|
+
<= 4104e788111a6c0254ec8184453383d2d8b18c8e0b86d1fea93c2691a9bc6240572f24129a634155d1291228a1721fc88737f75e51bb7575ccc69937d649c1422ea028386639353530323931314338316135454332626134623831356564326432433565316338383932359000
|
|
39
|
+
=> e002000015058000002c8000003c800000030000000000000000
|
|
40
|
+
<= 4104ffd79641446518c675ad32e6434a2aba9e7c426200bc336d78222cbec00d2c8aa7a8c685084f450870e2a801049795ba051f8b3a878a586158697d6bd4ce0b6d28386261343131303566464135343531306362394436376362334137323632344434303532634130389000
|
|
41
|
+
=> e002000015058000002c8000003c800000040000000000000000
|
|
42
|
+
<= 4104602f7c0f3f73a914b3dd83e8bb6f11f3dc8ea1d2c7308fa4f8d9d2000a4419eec324393f4cf191e83f3adc64de9388f5979664c6d6dac4c23c0566d7aabbddfa28366233343933464531383145413238336530333335653544384437363865323132326243366331389000
|
|
43
|
+
=> e002000015058000002c8000003c800000050000000000000000
|
|
44
|
+
<= 410484f94dfa2c52fee4f8b37b578b0087de88ee282cb788a56af1eabd7711ddd37e6da1c9eada59926b7828d7e12db21c443ed0a2ca4521561806d3175407a557c128323546456139343435344664334137413138443935383131463565346562353733633163434334329000
|
|
45
|
+
=> e002000015058000002c8000003c800000060000000000000000
|
|
46
|
+
<= 4104e7c7f373d0a568554b5372b68f6e697aee3947c053ee5d882afba2f2c9a44273768b2e61b01de519b0c1f365e23aea5e3d041a40a347a125e202a2d7d7ef596828624636373337664138373538463134443838376531646633323442423431363136334533366436319000
|
|
47
|
+
`,
|
|
48
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AccountRaw } from "@ledgerhq/types-live";
|
|
2
|
+
|
|
3
|
+
export const ethereum1: AccountRaw = {
|
|
4
|
+
id: "js:1:ethereum:0x0E3F0bb9516F01f2C34c25E0957518b8aC9414c5:",
|
|
5
|
+
seedIdentifier: "0x0E3F0bb9516F01f2C34c25E0957518b8aC9414c5",
|
|
6
|
+
name: "Ethereum legacy xpub6Bem...JyAdpYZy",
|
|
7
|
+
derivationMode: "",
|
|
8
|
+
index: 0,
|
|
9
|
+
freshAddress: "0x0E3F0bb9516F01f2C34c25E0957518b8aC9414c5",
|
|
10
|
+
freshAddressPath: "44'/60'/0'/0/0",
|
|
11
|
+
freshAddresses: [],
|
|
12
|
+
pendingOperations: [],
|
|
13
|
+
operations: [],
|
|
14
|
+
currencyId: "ethereum",
|
|
15
|
+
unitMagnitude: 18,
|
|
16
|
+
balance: "",
|
|
17
|
+
blockHeight: 0,
|
|
18
|
+
lastSyncDate: "",
|
|
19
|
+
xpub: "",
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AccountRaw } from "@ledgerhq/types-live";
|
|
2
|
+
|
|
3
|
+
export const ethereum2: AccountRaw = {
|
|
4
|
+
id: "js:2:ethereum:0x789d2f10826BF8f3a56Ec524359bBA4e738Af5bF:",
|
|
5
|
+
seedIdentifier: "0x789d2f10826BF8f3a56Ec524359bBA4e738Af5bF",
|
|
6
|
+
name: "Ethereum legacy xpub6Bem...JyAdpYZy",
|
|
7
|
+
derivationMode: "",
|
|
8
|
+
index: 0,
|
|
9
|
+
freshAddress: "0x789d2f10826BF8f3a56Ec524359bBA4e738Af5bF",
|
|
10
|
+
freshAddressPath: "44'/60'/0'/0/0",
|
|
11
|
+
freshAddresses: [],
|
|
12
|
+
pendingOperations: [],
|
|
13
|
+
operations: [],
|
|
14
|
+
currencyId: "ethereum",
|
|
15
|
+
unitMagnitude: 18,
|
|
16
|
+
balance: "",
|
|
17
|
+
blockHeight: 0,
|
|
18
|
+
lastSyncDate: "",
|
|
19
|
+
xpub: "",
|
|
20
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { CurrenciesData } from "@ledgerhq/types-live";
|
|
2
|
+
import type { Transaction } from "../types";
|
|
3
|
+
const dataset: CurrenciesData<Transaction> = {
|
|
4
|
+
scanAccounts: [
|
|
5
|
+
{
|
|
6
|
+
name: "ethereum_classic seed 1",
|
|
7
|
+
apdus: `
|
|
8
|
+
=> e00200000d038000002c8000003d80000000
|
|
9
|
+
<= 4104484d1e44afab12402f8d40684619f916936eb83872b4fb0b0cdcfe84bd73db6adc535ad2d4368ee7d8df42a261e295e04aabc60d80bdb010bd791d5fe87e731d28354564426331363364613164353133363936353530344265423732353361653346303432623542379000
|
|
10
|
+
=> e002000011048000002c8000003c8000000000000000
|
|
11
|
+
<= 4104b7577f404537d1e934a8d2a1fd2552a7f399928b5af0aad714acc17b36865b3f5d1843d6a580c737c051656ac35978283a388a759911d289e9994071247d167528356466304333363936343142384166336337653961653037364535343636654636373833313943649000
|
|
12
|
+
=> e002000011048000002c8000003c8000000000000001
|
|
13
|
+
<= 4104bee21a16156c645d0150e262c40648b9fd938c6462efe3adf9051efe077d30b356c86b8bc8a182e58cdc514e6d0c2670f6626d34f78220187e2d279d661d23f628446336313732383838343733383239324134373236353042624133653936433261344638383739369000
|
|
14
|
+
=> e002000011048000002c8000003c8000000000000002
|
|
15
|
+
<= 410467f77bf213f0de5fd7ae7ac2ca2b6f7ad6cacecbb8688acd0bcf0fcc5b7b58512fe786639619b9f4a513061dd0355590ec5b7d2c4d934c43a37778920bf07e1a28623262344230413836384543326530613162326533314131304142414130393365463032386544389000
|
|
16
|
+
=> e002000011048000002c8000003c8000000000000003
|
|
17
|
+
<= 4104dcce479cd733a7972cea67f0b5bf92d786a1e62a9afe5e50ddd2f7f7c8c1aaff89e28b236f5f1e75c702c3c0116de49dde6b32f06f66937f0b190bdd730bd84e28613563334139333430364465323733666639386244443343653935314232653431423137436443469000
|
|
18
|
+
=> e002000011048000002c8000003c8000000000000004
|
|
19
|
+
<= 4104b60582b8ea13540e5292396949f9d2ed23d9ec4344e2463e9fe7fa36c12372da03a0427c48d653dd59abfcbb7628b323076415f1fd53bc601b8071d82ddd635528393945363561463136626644393139303246623638394163373938343338633042464334373439359000
|
|
20
|
+
=> e002000011048000002c8000003c8000000000000005
|
|
21
|
+
<= 4104126bf90b475158cb8c947dbe47d9ecdff88c34c96c7b7f4fc17a05257dff1024c089fd51f657fa7f5b1041d23bc67d46cd0dd4df86c5318f653486199313e18f28663736394533463933663831313733653836333365354461653646433031426262443163634230389000
|
|
22
|
+
=> e002000011048000002c8000003c8000000000000006
|
|
23
|
+
<= 4104dc7934183510e92e07136e9192da7d5bbd4c3a757b4d9bdf8dcca9baabdf8efddfad24ef74e8a0db52d9e4171516665ff6e4cd152273f460627933df3ced177828463439386638653139323342653437633335343932376445334332313661633341453734666535619000
|
|
24
|
+
=> e002000011048000002c8000003c8000000000000007
|
|
25
|
+
<= 4104b7664a7012f69cee691362377df6d8558b0acfe1541dbf95af90e919d6867ac9d46b3b0b42e98fe8543c15ae501fed3d85869fd0310d9804faed0d07ae3b871628353932393338336336626631624439666533383462423665363162394232413230416637434361429000
|
|
26
|
+
=> e002000011048000002c8000003c8000000000000008
|
|
27
|
+
<= 41045cdb8bc99d890837444698a53d9c18d22c6159e0727e051fee54e7299318282d3fe882b4aa133e7e15529e90b824b4f83ea5242b3ad4651c7d9cca12c796e45428634339303838363541443934303634623733433739663235393861373966393843654544364446619000
|
|
28
|
+
=> e002000011048000002c8000003c8000000000000009
|
|
29
|
+
<= 4104720ec99d2297e627e239764e519be6900d06fc3d9145e306daeace60944c3c6dc14e74f24d27fc98278c0c07de821bae71ed5c95e9a7b95538637e817763609128373731663039424535353143386346393734426141426336373365324232323132643637383236469000
|
|
30
|
+
=> e002000011048000002c8000003c800000000000000a
|
|
31
|
+
<= 41043a98496a4115f61e264bd74ba1ea661729ccfa239e72318ecbd307fb747d2032be5e308e435b24417320a95b719d60b7740b0bf297f926b414b4d3b44d903a9f28384138383238373537353662333831336262613844644631376634304232363064423232466334379000
|
|
32
|
+
=> e002000011048000002c8000003c800000000000000b
|
|
33
|
+
<= 41040f3a6497cdef24c68b895a0d8a9f8b54e16ee84e4905a24236a242a82a900e068cb72ad71f52b57dfa41e00090cd035d1a4205dbe3982ac88189c743edb856a828646431344537456135384533384343316134653737386265663338323831664139413134353232419000
|
|
34
|
+
=> e002000015058000002c8000003c800000000000000000000001
|
|
35
|
+
<= 41040374fb34926a57e184cdd3438109021b3169a9c74ffe726d1abc7a187fa9440a11f071b96f72c8e9e0ea1f82dc2180166bd8c7bae9401cdd3d2466a40e1755ca28304536613732456439323243323338394466303365383666354537394261374336344535343933379000
|
|
36
|
+
=> e002000015058000002c8000003c800273d08000000000000000
|
|
37
|
+
<= 41048ebb30f7ad91340633bf4079b094df192c01e902b978a744463612f4d92779a26a981f940f5d1562ce2f7ece9410e2a510cbf0d58a72213a32ce5a4ac5ba2b4b28384438433044364436313243426531386545393339623438383130326330463266323330306342319000
|
|
38
|
+
=> e002000015058000002c8000003c800273d08000000000000001
|
|
39
|
+
<= 41044a0ed12ec0f81f63916275abb0a598f5cfaed33ee71a446b4cf4aa0c913f2dce6463416384b2da8aed0bc82495de7d98a4b97788a81fccabb6ccf18b02b3103f28304345383662333261393235304639373538393934396231664635386230653439383745426134319000
|
|
40
|
+
=> e002000015058000002c8000003c800273d08000000000000002
|
|
41
|
+
<= 41047c3451f44f8e83a6d1717d02b2d753a6f48d460ce658ac11e49aa7f23e24e9c163c44de44b545e50261ecc56071646aa206449360dc3d868d60f2ecf42f81a3928423234664145303442453136363132323061303939624334614339436334634431463131323735319000
|
|
42
|
+
=> e002000015058000002c8000003c800273d08000000000000003
|
|
43
|
+
<= 41044022220fe926b53f6ae37ab9750436da58de9954fd32b8360a084f6ba1886d89c9b0f5f54bd273eca6aef4efb5a838c1aeaffa679609b4997e4ef4375958abb628313963326334636432636131393732353142623530436235433043323537373532413631416237339000
|
|
44
|
+
=> e002000015058000002c8000003c800273d08000000000000004
|
|
45
|
+
<= 4104f639ceaa8f6bd63edc2168e8016c28bc7bb2e88b1655c5a340eea522121f5da8dd06351dc8329430b02d865b1b62f93ea5d29f6503ee4b79a8cebfdbde0bc03228306435663331313344393237413532333631356139303338644236343963334135613335313766439000
|
|
46
|
+
=> e002000015058000002c8000003c800273d08000000000000005
|
|
47
|
+
<= 4104fab595f8b864663c1dd3dcdcff04e79ef2c552a2a9bfdaa1f2870ee4fbb577d165444d1b88c89a93e7dec0fac582698cfb6d22ca0912fabc8f59b510e8d14aeb28613832643633303962416438343444663331333531646644354563323436333330643036334166339000
|
|
48
|
+
=> e002000015058000002c8000003c800273d08000000000000006
|
|
49
|
+
<= 410428bf0106161a8f6ee85702c927daf25b0933e87f30912c3731dd82cb734b8368358dd7b395f6a308ad10df2e669730e88f4bb25af4e470d0676330c9516c1e3228383946623865386531353134454435383837443430353439313130353033394539616531333861339000
|
|
50
|
+
=> e002000015058000002c8000003c800273d08000000000000007
|
|
51
|
+
<= 4104e9862872e1bd6db9369ce076c73e96cf5c48e3247cb57bc830835d5f9a1b561f170ccc871834083b55ec67146c82674c6198b1b1ff8d388ffc768eb39e1fdf9728323544336463393734353145453137456565363537374661653843453133653936313738623862399000
|
|
52
|
+
=> e002000015058000002c8000003c800273d08000000000000008
|
|
53
|
+
<= 41048267b52b06601d87bf6cc3aced6de50b5f9575b447cffaaf8575fc9ff0e3f20a82476e8798c805ad192946d5a7e0291e15d2ca2aa64554b77ba044d3558dd9bf28304331396631383643323064454241333934393937393431353845316339334641343039626238659000
|
|
54
|
+
=> e002000015058000002c8000003c800273d08000000000000009
|
|
55
|
+
<= 41045a03c0346a5744a2dc91720b58e09e19ca614e014e0ba2b2f16335ad759f94585cecf2be542b9c559b45f13781d19255d9d07b1c2a3c3edd233fe0f31056278c28433663364662643362303365326431463243633064313739413530373444303738313639336242459000
|
|
56
|
+
=> e002000015058000002c8000003c800273d0800000000000000a
|
|
57
|
+
<= 410406b58afef3acc41294fa5b75dacf131e7c0a112cea3fd479d967885fd5a7dd283bedeb63289dba3d941274b74e77a54173ea9f461b785708951dd2cf6425904928424264433236384545463134356539383964376238383342373233323736644130453342353134429000
|
|
58
|
+
=> e002000015058000002c8000003c800273d0800000000000000b
|
|
59
|
+
<= 4104d386c86afec5afc490ac49373c1853d7c52ec77084e79afe6bc4c06506647f16f1cca01cecb9fa9b9c858a88ac3fdea2b0e9db4dfa73bca657eb7f10edeb5e7728324364433246313866303834383337374430394661383862613546653163323865414144363065329000
|
|
60
|
+
=> e002000015058000002c8000003d800000000000000000000000
|
|
61
|
+
<= 4104e6961fb205192c59e2fc93113b38e3e352479b8903be6900db84aa1bb3849c7beb9b60795e61ca1bb8b13be0bf4e9190fffa7021b255d639921d9e46bc82495328363939343037623045453838323936323832303531413165444265623862626635343031466539629000
|
|
62
|
+
=> e002000015058000002c8000003d800000010000000000000000
|
|
63
|
+
<= 4104a7befc3709876c8787641f45c92fc065ffcd873338f41a571482822ae91825364c22ff2cde1ff0f91d8a00926e6ff92e0b5296362f4b6cce3ea02393505dbadb28323863386162303964633038463266363237623538384233363035353930413238363162336344319000
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
export default dataset;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
|
|
2
|
+
import { validateDomain } from "@ledgerhq/domain-service/utils/index";
|
|
3
|
+
import { Account, AccountLike } from "@ledgerhq/types-live";
|
|
4
|
+
|
|
5
|
+
import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
|
|
6
|
+
import { Transaction as EvmTransaction, TransactionStatus } from "./types";
|
|
7
|
+
|
|
8
|
+
type DeviceTransactionField = CommonDeviceTransactionField;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Method responsible for creating the summary of the screens visible on the nano
|
|
12
|
+
*/
|
|
13
|
+
function getDeviceTransactionConfig({
|
|
14
|
+
account,
|
|
15
|
+
parentAccount,
|
|
16
|
+
transaction,
|
|
17
|
+
}: {
|
|
18
|
+
account: AccountLike;
|
|
19
|
+
parentAccount: Account | null | undefined;
|
|
20
|
+
transaction: EvmTransaction;
|
|
21
|
+
status: TransactionStatus;
|
|
22
|
+
}): Array<DeviceTransactionField> {
|
|
23
|
+
const mainAccount = getMainAccount(account, parentAccount);
|
|
24
|
+
const { mode } = transaction;
|
|
25
|
+
const fields: Array<DeviceTransactionField> = [];
|
|
26
|
+
const hasValidDomain = validateDomain(transaction.recipientDomain?.domain);
|
|
27
|
+
|
|
28
|
+
switch (mode) {
|
|
29
|
+
default:
|
|
30
|
+
case "send":
|
|
31
|
+
fields.push(
|
|
32
|
+
{
|
|
33
|
+
type: "amount",
|
|
34
|
+
label: "Amount",
|
|
35
|
+
},
|
|
36
|
+
transaction.recipientDomain && hasValidDomain
|
|
37
|
+
? {
|
|
38
|
+
type: "text",
|
|
39
|
+
label: "Domain",
|
|
40
|
+
value: transaction.recipientDomain.domain,
|
|
41
|
+
}
|
|
42
|
+
: {
|
|
43
|
+
type: "address",
|
|
44
|
+
label: "Address",
|
|
45
|
+
address: transaction.recipient,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
type: "text",
|
|
49
|
+
label: "Network",
|
|
50
|
+
value: mainAccount.currency.name,
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fields.push({
|
|
57
|
+
type: "fees",
|
|
58
|
+
label: "Max fees",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return fields;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default getDeviceTransactionConfig;
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { createCustomErrorClass } from "@ledgerhq/errors";
|
|
2
|
+
|
|
3
|
+
export const EtherscanAPIError = createCustomErrorClass("EtherscanAPIError");
|
|
4
|
+
export const GasEstimationError = createCustomErrorClass("GasEstimationError");
|
|
5
|
+
export const InsufficientFunds = createCustomErrorClass("InsufficientFunds");
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
|
|
2
|
+
import type { AccountBridge } from "@ledgerhq/types-live";
|
|
3
|
+
import { createTransaction } from "./createTransaction";
|
|
4
|
+
import { prepareTransaction } from "./prepareTransaction";
|
|
5
|
+
import { Transaction as EvmTransaction } from "./types";
|
|
6
|
+
|
|
7
|
+
export const estimateMaxSpendable: AccountBridge<EvmTransaction>["estimateMaxSpendable"] =
|
|
8
|
+
async ({ account, parentAccount, transaction }) => {
|
|
9
|
+
const mainAccount = getMainAccount(account, parentAccount);
|
|
10
|
+
const estimatedTx = {
|
|
11
|
+
...createTransaction(mainAccount),
|
|
12
|
+
...transaction,
|
|
13
|
+
useAllAmount: true,
|
|
14
|
+
} as EvmTransaction;
|
|
15
|
+
|
|
16
|
+
const { amount } = await prepareTransaction(mainAccount, estimatedTx);
|
|
17
|
+
|
|
18
|
+
return amount;
|
|
19
|
+
};
|