@ledgerhq/coin-tezos 0.4.0-nightly.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 +20 -0
- package/.turbo/turbo-build.log +4 -0
- package/.unimportedrc.json +39 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE.txt +21 -0
- package/jest.config.js +6 -0
- package/lib/api/bakers.d.ts +14 -0
- package/lib/api/bakers.d.ts.map +1 -0
- package/lib/api/bakers.integration.test.d.ts +2 -0
- package/lib/api/bakers.integration.test.d.ts.map +1 -0
- package/lib/api/bakers.integration.test.js +61 -0
- package/lib/api/bakers.integration.test.js.map +1 -0
- package/lib/api/bakers.js +141 -0
- package/lib/api/bakers.js.map +1 -0
- package/lib/api/bakers.test.d.ts +2 -0
- package/lib/api/bakers.test.d.ts.map +1 -0
- package/lib/api/bakers.test.js +146 -0
- package/lib/api/bakers.test.js.map +1 -0
- package/lib/api/bakers.whitelist-default.d.ts +4 -0
- package/lib/api/bakers.whitelist-default.d.ts.map +1 -0
- package/lib/api/bakers.whitelist-default.js +34 -0
- package/lib/api/bakers.whitelist-default.js.map +1 -0
- package/lib/api/index.d.ts +3 -0
- package/lib/api/index.d.ts.map +1 -0
- package/lib/api/index.js +19 -0
- package/lib/api/index.js.map +1 -0
- package/lib/api/tzkt.d.ts +81 -0
- package/lib/api/tzkt.d.ts.map +1 -0
- package/lib/api/tzkt.js +52 -0
- package/lib/api/tzkt.js.map +1 -0
- package/lib/bridge/broadcast.d.ts +6 -0
- package/lib/bridge/broadcast.d.ts.map +1 -0
- package/lib/bridge/broadcast.js +22 -0
- package/lib/bridge/broadcast.js.map +1 -0
- package/lib/bridge/broadcast.test.d.ts +2 -0
- package/lib/bridge/broadcast.test.d.ts.map +1 -0
- package/lib/bridge/broadcast.test.js +40 -0
- package/lib/bridge/broadcast.test.js.map +1 -0
- package/lib/bridge/createTransaction.d.ts +3 -0
- package/lib/bridge/createTransaction.d.ts.map +1 -0
- package/lib/bridge/createTransaction.js +23 -0
- package/lib/bridge/createTransaction.js.map +1 -0
- package/lib/bridge/deviceTransactionConfig.d.ts +19 -0
- package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -0
- package/lib/bridge/deviceTransactionConfig.js +44 -0
- package/lib/bridge/deviceTransactionConfig.js.map +1 -0
- package/lib/bridge/estimateMaxSpendable.d.ts +10 -0
- package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -0
- package/lib/bridge/estimateMaxSpendable.js +29 -0
- package/lib/bridge/estimateMaxSpendable.js.map +1 -0
- package/lib/bridge/getAccountShape.d.ts +5 -0
- package/lib/bridge/getAccountShape.d.ts.map +1 -0
- package/lib/bridge/getAccountShape.js +253 -0
- package/lib/bridge/getAccountShape.js.map +1 -0
- package/lib/bridge/getAccountShape.test.d.ts +2 -0
- package/lib/bridge/getAccountShape.test.d.ts.map +1 -0
- package/lib/bridge/getAccountShape.test.js +33 -0
- package/lib/bridge/getAccountShape.test.js.map +1 -0
- package/lib/bridge/index.d.ts +8 -0
- package/lib/bridge/index.d.ts.map +1 -0
- package/lib/bridge/index.js +58 -0
- package/lib/bridge/index.js.map +1 -0
- package/lib/bridge/preload.d.ts +9 -0
- package/lib/bridge/preload.d.ts.map +1 -0
- package/lib/bridge/preload.js +32 -0
- package/lib/bridge/preload.js.map +1 -0
- package/lib/bridge/prepareTransaction.d.ts +9 -0
- package/lib/bridge/prepareTransaction.d.ts.map +1 -0
- package/lib/bridge/prepareTransaction.js +157 -0
- package/lib/bridge/prepareTransaction.js.map +1 -0
- package/lib/bridge/serialization.d.ts +7 -0
- package/lib/bridge/serialization.d.ts.map +1 -0
- package/lib/bridge/serialization.js +27 -0
- package/lib/bridge/serialization.js.map +1 -0
- package/lib/bridge/signOperation.d.ts +19 -0
- package/lib/bridge/signOperation.d.ts.map +1 -0
- package/lib/bridge/signOperation.js +147 -0
- package/lib/bridge/signOperation.js.map +1 -0
- package/lib/bridge/signOperation.test.d.ts +2 -0
- package/lib/bridge/signOperation.test.d.ts.map +1 -0
- package/lib/bridge/signOperation.test.js +223 -0
- package/lib/bridge/signOperation.test.js.map +1 -0
- package/lib/bridge/transaction.d.ts +15 -0
- package/lib/bridge/transaction.d.ts.map +1 -0
- package/lib/bridge/transaction.js +52 -0
- package/lib/bridge/transaction.js.map +1 -0
- package/lib/bridge/transactionStatus.d.ts +3 -0
- package/lib/bridge/transactionStatus.d.ts.map +1 -0
- package/lib/bridge/transactionStatus.js +114 -0
- package/lib/bridge/transactionStatus.js.map +1 -0
- package/lib/datasets/tezos.scanAccounts.1.d.ts +7 -0
- package/lib/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
- package/lib/datasets/tezos.scanAccounts.1.js +38 -0
- package/lib/datasets/tezos.scanAccounts.1.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +21 -0
- package/lib/index.js.map +1 -0
- package/lib/signer/getAddress.d.ts +6 -0
- package/lib/signer/getAddress.d.ts.map +1 -0
- package/lib/signer/getAddress.js +19 -0
- package/lib/signer/getAddress.js.map +1 -0
- package/lib/signer/index.d.ts +6 -0
- package/lib/signer/index.d.ts.map +1 -0
- package/lib/signer/index.js +11 -0
- package/lib/signer/index.js.map +1 -0
- package/lib/test/bot-deviceActions.d.ts +4 -0
- package/lib/test/bot-deviceActions.d.ts.map +1 -0
- package/lib/test/bot-deviceActions.js +74 -0
- package/lib/test/bot-deviceActions.js.map +1 -0
- package/lib/test/bot-specs.d.ts +7 -0
- package/lib/test/bot-specs.d.ts.map +1 -0
- package/lib/test/bot-specs.js +154 -0
- package/lib/test/bot-specs.js.map +1 -0
- package/lib/test/bridgeDatasetTest.d.ts +5 -0
- package/lib/test/bridgeDatasetTest.d.ts.map +1 -0
- package/lib/test/bridgeDatasetTest.js +99 -0
- package/lib/test/bridgeDatasetTest.js.map +1 -0
- package/lib/test/cli.d.ts +78 -0
- package/lib/test/cli.d.ts.map +1 -0
- package/lib/test/cli.js +97 -0
- package/lib/test/cli.js.map +1 -0
- package/lib/test/index.d.ts +2 -0
- package/lib/test/index.d.ts.map +1 -0
- package/lib/test/index.js +18 -0
- package/lib/test/index.js.map +1 -0
- package/lib/types/errors.d.ts +4 -0
- package/lib/types/errors.d.ts.map +1 -0
- package/lib/types/errors.js +6 -0
- package/lib/types/errors.js.map +1 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +20 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/model.d.ts +92 -0
- package/lib/types/model.d.ts.map +1 -0
- package/lib/types/model.fixture.d.ts +5 -0
- package/lib/types/model.fixture.d.ts.map +1 -0
- package/lib/types/model.fixture.js +85 -0
- package/lib/types/model.fixture.js.map +1 -0
- package/lib/types/model.js +8 -0
- package/lib/types/model.js.map +1 -0
- package/lib/types/signer.d.ts +37 -0
- package/lib/types/signer.d.ts.map +1 -0
- package/lib/types/signer.js +3 -0
- package/lib/types/signer.js.map +1 -0
- package/lib-es/api/bakers.d.ts +14 -0
- package/lib-es/api/bakers.d.ts.map +1 -0
- package/lib-es/api/bakers.integration.test.d.ts +2 -0
- package/lib-es/api/bakers.integration.test.d.ts.map +1 -0
- package/lib-es/api/bakers.integration.test.js +56 -0
- package/lib-es/api/bakers.integration.test.js.map +1 -0
- package/lib-es/api/bakers.js +125 -0
- package/lib-es/api/bakers.js.map +1 -0
- package/lib-es/api/bakers.test.d.ts +2 -0
- package/lib-es/api/bakers.test.d.ts.map +1 -0
- package/lib-es/api/bakers.test.js +141 -0
- package/lib-es/api/bakers.test.js.map +1 -0
- package/lib-es/api/bakers.whitelist-default.d.ts +4 -0
- package/lib-es/api/bakers.whitelist-default.d.ts.map +1 -0
- package/lib-es/api/bakers.whitelist-default.js +31 -0
- package/lib-es/api/bakers.whitelist-default.js.map +1 -0
- package/lib-es/api/index.d.ts +3 -0
- package/lib-es/api/index.d.ts.map +1 -0
- package/lib-es/api/index.js +3 -0
- package/lib-es/api/index.js.map +1 -0
- package/lib-es/api/tzkt.d.ts +81 -0
- package/lib-es/api/tzkt.d.ts.map +1 -0
- package/lib-es/api/tzkt.js +47 -0
- package/lib-es/api/tzkt.js.map +1 -0
- package/lib-es/bridge/broadcast.d.ts +6 -0
- package/lib-es/bridge/broadcast.d.ts.map +1 -0
- package/lib-es/bridge/broadcast.js +20 -0
- package/lib-es/bridge/broadcast.js.map +1 -0
- package/lib-es/bridge/broadcast.test.d.ts +2 -0
- package/lib-es/bridge/broadcast.test.d.ts.map +1 -0
- package/lib-es/bridge/broadcast.test.js +35 -0
- package/lib-es/bridge/broadcast.test.js.map +1 -0
- package/lib-es/bridge/createTransaction.d.ts +3 -0
- package/lib-es/bridge/createTransaction.d.ts.map +1 -0
- package/lib-es/bridge/createTransaction.js +17 -0
- package/lib-es/bridge/createTransaction.js.map +1 -0
- package/lib-es/bridge/deviceTransactionConfig.d.ts +19 -0
- package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -0
- package/lib-es/bridge/deviceTransactionConfig.js +42 -0
- package/lib-es/bridge/deviceTransactionConfig.js.map +1 -0
- package/lib-es/bridge/estimateMaxSpendable.d.ts +10 -0
- package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -0
- package/lib-es/bridge/estimateMaxSpendable.js +24 -0
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -0
- package/lib-es/bridge/getAccountShape.d.ts +5 -0
- package/lib-es/bridge/getAccountShape.d.ts.map +1 -0
- package/lib-es/bridge/getAccountShape.js +245 -0
- package/lib-es/bridge/getAccountShape.js.map +1 -0
- package/lib-es/bridge/getAccountShape.test.d.ts +2 -0
- package/lib-es/bridge/getAccountShape.test.d.ts.map +1 -0
- package/lib-es/bridge/getAccountShape.test.js +31 -0
- package/lib-es/bridge/getAccountShape.test.js.map +1 -0
- package/lib-es/bridge/index.d.ts +8 -0
- package/lib-es/bridge/index.d.ts.map +1 -0
- package/lib-es/bridge/index.js +51 -0
- package/lib-es/bridge/index.js.map +1 -0
- package/lib-es/bridge/preload.d.ts +9 -0
- package/lib-es/bridge/preload.d.ts.map +1 -0
- package/lib-es/bridge/preload.js +26 -0
- package/lib-es/bridge/preload.js.map +1 -0
- package/lib-es/bridge/prepareTransaction.d.ts +9 -0
- package/lib-es/bridge/prepareTransaction.d.ts.map +1 -0
- package/lib-es/bridge/prepareTransaction.js +150 -0
- package/lib-es/bridge/prepareTransaction.js.map +1 -0
- package/lib-es/bridge/serialization.d.ts +7 -0
- package/lib-es/bridge/serialization.d.ts.map +1 -0
- package/lib-es/bridge/serialization.js +20 -0
- package/lib-es/bridge/serialization.js.map +1 -0
- package/lib-es/bridge/signOperation.d.ts +19 -0
- package/lib-es/bridge/signOperation.d.ts.map +1 -0
- package/lib-es/bridge/signOperation.js +143 -0
- package/lib-es/bridge/signOperation.js.map +1 -0
- package/lib-es/bridge/signOperation.test.d.ts +2 -0
- package/lib-es/bridge/signOperation.test.d.ts.map +1 -0
- package/lib-es/bridge/signOperation.test.js +195 -0
- package/lib-es/bridge/signOperation.test.js.map +1 -0
- package/lib-es/bridge/transaction.d.ts +15 -0
- package/lib-es/bridge/transaction.d.ts.map +1 -0
- package/lib-es/bridge/transaction.js +46 -0
- package/lib-es/bridge/transaction.js.map +1 -0
- package/lib-es/bridge/transactionStatus.d.ts +3 -0
- package/lib-es/bridge/transactionStatus.d.ts.map +1 -0
- package/lib-es/bridge/transactionStatus.js +107 -0
- package/lib-es/bridge/transactionStatus.js.map +1 -0
- package/lib-es/datasets/tezos.scanAccounts.1.d.ts +7 -0
- package/lib-es/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
- package/lib-es/datasets/tezos.scanAccounts.1.js +36 -0
- package/lib-es/datasets/tezos.scanAccounts.1.js.map +1 -0
- package/lib-es/index.d.ts +3 -0
- package/lib-es/index.d.ts.map +1 -0
- package/lib-es/index.js +3 -0
- package/lib-es/index.js.map +1 -0
- package/lib-es/signer/getAddress.d.ts +6 -0
- package/lib-es/signer/getAddress.d.ts.map +1 -0
- package/lib-es/signer/getAddress.js +17 -0
- package/lib-es/signer/getAddress.js.map +1 -0
- package/lib-es/signer/index.d.ts +6 -0
- package/lib-es/signer/index.d.ts.map +1 -0
- package/lib-es/signer/index.js +6 -0
- package/lib-es/signer/index.js.map +1 -0
- package/lib-es/test/bot-deviceActions.d.ts +4 -0
- package/lib-es/test/bot-deviceActions.d.ts.map +1 -0
- package/lib-es/test/bot-deviceActions.js +71 -0
- package/lib-es/test/bot-deviceActions.js.map +1 -0
- package/lib-es/test/bot-specs.d.ts +7 -0
- package/lib-es/test/bot-specs.d.ts.map +1 -0
- package/lib-es/test/bot-specs.js +149 -0
- package/lib-es/test/bot-specs.js.map +1 -0
- package/lib-es/test/bridgeDatasetTest.d.ts +5 -0
- package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -0
- package/lib-es/test/bridgeDatasetTest.js +93 -0
- package/lib-es/test/bridgeDatasetTest.js.map +1 -0
- package/lib-es/test/cli.d.ts +78 -0
- package/lib-es/test/cli.d.ts.map +1 -0
- package/lib-es/test/cli.js +91 -0
- package/lib-es/test/cli.js.map +1 -0
- package/lib-es/test/index.d.ts +2 -0
- package/lib-es/test/index.d.ts.map +1 -0
- package/lib-es/test/index.js +2 -0
- package/lib-es/test/index.js.map +1 -0
- package/lib-es/types/errors.d.ts +4 -0
- package/lib-es/types/errors.d.ts.map +1 -0
- package/lib-es/types/errors.js +3 -0
- package/lib-es/types/errors.js.map +1 -0
- package/lib-es/types/index.d.ts +4 -0
- package/lib-es/types/index.d.ts.map +1 -0
- package/lib-es/types/index.js +4 -0
- package/lib-es/types/index.js.map +1 -0
- package/lib-es/types/model.d.ts +92 -0
- package/lib-es/types/model.d.ts.map +1 -0
- package/lib-es/types/model.fixture.d.ts +5 -0
- package/lib-es/types/model.fixture.d.ts.map +1 -0
- package/lib-es/types/model.fixture.js +76 -0
- package/lib-es/types/model.fixture.js.map +1 -0
- package/lib-es/types/model.js +4 -0
- package/lib-es/types/model.js.map +1 -0
- package/lib-es/types/signer.d.ts +37 -0
- package/lib-es/types/signer.d.ts.map +1 -0
- package/lib-es/types/signer.js +2 -0
- package/lib-es/types/signer.js.map +1 -0
- package/package.json +116 -0
- package/src/README.md +29 -0
- package/src/api/bakers.integration.test.ts +61 -0
- package/src/api/bakers.test.ts +140 -0
- package/src/api/bakers.ts +139 -0
- package/src/api/bakers.whitelist-default.ts +33 -0
- package/src/api/index.ts +2 -0
- package/src/api/tzkt.ts +112 -0
- package/src/bridge/broadcast.test.ts +30 -0
- package/src/bridge/broadcast.ts +18 -0
- package/src/bridge/createTransaction.ts +18 -0
- package/src/bridge/deviceTransactionConfig.ts +74 -0
- package/src/bridge/estimateMaxSpendable.ts +32 -0
- package/src/bridge/getAccountShape.test.ts +22 -0
- package/src/bridge/getAccountShape.ts +289 -0
- package/src/bridge/index.ts +65 -0
- package/src/bridge/preload.ts +18 -0
- package/src/bridge/prepareTransaction.ts +160 -0
- package/src/bridge/serialization.ts +27 -0
- package/src/bridge/signOperation.test.ts +211 -0
- package/src/bridge/signOperation.ts +213 -0
- package/src/bridge/transaction.ts +94 -0
- package/src/bridge/transactionStatus.ts +130 -0
- package/src/datasets/tezos.scanAccounts.1.ts +35 -0
- package/src/index.ts +3 -0
- package/src/signer/getAddress.ts +13 -0
- package/src/signer/index.ts +7 -0
- package/src/test/bot-deviceActions.ts +79 -0
- package/src/test/bot-specs.ts +152 -0
- package/src/test/bridgeDatasetTest.ts +132 -0
- package/src/test/cli.ts +137 -0
- package/src/test/index.ts +1 -0
- package/src/types/errors.ts +5 -0
- package/src/types/index.ts +3 -0
- package/src/types/model.fixture.ts +89 -0
- package/src/types/model.ts +123 -0
- package/src/types/signer.ts +48 -0
- package/tsconfig.json +13 -0
- package/types/@taquito/ledger-signer/index.d.ts +3 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { Transaction } from "../types";
|
|
3
|
+
|
|
4
|
+
export default function createTransaction(): Transaction {
|
|
5
|
+
return {
|
|
6
|
+
family: "tezos",
|
|
7
|
+
mode: "send",
|
|
8
|
+
amount: new BigNumber(0),
|
|
9
|
+
fees: null,
|
|
10
|
+
gasLimit: null,
|
|
11
|
+
storageLimit: null,
|
|
12
|
+
recipient: "",
|
|
13
|
+
networkInfo: null,
|
|
14
|
+
useAllAmount: false,
|
|
15
|
+
taquitoError: null,
|
|
16
|
+
estimatedFees: null,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { AccountLike, Account } from "@ledgerhq/types-live";
|
|
2
|
+
import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
|
|
3
|
+
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
|
|
4
|
+
import type { Transaction, TransactionStatus } from "../types";
|
|
5
|
+
|
|
6
|
+
export type ExtraDeviceTransactionField =
|
|
7
|
+
| {
|
|
8
|
+
type: "tezos.delegateValidator";
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
| {
|
|
12
|
+
type: "tezos.storageLimit";
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
type DeviceTransactionField = CommonDeviceTransactionField | ExtraDeviceTransactionField;
|
|
16
|
+
|
|
17
|
+
function getDeviceTransactionConfig({
|
|
18
|
+
account,
|
|
19
|
+
parentAccount,
|
|
20
|
+
transaction: { mode, recipient },
|
|
21
|
+
status: { amount, estimatedFees },
|
|
22
|
+
}: {
|
|
23
|
+
account: AccountLike;
|
|
24
|
+
parentAccount: Account | null | undefined;
|
|
25
|
+
transaction: Transaction;
|
|
26
|
+
status: TransactionStatus;
|
|
27
|
+
}): Array<DeviceTransactionField> {
|
|
28
|
+
const mainAccount = getMainAccount(account, parentAccount);
|
|
29
|
+
const source = mainAccount.freshAddress;
|
|
30
|
+
const isDelegateOperation = mode === "delegate";
|
|
31
|
+
const fields: Array<DeviceTransactionField> = [
|
|
32
|
+
{
|
|
33
|
+
type: "address",
|
|
34
|
+
label: "Source",
|
|
35
|
+
address: source,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
if (isDelegateOperation) {
|
|
40
|
+
fields.push(
|
|
41
|
+
{
|
|
42
|
+
type: "tezos.delegateValidator",
|
|
43
|
+
label: "Validator",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: "address",
|
|
47
|
+
label: "Delegate",
|
|
48
|
+
address: recipient,
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!amount.isZero()) {
|
|
54
|
+
fields.push({
|
|
55
|
+
type: "amount",
|
|
56
|
+
label: "Amount",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!estimatedFees.isZero()) {
|
|
61
|
+
fields.push({
|
|
62
|
+
type: "fees",
|
|
63
|
+
label: "Fees",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fields.push({
|
|
68
|
+
type: "tezos.storageLimit",
|
|
69
|
+
label: "Storage Limit",
|
|
70
|
+
});
|
|
71
|
+
return fields;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export default getDeviceTransactionConfig;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { Account, AccountLike } from "@ledgerhq/types-live";
|
|
3
|
+
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
|
|
4
|
+
import { TezosAccount, Transaction } from "../types";
|
|
5
|
+
import prepareTransaction from "./prepareTransaction";
|
|
6
|
+
import createTransaction from "./createTransaction";
|
|
7
|
+
import { getTransactionStatus } from "./transactionStatus";
|
|
8
|
+
|
|
9
|
+
const TEZOS_BURN_ADDRESS = "tz1burnburnburnburnburnburnburjAYjjX";
|
|
10
|
+
|
|
11
|
+
const estimateMaxSpendable = async ({
|
|
12
|
+
account,
|
|
13
|
+
parentAccount,
|
|
14
|
+
transaction,
|
|
15
|
+
}: {
|
|
16
|
+
account: AccountLike;
|
|
17
|
+
parentAccount: Account | undefined;
|
|
18
|
+
transaction: Transaction;
|
|
19
|
+
}): Promise<BigNumber> => {
|
|
20
|
+
const mainAccount = getMainAccount(account, parentAccount) as TezosAccount;
|
|
21
|
+
const t = await prepareTransaction(mainAccount, {
|
|
22
|
+
...createTransaction(),
|
|
23
|
+
...transaction,
|
|
24
|
+
// estimate using a burn address that exists so we don't enter into NotEnoughBalanceBecauseDestinationNotCreated
|
|
25
|
+
recipient: transaction?.recipient || TEZOS_BURN_ADDRESS,
|
|
26
|
+
useAllAmount: true,
|
|
27
|
+
});
|
|
28
|
+
const s = await getTransactionStatus(mainAccount, t);
|
|
29
|
+
return s.amount;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default estimateMaxSpendable;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getEnv, setEnv } from "@ledgerhq/live-env";
|
|
2
|
+
import { fetchAllTransactions } from "./getAccountShape";
|
|
3
|
+
|
|
4
|
+
jest.setTimeout(2 * 60 * 1000);
|
|
5
|
+
|
|
6
|
+
describe("TEZOS_MAX_TX_QUERIES", () => {
|
|
7
|
+
const bigAccount = "tz1boBHAVpwcvKkNFAQHYr7mjxAz1PpVgKq7";
|
|
8
|
+
test("default have more than 100 txs", async () => {
|
|
9
|
+
const txs = await fetchAllTransactions(bigAccount);
|
|
10
|
+
expect(txs.length).toBeGreaterThan(100);
|
|
11
|
+
});
|
|
12
|
+
test("lowering it to 1 will only fetch a few txs", async () => {
|
|
13
|
+
const cur = getEnv("TEZOS_MAX_TX_QUERIES");
|
|
14
|
+
setEnv("TEZOS_MAX_TX_QUERIES", 1);
|
|
15
|
+
try {
|
|
16
|
+
const txs = await fetchAllTransactions(bigAccount);
|
|
17
|
+
expect(txs.length).toBeLessThanOrEqual(100);
|
|
18
|
+
} finally {
|
|
19
|
+
setEnv("TEZOS_MAX_TX_QUERIES", cur);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { BigNumber } from "bignumber.js";
|
|
2
|
+
import invariant from "invariant";
|
|
3
|
+
import bs58check from "bs58check";
|
|
4
|
+
import blake2b from "blake2b";
|
|
5
|
+
import { log } from "@ledgerhq/logs";
|
|
6
|
+
import { getEnv } from "@ledgerhq/live-env";
|
|
7
|
+
import type { Account, OperationType, TokenAccount } from "@ledgerhq/types-live";
|
|
8
|
+
import {
|
|
9
|
+
areAllOperationsLoaded,
|
|
10
|
+
decodeAccountId,
|
|
11
|
+
encodeAccountId,
|
|
12
|
+
} from "@ledgerhq/coin-framework/account/index";
|
|
13
|
+
import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
14
|
+
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
15
|
+
import api, { type APIOperation } from "../api/tzkt";
|
|
16
|
+
import { TezosOperation } from "../types";
|
|
17
|
+
|
|
18
|
+
function reconciliatePublicKey(
|
|
19
|
+
publicKey: string | undefined,
|
|
20
|
+
initialAccount: Account | undefined,
|
|
21
|
+
): string {
|
|
22
|
+
if (publicKey) return publicKey;
|
|
23
|
+
if (initialAccount) {
|
|
24
|
+
const { xpubOrAddress } = decodeAccountId(initialAccount.id);
|
|
25
|
+
return xpubOrAddress;
|
|
26
|
+
}
|
|
27
|
+
throw new Error("publicKey wasn't properly restored");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const encodeAddress = (publicKey: Buffer) => {
|
|
31
|
+
const curve = 0;
|
|
32
|
+
const curveData = {
|
|
33
|
+
pkB58Prefix: Buffer.from([13, 15, 37, 217]),
|
|
34
|
+
pkhB58Prefix: Buffer.from([6, 161, 159]),
|
|
35
|
+
compressPublicKey: (publicKey: Buffer, curve: number) => {
|
|
36
|
+
publicKey = publicKey.slice(0);
|
|
37
|
+
publicKey[0] = curve;
|
|
38
|
+
return publicKey;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const publicKeyBuf = curveData.compressPublicKey(publicKey, curve);
|
|
42
|
+
const key = publicKeyBuf.slice(1);
|
|
43
|
+
const keyHashSize = 20;
|
|
44
|
+
// eslint-disable-next-line prefer-const
|
|
45
|
+
const hash = Buffer.alloc(keyHashSize);
|
|
46
|
+
const blakHash = blake2b(keyHashSize);
|
|
47
|
+
blakHash.update(key);
|
|
48
|
+
blakHash.digest(hash);
|
|
49
|
+
const address = bs58check.encode(Buffer.concat([curveData.pkhB58Prefix, hash]));
|
|
50
|
+
return address;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function isStringHex(s: string): boolean {
|
|
54
|
+
for (let i = 0; i < s.length; i += 2) {
|
|
55
|
+
const ss = s.slice(i, i + 2);
|
|
56
|
+
const x = parseInt(ss, 16);
|
|
57
|
+
if (Number.isNaN(x)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const getAccountShape: GetAccountShape = async infoInput => {
|
|
65
|
+
const { initialAccount, rest, currency, derivationMode } = infoInput;
|
|
66
|
+
const publicKey = reconciliatePublicKey(rest?.publicKey, initialAccount);
|
|
67
|
+
invariant(
|
|
68
|
+
isStringHex(publicKey),
|
|
69
|
+
`Invalid public key (${publicKey}). Please reimport your Tezos accounts`,
|
|
70
|
+
);
|
|
71
|
+
const hex = Buffer.from(publicKey, "hex");
|
|
72
|
+
const address = encodeAddress(hex);
|
|
73
|
+
|
|
74
|
+
const accountId = encodeAccountId({
|
|
75
|
+
type: "js",
|
|
76
|
+
version: "2",
|
|
77
|
+
currencyId: currency.id,
|
|
78
|
+
xpubOrAddress: publicKey,
|
|
79
|
+
derivationMode,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const initialStableOperations = (
|
|
83
|
+
initialAccount && initialAccount.id === accountId ? initialAccount.operations : []
|
|
84
|
+
) as TezosOperation[];
|
|
85
|
+
|
|
86
|
+
// fetch transactions, incrementally if possible
|
|
87
|
+
const mostRecentStableOperation = initialStableOperations[0];
|
|
88
|
+
|
|
89
|
+
const lastId =
|
|
90
|
+
initialAccount && areAllOperationsLoaded(initialAccount) && mostRecentStableOperation
|
|
91
|
+
? mostRecentStableOperation.extra.id || undefined
|
|
92
|
+
: undefined;
|
|
93
|
+
|
|
94
|
+
const apiAccountPromise = api.getAccountByAddress(address);
|
|
95
|
+
const blocksCountPromise = api.getBlockCount();
|
|
96
|
+
|
|
97
|
+
const [apiAccount, blockHeight] = await Promise.all([apiAccountPromise, blocksCountPromise]);
|
|
98
|
+
|
|
99
|
+
if (apiAccount.type === "empty") {
|
|
100
|
+
return {
|
|
101
|
+
id: accountId,
|
|
102
|
+
xpub: publicKey,
|
|
103
|
+
freshAddress: address,
|
|
104
|
+
blockHeight,
|
|
105
|
+
lastSyncDate: new Date(),
|
|
106
|
+
tezosResources: {
|
|
107
|
+
revealed: false,
|
|
108
|
+
counter: 0,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const fullySupported = apiAccount.type === "user";
|
|
114
|
+
|
|
115
|
+
const apiOperations = fullySupported ? await fetchAllTransactions(address, lastId) : [];
|
|
116
|
+
|
|
117
|
+
const { revealed, counter } = apiAccount;
|
|
118
|
+
|
|
119
|
+
const tezosResources = {
|
|
120
|
+
revealed,
|
|
121
|
+
counter,
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const balance = new BigNumber(apiAccount.balance);
|
|
125
|
+
const subAccounts: TokenAccount[] = [];
|
|
126
|
+
|
|
127
|
+
const newOps = apiOperations
|
|
128
|
+
.map(txToOp({ address, accountId }))
|
|
129
|
+
.filter(Boolean) as unknown as TezosOperation[]; // force cast because `filter(Boolean)` remove undefined and null value
|
|
130
|
+
|
|
131
|
+
const operations = mergeOps(initialStableOperations, newOps);
|
|
132
|
+
|
|
133
|
+
const accountShape = {
|
|
134
|
+
id: accountId,
|
|
135
|
+
xpub: publicKey,
|
|
136
|
+
freshAddress: address,
|
|
137
|
+
operations,
|
|
138
|
+
balance,
|
|
139
|
+
subAccounts,
|
|
140
|
+
spendableBalance: balance,
|
|
141
|
+
blockHeight,
|
|
142
|
+
lastSyncDate: new Date(),
|
|
143
|
+
tezosResources,
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return accountShape;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const txToOp =
|
|
150
|
+
({ address, accountId }: { address: string; accountId: string }) =>
|
|
151
|
+
(tx: APIOperation): TezosOperation | null | undefined => {
|
|
152
|
+
let type: OperationType;
|
|
153
|
+
let maybeValue;
|
|
154
|
+
let senders: string[] = [];
|
|
155
|
+
let recipients: string[] = [];
|
|
156
|
+
const hasFailed = tx.status ? tx.status !== "applied" : false;
|
|
157
|
+
|
|
158
|
+
switch (tx.type) {
|
|
159
|
+
case "transaction": {
|
|
160
|
+
const initiator = tx.initiator?.address;
|
|
161
|
+
const from = tx.sender?.address;
|
|
162
|
+
const to = tx.target?.address;
|
|
163
|
+
if (from !== address && to !== address && initiator !== address) {
|
|
164
|
+
// failsafe for a case that shouldn't happen.
|
|
165
|
+
console.warn("found tx is unrelated to account! " + tx.hash);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
senders = [from || initiator || ""];
|
|
169
|
+
recipients = [to || ""];
|
|
170
|
+
if (
|
|
171
|
+
(from === address && to === address) || // self tx
|
|
172
|
+
(from !== address && to !== address) // initiator but not in from/to
|
|
173
|
+
) {
|
|
174
|
+
// we just pay fees in that case
|
|
175
|
+
type = "FEES";
|
|
176
|
+
} else {
|
|
177
|
+
type = to === address ? "IN" : "OUT";
|
|
178
|
+
if (!hasFailed) {
|
|
179
|
+
maybeValue = new BigNumber(tx.amount || 0);
|
|
180
|
+
if (maybeValue.eq(0)) {
|
|
181
|
+
type = "FEES";
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case "delegation":
|
|
188
|
+
type = tx.newDelegate ? "DELEGATE" : "UNDELEGATE";
|
|
189
|
+
senders = [address];
|
|
190
|
+
// convention was to use recipient for the new delegation address or "" if undelegation
|
|
191
|
+
recipients = [tx.newDelegate ? tx.newDelegate.address : ""];
|
|
192
|
+
break;
|
|
193
|
+
case "reveal":
|
|
194
|
+
type = "REVEAL";
|
|
195
|
+
senders = [address];
|
|
196
|
+
recipients = [address];
|
|
197
|
+
break;
|
|
198
|
+
case "migration":
|
|
199
|
+
type = tx.balanceChange < 0 ? "OUT" : "IN";
|
|
200
|
+
maybeValue = new BigNumber(Math.abs(tx.balanceChange || 0));
|
|
201
|
+
senders = [address];
|
|
202
|
+
recipients = [address];
|
|
203
|
+
break;
|
|
204
|
+
case "origination":
|
|
205
|
+
type = "CREATE";
|
|
206
|
+
maybeValue = new BigNumber(tx.contractBalance || 0);
|
|
207
|
+
senders = [address];
|
|
208
|
+
recipients = [tx.originatedContract?.address || ""];
|
|
209
|
+
break;
|
|
210
|
+
case "activation":
|
|
211
|
+
type = "IN";
|
|
212
|
+
senders = [address];
|
|
213
|
+
recipients = [address];
|
|
214
|
+
maybeValue = new BigNumber(tx.balance || 0);
|
|
215
|
+
break;
|
|
216
|
+
// TODO more type of tx
|
|
217
|
+
default:
|
|
218
|
+
console.warn("unsupported tx:", tx);
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let { hash } = tx;
|
|
223
|
+
const {
|
|
224
|
+
id,
|
|
225
|
+
allocationFee,
|
|
226
|
+
bakerFee,
|
|
227
|
+
storageFee,
|
|
228
|
+
level: blockHeight,
|
|
229
|
+
block: blockHash,
|
|
230
|
+
timestamp,
|
|
231
|
+
} = tx;
|
|
232
|
+
|
|
233
|
+
if (!hash) {
|
|
234
|
+
// in migration case, there is no hash...
|
|
235
|
+
hash = "";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let value = maybeValue || new BigNumber(0);
|
|
239
|
+
if (type === "IN" && value.eq(0)) {
|
|
240
|
+
return; // not interesting op
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let fee = new BigNumber(bakerFee || 0);
|
|
244
|
+
|
|
245
|
+
if (!hasFailed) {
|
|
246
|
+
fee = fee.plus(allocationFee || 0).plus(storageFee || 0);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (type !== "IN") {
|
|
250
|
+
value = value.plus(fee);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
id: encodeOperationId(accountId, hash, type),
|
|
255
|
+
hash,
|
|
256
|
+
type,
|
|
257
|
+
value,
|
|
258
|
+
fee,
|
|
259
|
+
senders,
|
|
260
|
+
recipients,
|
|
261
|
+
blockHeight,
|
|
262
|
+
blockHash,
|
|
263
|
+
accountId,
|
|
264
|
+
date: new Date(timestamp),
|
|
265
|
+
extra: { id },
|
|
266
|
+
hasFailed,
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export const fetchAllTransactions = async (
|
|
271
|
+
address: string,
|
|
272
|
+
lastId?: number,
|
|
273
|
+
): Promise<APIOperation[]> => {
|
|
274
|
+
let txs: APIOperation[] = [];
|
|
275
|
+
let maxIteration = getEnv("TEZOS_MAX_TX_QUERIES");
|
|
276
|
+
do {
|
|
277
|
+
const r = await api.getAccountOperations(address, { lastId, sort: 0 });
|
|
278
|
+
if (r.length === 0) return txs;
|
|
279
|
+
txs = txs.concat(r);
|
|
280
|
+
const last = txs[txs.length - 1];
|
|
281
|
+
if (!last) return txs;
|
|
282
|
+
lastId = last.id;
|
|
283
|
+
if (!lastId) {
|
|
284
|
+
log("tezos", "id missing!");
|
|
285
|
+
return txs;
|
|
286
|
+
}
|
|
287
|
+
} while (--maxIteration);
|
|
288
|
+
return txs;
|
|
289
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { CurrencyBridge, AccountBridge } from "@ledgerhq/types-live";
|
|
2
|
+
import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
|
|
3
|
+
import {
|
|
4
|
+
defaultUpdateTransaction,
|
|
5
|
+
makeAccountBridgeReceive,
|
|
6
|
+
makeScanAccounts,
|
|
7
|
+
makeSync,
|
|
8
|
+
} from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
9
|
+
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
|
10
|
+
import type { TezosSigner, Transaction } from "../types";
|
|
11
|
+
import signerGetAddress from "../signer";
|
|
12
|
+
import { getAccountShape } from "./getAccountShape";
|
|
13
|
+
import buildSignOperation from "./signOperation";
|
|
14
|
+
import { assignFromAccountRaw, assignToAccountRaw } from "./serialization";
|
|
15
|
+
import { getPreloadStrategy, hydrate, preload } from "./preload";
|
|
16
|
+
import { getTransactionStatus } from "./transactionStatus";
|
|
17
|
+
import prepareTransaction from "./prepareTransaction";
|
|
18
|
+
import estimateMaxSpendable from "./estimateMaxSpendable";
|
|
19
|
+
import createTransaction from "./createTransaction";
|
|
20
|
+
import broadcast from "./broadcast";
|
|
21
|
+
|
|
22
|
+
function buildCurrencyBridge(signerContext: SignerContext<TezosSigner>): CurrencyBridge {
|
|
23
|
+
const getAddress = signerGetAddress(signerContext);
|
|
24
|
+
|
|
25
|
+
const scanAccounts = makeScanAccounts({
|
|
26
|
+
getAccountShape,
|
|
27
|
+
getAddressFn: getAddressWrapper(getAddress),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
getPreloadStrategy,
|
|
32
|
+
preload,
|
|
33
|
+
hydrate,
|
|
34
|
+
scanAccounts,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function buildAccountBridge(signerContext: SignerContext<TezosSigner>): AccountBridge<Transaction> {
|
|
39
|
+
const getAddress = signerGetAddress(signerContext);
|
|
40
|
+
|
|
41
|
+
const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress));
|
|
42
|
+
const signOperation = buildSignOperation(signerContext);
|
|
43
|
+
const sync = makeSync({ getAccountShape });
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
estimateMaxSpendable,
|
|
47
|
+
createTransaction,
|
|
48
|
+
updateTransaction: defaultUpdateTransaction,
|
|
49
|
+
getTransactionStatus,
|
|
50
|
+
prepareTransaction,
|
|
51
|
+
sync,
|
|
52
|
+
receive,
|
|
53
|
+
signOperation,
|
|
54
|
+
broadcast,
|
|
55
|
+
assignFromAccountRaw,
|
|
56
|
+
assignToAccountRaw,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function createBridges(signerContext: SignerContext<TezosSigner>) {
|
|
61
|
+
return {
|
|
62
|
+
currencyBridge: buildCurrencyBridge(signerContext),
|
|
63
|
+
accountBridge: buildAccountBridge(signerContext),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
2
|
+
import { fetchAllBakers, hydrateBakers } from "../api/bakers";
|
|
3
|
+
|
|
4
|
+
export const getPreloadStrategy = (_currency: CryptoCurrency) => ({
|
|
5
|
+
preloadMaxAge: 30 * 1000,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const preload = async () => {
|
|
9
|
+
const bakers = await fetchAllBakers();
|
|
10
|
+
return { bakers };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const hydrate = (data: any) => {
|
|
14
|
+
if (!data || typeof data !== "object") return;
|
|
15
|
+
const { bakers } = data;
|
|
16
|
+
if (!bakers || typeof bakers !== "object" || !Array.isArray(bakers)) return;
|
|
17
|
+
hydrateBakers(bakers);
|
|
18
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { DEFAULT_FEE, DEFAULT_STORAGE_LIMIT, Estimate, TezosToolkit } from "@taquito/taquito";
|
|
3
|
+
import { DerivationType } from "@taquito/ledger-signer";
|
|
4
|
+
import { compressPublicKey } from "@taquito/ledger-signer/dist/lib/utils";
|
|
5
|
+
import { b58cencode, prefix, Prefix, validateAddress, ValidationResult } from "@taquito/utils";
|
|
6
|
+
import { InvalidAddress, RecipientRequired } from "@ledgerhq/errors";
|
|
7
|
+
import { log } from "@ledgerhq/logs";
|
|
8
|
+
import { getEnv } from "@ledgerhq/live-env";
|
|
9
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
10
|
+
import { TezosAccount, Transaction } from "../types";
|
|
11
|
+
|
|
12
|
+
function bnEq(a: BigNumber | null | undefined, b: BigNumber | null | undefined): boolean {
|
|
13
|
+
return !a && !b ? true : !a || !b ? false : a.eq(b);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const validateRecipient = (currency: CryptoCurrency, recipient: string) => {
|
|
17
|
+
let recipientError: Error | null = null;
|
|
18
|
+
const recipientWarning = null;
|
|
19
|
+
if (!recipient) {
|
|
20
|
+
recipientError = new RecipientRequired("");
|
|
21
|
+
} else if (validateAddress(recipient) !== ValidationResult.VALID) {
|
|
22
|
+
recipientError = new InvalidAddress(undefined, {
|
|
23
|
+
currencyName: currency.name,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return Promise.resolve({ recipientError, recipientWarning });
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const prepareTransaction = async (
|
|
30
|
+
account: TezosAccount,
|
|
31
|
+
transaction: Transaction,
|
|
32
|
+
): Promise<Transaction> => {
|
|
33
|
+
const { tezosResources } = account;
|
|
34
|
+
if (!tezosResources) throw new Error("tezosResources is missing");
|
|
35
|
+
|
|
36
|
+
if (account.balance.lte(0)) {
|
|
37
|
+
return Promise.resolve(transaction);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// basic check to confirm the transaction is "complete"
|
|
41
|
+
if (transaction.mode !== "undelegate") {
|
|
42
|
+
if (!transaction.recipient) {
|
|
43
|
+
return Promise.resolve(transaction);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const { recipientError } = await validateRecipient(account.currency, transaction.recipient);
|
|
47
|
+
if (recipientError) {
|
|
48
|
+
return Promise.resolve(transaction);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const encodedPubKey = b58cencode(
|
|
53
|
+
compressPublicKey(Buffer.from(account.xpub || "", "hex"), DerivationType.ED25519),
|
|
54
|
+
prefix[Prefix.EDPK],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
|
|
58
|
+
|
|
59
|
+
tezos.setProvider({
|
|
60
|
+
signer: {
|
|
61
|
+
publicKeyHash: async () => account.freshAddress,
|
|
62
|
+
publicKey: async () => encodedPubKey,
|
|
63
|
+
sign: () => Promise.reject(new Error("unsupported")),
|
|
64
|
+
secretKey: () => Promise.reject(new Error("unsupported")),
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const tx: Transaction = { ...transaction, taquitoError: null };
|
|
69
|
+
|
|
70
|
+
let amount = transaction.amount;
|
|
71
|
+
if (transaction.useAllAmount) {
|
|
72
|
+
amount = new BigNumber(1); // send max do a pre-estimation with minimum amount (taquito refuses 0)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
let estimate: Estimate;
|
|
77
|
+
switch (transaction.mode) {
|
|
78
|
+
case "send":
|
|
79
|
+
estimate = await tezos.estimate.transfer({
|
|
80
|
+
mutez: true,
|
|
81
|
+
to: transaction.recipient,
|
|
82
|
+
amount: amount.toNumber(),
|
|
83
|
+
storageLimit: DEFAULT_STORAGE_LIMIT.ORIGINATION, // https://github.com/TezTech/eztz/blob/master/PROTO_003_FEES.md for originating an account
|
|
84
|
+
});
|
|
85
|
+
break;
|
|
86
|
+
case "delegate":
|
|
87
|
+
estimate = await tezos.estimate.setDelegate({
|
|
88
|
+
source: account.freshAddress,
|
|
89
|
+
delegate: transaction.recipient,
|
|
90
|
+
});
|
|
91
|
+
break;
|
|
92
|
+
case "undelegate":
|
|
93
|
+
estimate = await tezos.estimate.setDelegate({
|
|
94
|
+
source: account.freshAddress,
|
|
95
|
+
});
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
throw new Error("unsupported mode=" + transaction.mode);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (tx.useAllAmount) {
|
|
102
|
+
const totalFees = estimate.suggestedFeeMutez + estimate.burnFeeMutez;
|
|
103
|
+
const maxAmount = account.balance
|
|
104
|
+
.minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
|
|
105
|
+
.toNumber();
|
|
106
|
+
// from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
|
|
107
|
+
// Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
|
|
108
|
+
// we need to increase the gasLimit and fee returned by the estimation
|
|
109
|
+
const gasBuffer = 500;
|
|
110
|
+
const MINIMAL_FEE_PER_GAS_MUTEZ = 0.1;
|
|
111
|
+
const increasedFee = (gasBuffer: number, opSize: number) => {
|
|
112
|
+
return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
|
|
113
|
+
};
|
|
114
|
+
const incr = increasedFee(gasBuffer, Number(estimate.opSize));
|
|
115
|
+
tx.fees = new BigNumber(estimate.suggestedFeeMutez + incr);
|
|
116
|
+
tx.gasLimit = new BigNumber(estimate.gasLimit + gasBuffer);
|
|
117
|
+
tx.amount = maxAmount - incr > 0 ? new BigNumber(maxAmount - incr) : new BigNumber(0);
|
|
118
|
+
} else {
|
|
119
|
+
tx.fees = new BigNumber(estimate.suggestedFeeMutez);
|
|
120
|
+
tx.gasLimit = new BigNumber(estimate.gasLimit);
|
|
121
|
+
tx.storageLimit = new BigNumber(estimate.storageLimit);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
tx.storageLimit = new BigNumber(estimate.storageLimit);
|
|
125
|
+
tx.estimatedFees = tx.fees;
|
|
126
|
+
if (!tezosResources.revealed) {
|
|
127
|
+
tx.estimatedFees = tx.estimatedFees.plus(DEFAULT_FEE.REVEAL);
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
if (typeof e !== "object" || !e) throw e;
|
|
131
|
+
if ("id" in e) {
|
|
132
|
+
tx.taquitoError = (e as { id: string }).id;
|
|
133
|
+
log("taquito-error", "taquito got error " + tx.taquitoError);
|
|
134
|
+
} else if ("status" in e) {
|
|
135
|
+
// in case of http 400, log & ignore (more case to handle)
|
|
136
|
+
log("taquito-network-error", String((e as unknown as { message: string }).message || ""), {
|
|
137
|
+
transaction: tx,
|
|
138
|
+
});
|
|
139
|
+
throw e;
|
|
140
|
+
} else {
|
|
141
|
+
throw e;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// nothing changed
|
|
146
|
+
if (
|
|
147
|
+
bnEq(tx.estimatedFees, transaction.estimatedFees) &&
|
|
148
|
+
bnEq(tx.fees, transaction.fees) &&
|
|
149
|
+
bnEq(tx.gasLimit, transaction.gasLimit) &&
|
|
150
|
+
bnEq(tx.storageLimit, transaction.storageLimit) &&
|
|
151
|
+
bnEq(tx.amount, transaction.amount) &&
|
|
152
|
+
tx.taquitoError === transaction.taquitoError
|
|
153
|
+
) {
|
|
154
|
+
return transaction;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return tx;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export default prepareTransaction;
|