@ledgerhq/live-common 27.0.1-next.0 → 27.1.0-next.2
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/lib/account/serialization.d.ts +2 -0
- package/lib/account/serialization.d.ts.map +1 -1
- package/lib/account/serialization.js +23 -8
- package/lib/account/serialization.js.map +1 -1
- package/lib/api/explorerConfig/index.js +1 -1
- package/lib/api/explorerConfig/index.js.map +1 -1
- package/lib/apps/support.d.ts.map +1 -1
- package/lib/apps/support.js +1 -0
- package/lib/apps/support.js.map +1 -1
- package/lib/families/celo/api/hubble.d.ts +6 -1
- package/lib/families/celo/api/hubble.d.ts.map +1 -1
- package/lib/families/celo/api/hubble.js +135 -13
- package/lib/families/celo/api/hubble.js.map +1 -1
- package/lib/families/celo/api/index.d.ts +1 -1
- package/lib/families/celo/api/index.d.ts.map +1 -1
- package/lib/families/celo/api/index.js +2 -1
- package/lib/families/celo/api/index.js.map +1 -1
- package/lib/families/celo/api/sdk.d.ts +22 -0
- package/lib/families/celo/api/sdk.d.ts.map +1 -1
- package/lib/families/celo/api/sdk.js +168 -1
- package/lib/families/celo/api/sdk.js.map +1 -1
- package/lib/families/celo/bridge/js.d.ts.map +1 -1
- package/lib/families/celo/bridge/js.js +4 -42
- package/lib/families/celo/bridge/js.js.map +1 -1
- package/lib/families/celo/cli-transaction.d.ts +12 -2
- package/lib/families/celo/cli-transaction.d.ts.map +1 -1
- package/lib/families/celo/cli-transaction.js +38 -4
- package/lib/families/celo/cli-transaction.js.map +1 -1
- package/lib/families/celo/datasets/celo.scanAccounts.1.d.ts +1 -0
- package/lib/families/celo/datasets/celo.scanAccounts.1.d.ts.map +1 -1
- package/lib/families/celo/datasets/celo.scanAccounts.1.js +298 -2
- package/lib/families/celo/datasets/celo.scanAccounts.1.js.map +1 -1
- package/lib/families/celo/errors.d.ts +2 -0
- package/lib/families/celo/errors.d.ts.map +1 -0
- package/lib/families/celo/errors.js +6 -0
- package/lib/families/celo/errors.js.map +1 -0
- package/lib/families/celo/js-buildTransaction.d.ts +2 -3
- package/lib/families/celo/js-buildTransaction.d.ts.map +1 -1
- package/lib/families/celo/js-buildTransaction.js +194 -19
- package/lib/families/celo/js-buildTransaction.js.map +1 -1
- package/lib/families/celo/js-createTransaction.d.ts.map +1 -1
- package/lib/families/celo/js-createTransaction.js +3 -1
- package/lib/families/celo/js-createTransaction.js.map +1 -1
- package/lib/families/celo/js-estimateMaxSpendable.d.ts.map +1 -1
- package/lib/families/celo/js-estimateMaxSpendable.js.map +1 -1
- package/lib/families/celo/js-getFeesForTransaction.d.ts +2 -3
- package/lib/families/celo/js-getFeesForTransaction.d.ts.map +1 -1
- package/lib/families/celo/js-getFeesForTransaction.js +137 -10
- package/lib/families/celo/js-getFeesForTransaction.js.map +1 -1
- package/lib/families/celo/js-getTransactionStatus.d.ts +2 -3
- package/lib/families/celo/js-getTransactionStatus.d.ts.map +1 -1
- package/lib/families/celo/js-getTransactionStatus.js +97 -41
- package/lib/families/celo/js-getTransactionStatus.js.map +1 -1
- package/lib/families/celo/js-prepareTransaction.d.ts +2 -3
- package/lib/families/celo/js-prepareTransaction.d.ts.map +1 -1
- package/lib/families/celo/js-prepareTransaction.js +8 -3
- package/lib/families/celo/js-prepareTransaction.js.map +1 -1
- package/lib/families/celo/js-signOperation.d.ts.map +1 -1
- package/lib/families/celo/js-signOperation.js +17 -3
- package/lib/families/celo/js-signOperation.js.map +1 -1
- package/lib/families/celo/js-synchronisation.d.ts.map +1 -1
- package/lib/families/celo/js-synchronisation.js +51 -6
- package/lib/families/celo/js-synchronisation.js.map +1 -1
- package/lib/families/celo/logic.d.ts +21 -0
- package/lib/families/celo/logic.d.ts.map +1 -0
- package/lib/families/celo/logic.js +132 -0
- package/lib/families/celo/logic.js.map +1 -0
- package/lib/families/celo/preload.d.ts +10 -0
- package/lib/families/celo/preload.d.ts.map +1 -0
- package/lib/families/celo/preload.js +118 -0
- package/lib/families/celo/preload.js.map +1 -0
- package/lib/families/celo/react.d.ts +4 -0
- package/lib/families/celo/react.d.ts.map +1 -0
- package/lib/families/celo/react.js +47 -0
- package/lib/families/celo/react.js.map +1 -0
- package/lib/families/celo/serialization.d.ts +4 -0
- package/lib/families/celo/serialization.d.ts.map +1 -0
- package/lib/families/celo/serialization.js +55 -0
- package/lib/families/celo/serialization.js.map +1 -0
- package/lib/families/celo/specs/createActivateVoteMutation.d.ts +4 -0
- package/lib/families/celo/specs/createActivateVoteMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createActivateVoteMutation.js +38 -0
- package/lib/families/celo/specs/createActivateVoteMutation.js.map +1 -0
- package/lib/families/celo/specs/createLockMutation.d.ts +4 -0
- package/lib/families/celo/specs/createLockMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createLockMutation.js +40 -0
- package/lib/families/celo/specs/createLockMutation.js.map +1 -0
- package/lib/families/celo/specs/createRegisterAccountMutation.d.ts +4 -0
- package/lib/families/celo/specs/createRegisterAccountMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createRegisterAccountMutation.js +31 -0
- package/lib/families/celo/specs/createRegisterAccountMutation.js.map +1 -0
- package/lib/families/celo/specs/createRevokeVoteMutation.d.ts +4 -0
- package/lib/families/celo/specs/createRevokeVoteMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createRevokeVoteMutation.js +39 -0
- package/lib/families/celo/specs/createRevokeVoteMutation.js.map +1 -0
- package/lib/families/celo/specs/createSendMutation.d.ts +5 -0
- package/lib/families/celo/specs/createSendMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createSendMutation.js +44 -0
- package/lib/families/celo/specs/createSendMutation.js.map +1 -0
- package/lib/families/celo/specs/createUnlockMutation.d.ts +4 -0
- package/lib/families/celo/specs/createUnlockMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createUnlockMutation.js +37 -0
- package/lib/families/celo/specs/createUnlockMutation.js.map +1 -0
- package/lib/families/celo/specs/createVoteMutation.d.ts +4 -0
- package/lib/families/celo/specs/createVoteMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createVoteMutation.js +51 -0
- package/lib/families/celo/specs/createVoteMutation.js.map +1 -0
- package/lib/families/celo/specs/createWithdrawMutation.d.ts +4 -0
- package/lib/families/celo/specs/createWithdrawMutation.d.ts.map +1 -0
- package/lib/families/celo/specs/createWithdrawMutation.js +36 -0
- package/lib/families/celo/specs/createWithdrawMutation.js.map +1 -0
- package/lib/families/celo/specs/index.d.ts +9 -0
- package/lib/families/celo/specs/index.d.ts.map +1 -0
- package/lib/families/celo/specs/index.js +25 -0
- package/lib/families/celo/specs/index.js.map +1 -0
- package/lib/families/celo/specs.d.ts +1 -1
- package/lib/families/celo/specs.d.ts.map +1 -1
- package/lib/families/celo/specs.js +20 -37
- package/lib/families/celo/specs.js.map +1 -1
- package/lib/families/celo/speculos-deviceActions.d.ts.map +1 -1
- package/lib/families/celo/speculos-deviceActions.js +22 -0
- package/lib/families/celo/speculos-deviceActions.js.map +1 -1
- package/lib/families/celo/transaction.d.ts.map +1 -1
- package/lib/families/celo/transaction.js +8 -6
- package/lib/families/celo/transaction.js.map +1 -1
- package/lib/families/celo/types.d.ts +102 -1
- package/lib/families/celo/types.d.ts.map +1 -1
- package/lib/families/celo/validators.d.ts +3 -0
- package/lib/families/celo/validators.d.ts.map +1 -0
- package/lib/families/celo/validators.js +6 -0
- package/lib/families/celo/validators.js.map +1 -0
- package/lib/families/cosmos/banner.d.ts +10 -0
- package/lib/families/cosmos/banner.d.ts.map +1 -0
- package/lib/families/cosmos/banner.js +133 -0
- package/lib/families/cosmos/banner.js.map +1 -0
- package/lib/families/cosmos/banner.test.d.ts +2 -0
- package/lib/families/cosmos/banner.test.d.ts.map +1 -0
- package/lib/families/cosmos/banner.test.js +233 -0
- package/lib/families/cosmos/banner.test.js.map +1 -0
- package/lib/families/solana/api/chain/instruction/token/types.d.ts +2 -2
- package/lib/generated/cli-transaction.d.ts +12 -2
- package/lib/generated/cli-transaction.d.ts.map +1 -1
- package/lib/operation.d.ts.map +1 -1
- package/lib/operation.js +6 -0
- package/lib/operation.js.map +1 -1
- package/lib/reconciliation.d.ts.map +1 -1
- package/lib/reconciliation.js +11 -0
- package/lib/reconciliation.js.map +1 -1
- package/package.json +3 -4
- package/src/account/serialization.ts +22 -2
- package/src/api/explorerConfig/index.ts +1 -1
- package/src/apps/support.ts +1 -0
- package/src/families/celo/__snapshots__/bridge.integration.test.ts.snap +134 -857
- package/src/families/celo/api/hubble.ts +113 -16
- package/src/families/celo/api/index.ts +1 -1
- package/src/families/celo/api/sdk.ts +88 -0
- package/src/families/celo/bridge/js.ts +2 -3
- package/src/families/celo/cli-transaction.ts +46 -2
- package/src/families/celo/datasets/celo.scanAccounts.1.ts +365 -5
- package/src/families/celo/errors.ts +5 -0
- package/src/families/celo/js-buildTransaction.ts +173 -20
- package/src/families/celo/js-createTransaction.ts +2 -0
- package/src/families/celo/js-estimateMaxSpendable.ts +2 -2
- package/src/families/celo/js-getFeesForTransaction.ts +118 -19
- package/src/families/celo/js-getTransactionStatus.ts +72 -17
- package/src/families/celo/js-prepareTransaction.ts +13 -7
- package/src/families/celo/js-signOperation.ts +22 -5
- package/src/families/celo/js-synchronisation.ts +32 -0
- package/src/families/celo/logic.ts +184 -0
- package/src/families/celo/preload.ts +78 -0
- package/src/families/celo/react.ts +35 -0
- package/src/families/celo/serialization.ts +61 -0
- package/src/families/celo/specs/createActivateVoteMutation.ts +44 -0
- package/src/families/celo/specs/createLockMutation.ts +46 -0
- package/src/families/celo/specs/createRegisterAccountMutation.ts +34 -0
- package/src/families/celo/specs/createRevokeVoteMutation.ts +43 -0
- package/src/families/celo/specs/createSendMutation.ts +44 -0
- package/src/families/celo/specs/createUnlockMutation.ts +44 -0
- package/src/families/celo/specs/createVoteMutation.ts +67 -0
- package/src/families/celo/specs/createWithdrawMutation.ts +44 -0
- package/src/families/celo/specs/index.ts +8 -0
- package/src/families/celo/specs.ts +32 -34
- package/src/families/celo/speculos-deviceActions.ts +21 -2
- package/src/families/celo/transaction.ts +12 -4
- package/src/families/celo/types.ts +113 -0
- package/src/families/celo/validators.ts +2 -0
- package/src/families/cosmos/banner.test.ts +160 -0
- package/src/families/cosmos/banner.ts +87 -0
- package/src/operation.ts +6 -0
- package/src/reconciliation.ts +22 -0
|
@@ -1,38 +1,137 @@
|
|
|
1
|
-
import type { Account } from "@ledgerhq/types-live";
|
|
2
1
|
import { BigNumber } from "bignumber.js";
|
|
3
|
-
import { Transaction } from "
|
|
2
|
+
import type { CeloAccount, Transaction } from "./types";
|
|
4
3
|
import { celoKit } from "./api/sdk";
|
|
4
|
+
import { getPendingStakingOperationAmounts, getVote } from "./logic";
|
|
5
5
|
|
|
6
6
|
const getFeesForTransaction = async ({
|
|
7
7
|
account,
|
|
8
8
|
transaction,
|
|
9
9
|
}: {
|
|
10
|
-
account:
|
|
10
|
+
account: CeloAccount;
|
|
11
11
|
transaction: Transaction;
|
|
12
12
|
}): Promise<BigNumber> => {
|
|
13
|
-
const { amount } = transaction;
|
|
13
|
+
const { amount, index } = transaction;
|
|
14
14
|
const kit = celoKit();
|
|
15
15
|
|
|
16
16
|
// A workaround - estimating gas throws an error if value > funds
|
|
17
|
-
|
|
18
|
-
? account.spendableBalance
|
|
19
|
-
: BigNumber.minimum(amount, account.spendableBalance);
|
|
17
|
+
let value: BigNumber = new BigNumber(0);
|
|
20
18
|
|
|
21
|
-
const
|
|
19
|
+
const pendingOperationAmounts = getPendingStakingOperationAmounts(account);
|
|
20
|
+
const lockedGold = await kit.contracts.getLockedGold();
|
|
21
|
+
const nonvotingLockedGoldBalance =
|
|
22
|
+
await lockedGold.getAccountNonvotingLockedGold(account.freshAddress);
|
|
23
|
+
// Deduct pending vote operations from the non-voting locked balance
|
|
24
|
+
const totalNonVotingLockedBalance = nonvotingLockedGoldBalance.minus(
|
|
25
|
+
pendingOperationAmounts.vote
|
|
26
|
+
);
|
|
27
|
+
// Deduct pending lock operations from the spendable balance
|
|
28
|
+
const totalSpendableBalance = account.spendableBalance.minus(
|
|
29
|
+
pendingOperationAmounts.lock
|
|
30
|
+
);
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
if (
|
|
33
|
+
(transaction.mode === "unlock" || transaction.mode === "vote") &&
|
|
34
|
+
account.celoResources
|
|
35
|
+
) {
|
|
36
|
+
value = transaction.useAllAmount
|
|
37
|
+
? totalNonVotingLockedBalance
|
|
38
|
+
: BigNumber.minimum(amount, totalNonVotingLockedBalance);
|
|
39
|
+
} else if (transaction.mode === "revoke" && account.celoResources) {
|
|
40
|
+
const vote = getVote(account, transaction.recipient, transaction.index);
|
|
41
|
+
if (vote) {
|
|
42
|
+
value = transaction.useAllAmount
|
|
43
|
+
? vote.amount
|
|
44
|
+
: BigNumber.minimum(amount, vote.amount);
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
value = transaction.useAllAmount
|
|
48
|
+
? totalSpendableBalance
|
|
49
|
+
: BigNumber.minimum(amount, totalSpendableBalance);
|
|
50
|
+
}
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
let gas: number | null = null;
|
|
53
|
+
if (transaction.mode === "lock") {
|
|
54
|
+
gas = await lockedGold
|
|
55
|
+
.lock()
|
|
56
|
+
.txo.estimateGas({ from: account.freshAddress, value: value.toFixed() });
|
|
57
|
+
} else if (transaction.mode === "unlock") {
|
|
58
|
+
const lockedGold = await kit.contracts.getLockedGold();
|
|
59
|
+
|
|
60
|
+
gas = await lockedGold
|
|
61
|
+
.unlock(value)
|
|
62
|
+
.txo.estimateGas({ from: account.freshAddress });
|
|
63
|
+
} else if (transaction.mode === "withdraw") {
|
|
64
|
+
const lockedGold = await kit.contracts.getLockedGold();
|
|
65
|
+
|
|
66
|
+
gas = await lockedGold
|
|
67
|
+
.withdraw(index || 0)
|
|
68
|
+
.txo.estimateGas({ from: account.freshAddress });
|
|
69
|
+
} else if (transaction.mode === "vote") {
|
|
70
|
+
const election = await kit.contracts.getElection();
|
|
71
|
+
|
|
72
|
+
const vote = await election.vote(
|
|
73
|
+
transaction.recipient,
|
|
74
|
+
new BigNumber(value)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
gas = await vote.txo.estimateGas({ from: account.freshAddress });
|
|
78
|
+
} else if (transaction.mode === "revoke") {
|
|
79
|
+
const election = await kit.contracts.getElection();
|
|
80
|
+
const accounts = await kit.contracts.getAccounts();
|
|
81
|
+
const voteSignerAccount = await accounts.voteSignerToAccount(
|
|
82
|
+
account.freshAddress
|
|
83
|
+
);
|
|
84
|
+
const revokeTxs = await election.revoke(
|
|
85
|
+
voteSignerAccount,
|
|
86
|
+
transaction.recipient,
|
|
87
|
+
new BigNumber(value)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const revokeTx = revokeTxs.find((transactionObject) => {
|
|
91
|
+
return (
|
|
92
|
+
(transactionObject.txo as any)._method.name ===
|
|
93
|
+
(transaction.index === 0 ? "revokePending" : "revokeActive")
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
if (!revokeTx) return new BigNumber(0);
|
|
35
97
|
|
|
98
|
+
gas = await revokeTx.txo.estimateGas({ from: account.freshAddress });
|
|
99
|
+
} else if (transaction.mode === "activate") {
|
|
100
|
+
const election = await kit.contracts.getElection();
|
|
101
|
+
const accounts = await kit.contracts.getAccounts();
|
|
102
|
+
const voteSignerAccount = await accounts.voteSignerToAccount(
|
|
103
|
+
account.freshAddress
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const activates = await election.activate(voteSignerAccount);
|
|
107
|
+
|
|
108
|
+
const activate = activates.find(
|
|
109
|
+
(a) => a.txo.arguments[0] === transaction.recipient
|
|
110
|
+
);
|
|
111
|
+
if (!activate) return new BigNumber(0);
|
|
112
|
+
|
|
113
|
+
gas = await activate.txo.estimateGas({ from: account.freshAddress });
|
|
114
|
+
} else if (transaction.mode === "register") {
|
|
115
|
+
const accounts = await kit.contracts.getAccounts();
|
|
116
|
+
|
|
117
|
+
gas = await accounts
|
|
118
|
+
.createAccount()
|
|
119
|
+
.txo.estimateGas({ from: account.freshAddress });
|
|
120
|
+
} else {
|
|
121
|
+
const celoToken = await kit.contracts.getGoldToken();
|
|
122
|
+
|
|
123
|
+
const celoTransaction = {
|
|
124
|
+
from: account.freshAddress,
|
|
125
|
+
to: celoToken.address,
|
|
126
|
+
data: celoToken
|
|
127
|
+
.transfer(transaction.recipient, value.toFixed())
|
|
128
|
+
.txo.encodeABI(),
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
gas = await kit.connection.estimateGasWithInflationFactor(celoTransaction);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const gasPrice = new BigNumber(await kit.connection.gasPrice());
|
|
36
135
|
return gasPrice.times(gas);
|
|
37
136
|
};
|
|
38
137
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transaction, TransactionStatus } from "./types";
|
|
1
|
+
import { CeloAccount, Transaction, TransactionStatus } from "./types";
|
|
2
2
|
import {
|
|
3
3
|
AmountRequired,
|
|
4
4
|
FeeNotLoaded,
|
|
@@ -9,10 +9,17 @@ import {
|
|
|
9
9
|
} from "@ledgerhq/errors";
|
|
10
10
|
import { BigNumber } from "bignumber.js";
|
|
11
11
|
import { isValidAddress } from "@celo/utils/lib/address";
|
|
12
|
-
import {
|
|
12
|
+
import { CeloAllFundsWarning } from "./errors";
|
|
13
|
+
import { getPendingStakingOperationAmounts, getVote } from "./logic";
|
|
14
|
+
import { celoKit } from "./api/sdk";
|
|
15
|
+
|
|
16
|
+
const kit = celoKit();
|
|
17
|
+
|
|
18
|
+
// Arbitrary buffer for paying fees of next transactions. 0.05 Celo for ~100 transactions
|
|
19
|
+
const FEES_SAFETY_BUFFER = new BigNumber(5000000000000000);
|
|
13
20
|
|
|
14
21
|
const getTransactionStatus = async (
|
|
15
|
-
account:
|
|
22
|
+
account: CeloAccount,
|
|
16
23
|
transaction: Transaction
|
|
17
24
|
): Promise<TransactionStatus> => {
|
|
18
25
|
const errors: any = {};
|
|
@@ -27,34 +34,82 @@ const getTransactionStatus = async (
|
|
|
27
34
|
errors.fees = new FeeNotLoaded();
|
|
28
35
|
}
|
|
29
36
|
|
|
37
|
+
const pendingOperationAmounts = getPendingStakingOperationAmounts(account);
|
|
38
|
+
const lockedGold = await kit.contracts.getLockedGold();
|
|
39
|
+
const nonvotingLockedGoldBalance =
|
|
40
|
+
await lockedGold.getAccountNonvotingLockedGold(account.freshAddress);
|
|
41
|
+
// Deduct pending vote operations from the non-voting locked balance
|
|
42
|
+
const totalNonVotingLockedBalance = nonvotingLockedGoldBalance.minus(
|
|
43
|
+
pendingOperationAmounts.vote
|
|
44
|
+
);
|
|
45
|
+
// Deduct pending lock operations from the spendable balance
|
|
46
|
+
const totalSpendableBalance = account.spendableBalance.minus(
|
|
47
|
+
pendingOperationAmounts.lock
|
|
48
|
+
);
|
|
30
49
|
const estimatedFees = transaction.fees || new BigNumber(0);
|
|
31
50
|
|
|
32
|
-
let amount =
|
|
33
|
-
|
|
34
|
-
|
|
51
|
+
let amount: BigNumber = new BigNumber(0);
|
|
52
|
+
if (
|
|
53
|
+
useAllAmount &&
|
|
54
|
+
(transaction.mode === "unlock" || transaction.mode === "vote")
|
|
55
|
+
) {
|
|
56
|
+
amount = totalNonVotingLockedBalance ?? new BigNumber(0);
|
|
57
|
+
} else if (useAllAmount && transaction.mode === "revoke") {
|
|
58
|
+
const revoke = getVote(account, transaction.recipient, transaction.index);
|
|
59
|
+
if (revoke?.amount) amount = revoke.amount;
|
|
60
|
+
} else if (useAllAmount) {
|
|
61
|
+
amount = totalSpendableBalance.minus(estimatedFees);
|
|
62
|
+
} else {
|
|
63
|
+
amount = new BigNumber(transaction.amount);
|
|
64
|
+
}
|
|
35
65
|
|
|
36
66
|
if (amount.lt(0)) amount = new BigNumber(0);
|
|
37
67
|
|
|
38
|
-
if (
|
|
39
|
-
errors.amount
|
|
68
|
+
if (
|
|
69
|
+
!errors.amount &&
|
|
70
|
+
(account.celoResources?.lockedBalance.gt(0) ||
|
|
71
|
+
!!account.celoResources?.pendingWithdrawals?.length) &&
|
|
72
|
+
(transaction.useAllAmount ||
|
|
73
|
+
totalSpendableBalance.minus(amount).lt(FEES_SAFETY_BUFFER)) &&
|
|
74
|
+
["send", "lock"].includes(transaction.mode)
|
|
75
|
+
) {
|
|
76
|
+
warnings.amount = new CeloAllFundsWarning();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!["register", "withdraw", "activate"].includes(transaction.mode)) {
|
|
80
|
+
if (amount.lte(0) && !useAllAmount) {
|
|
81
|
+
errors.amount = new AmountRequired();
|
|
82
|
+
}
|
|
40
83
|
}
|
|
41
84
|
|
|
42
85
|
const totalSpent = amount.plus(estimatedFees);
|
|
43
86
|
|
|
44
|
-
if (
|
|
45
|
-
|
|
87
|
+
if (transaction.mode === "unlock" || transaction.mode === "vote") {
|
|
88
|
+
if (totalNonVotingLockedBalance && amount.gt(totalNonVotingLockedBalance)) {
|
|
89
|
+
errors.amount = new NotEnoughBalance();
|
|
90
|
+
}
|
|
91
|
+
} else if (transaction.mode === "revoke") {
|
|
92
|
+
const revoke = getVote(account, transaction.recipient, transaction.index);
|
|
93
|
+
if (revoke?.amount && amount.gt(revoke.amount))
|
|
94
|
+
errors.amount = new NotEnoughBalance();
|
|
95
|
+
} else {
|
|
96
|
+
if (totalSpent.gt(totalSpendableBalance)) {
|
|
97
|
+
errors.amount = new NotEnoughBalance();
|
|
98
|
+
}
|
|
46
99
|
}
|
|
47
100
|
|
|
48
|
-
if (!errors.amount &&
|
|
101
|
+
if (!errors.amount && totalSpendableBalance.lt(estimatedFees)) {
|
|
49
102
|
errors.amount = new NotEnoughBalance();
|
|
50
103
|
}
|
|
51
104
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
105
|
+
if (transaction.mode === "send") {
|
|
106
|
+
if (!transaction.recipient) {
|
|
107
|
+
errors.recipient = new RecipientRequired();
|
|
108
|
+
} else if (!isValidAddress(transaction.recipient)) {
|
|
109
|
+
errors.recipient = new InvalidAddress("", {
|
|
110
|
+
currencyName: account.currency.name,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
58
113
|
}
|
|
59
114
|
|
|
60
115
|
return Promise.resolve({
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import { Transaction } from "./types";
|
|
1
|
+
import { CeloAccount, Transaction } from "./types";
|
|
2
2
|
import getFeesForTransaction from "./js-getFeesForTransaction";
|
|
3
3
|
import { isValidAddress } from "@celo/utils/lib/address";
|
|
4
|
-
import
|
|
4
|
+
import BigNumber from "bignumber.js";
|
|
5
5
|
|
|
6
6
|
const sameFees = (a, b) => (!a || !b ? a === b : a.eq(b));
|
|
7
7
|
|
|
8
8
|
const prepareTransaction = async (
|
|
9
|
-
account:
|
|
9
|
+
account: CeloAccount,
|
|
10
10
|
transaction: Transaction
|
|
11
11
|
) => {
|
|
12
|
+
if (transaction.recipient && !isValidAddress(transaction.recipient))
|
|
13
|
+
return transaction;
|
|
14
|
+
|
|
15
|
+
if (["send", "vote"].includes(transaction.mode) && !transaction.recipient)
|
|
16
|
+
return transaction;
|
|
17
|
+
|
|
12
18
|
if (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
transaction.mode === "vote" &&
|
|
20
|
+
!transaction.useAllAmount &&
|
|
21
|
+
new BigNumber(transaction.amount).lte(0)
|
|
22
|
+
)
|
|
16
23
|
return transaction;
|
|
17
|
-
}
|
|
18
24
|
|
|
19
25
|
const fees = await getFeesForTransaction({ account, transaction });
|
|
20
26
|
|
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
import { BigNumber } from "bignumber.js";
|
|
2
2
|
import { Observable } from "rxjs";
|
|
3
3
|
import { FeeNotLoaded } from "@ledgerhq/errors";
|
|
4
|
-
import type { Transaction } from "./types";
|
|
4
|
+
import type { Transaction, CeloOperationMode, CeloAccount } from "./types";
|
|
5
5
|
import { encodeOperationId } from "../../operation";
|
|
6
6
|
import { CeloApp } from "./hw-app-celo";
|
|
7
7
|
import buildTransaction from "./js-buildTransaction";
|
|
8
8
|
import { rlpEncodedTx, encodeTransaction } from "@celo/wallet-base";
|
|
9
9
|
import { tokenInfoByAddressAndChainId } from "@celo/wallet-ledger/lib/tokens";
|
|
10
10
|
import { withDevice } from "../../hw/deviceAccess";
|
|
11
|
+
|
|
12
|
+
const MODE_TO_TYPE: { [key in CeloOperationMode | "default"]: string } = {
|
|
13
|
+
send: "OUT",
|
|
14
|
+
lock: "LOCK",
|
|
15
|
+
unlock: "UNLOCK",
|
|
16
|
+
withdraw: "WITHDRAW",
|
|
17
|
+
vote: "VOTE",
|
|
18
|
+
revoke: "REVOKE",
|
|
19
|
+
activate: "ACTIVATE",
|
|
20
|
+
register: "REGISTER",
|
|
21
|
+
default: "FEE",
|
|
22
|
+
};
|
|
11
23
|
import type {
|
|
12
24
|
Account,
|
|
13
25
|
Operation,
|
|
26
|
+
OperationType,
|
|
14
27
|
SignOperationEvent,
|
|
15
28
|
} from "@ledgerhq/types-live";
|
|
16
29
|
|
|
@@ -19,9 +32,13 @@ const buildOptimisticOperation = (
|
|
|
19
32
|
transaction: Transaction,
|
|
20
33
|
fee: BigNumber
|
|
21
34
|
): Operation => {
|
|
22
|
-
const type =
|
|
35
|
+
const type = (MODE_TO_TYPE[transaction.mode] ??
|
|
36
|
+
MODE_TO_TYPE.default) as OperationType;
|
|
23
37
|
|
|
24
|
-
const value =
|
|
38
|
+
const value =
|
|
39
|
+
type === "OUT" || type === "LOCK"
|
|
40
|
+
? new BigNumber(transaction.amount).plus(fee)
|
|
41
|
+
: new BigNumber(transaction.amount);
|
|
25
42
|
|
|
26
43
|
const operation: Operation = {
|
|
27
44
|
id: encodeOperationId(account.id, "", type),
|
|
@@ -35,7 +52,7 @@ const buildOptimisticOperation = (
|
|
|
35
52
|
recipients: [transaction.recipient].filter(Boolean),
|
|
36
53
|
accountId: account.id,
|
|
37
54
|
date: new Date(),
|
|
38
|
-
extra: {
|
|
55
|
+
extra: {},
|
|
39
56
|
};
|
|
40
57
|
|
|
41
58
|
return operation;
|
|
@@ -94,7 +111,7 @@ const signOperation = ({
|
|
|
94
111
|
|
|
95
112
|
const celo = new CeloApp(transport);
|
|
96
113
|
const unsignedTransaction = await buildTransaction(
|
|
97
|
-
account,
|
|
114
|
+
account as CeloAccount,
|
|
98
115
|
transaction
|
|
99
116
|
);
|
|
100
117
|
const { chainId, to } = unsignedTransaction;
|
|
@@ -2,10 +2,21 @@ import { encodeAccountId } from "../../account";
|
|
|
2
2
|
import type { GetAccountShape } from "../../bridge/jsHelpers";
|
|
3
3
|
import { makeSync, makeScanAccounts, mergeOps } from "../../bridge/jsHelpers";
|
|
4
4
|
import { getAccountDetails } from "./api";
|
|
5
|
+
import { celoKit } from "./api/sdk";
|
|
6
|
+
import {
|
|
7
|
+
getAccountRegistrationStatus,
|
|
8
|
+
getPendingWithdrawals,
|
|
9
|
+
getVotes,
|
|
10
|
+
} from "./api/sdk";
|
|
11
|
+
|
|
12
|
+
const kit = celoKit();
|
|
5
13
|
|
|
6
14
|
const getAccountShape: GetAccountShape = async (info) => {
|
|
7
15
|
const { address, currency, initialAccount, derivationMode } = info;
|
|
8
16
|
const oldOperations = initialAccount?.operations || [];
|
|
17
|
+
const election = await kit.contracts.getElection();
|
|
18
|
+
const electionConfig = await election.getConfig();
|
|
19
|
+
const lockedGold = await kit.contracts.getLockedGold();
|
|
9
20
|
|
|
10
21
|
const accountId = encodeAccountId({
|
|
11
22
|
type: "js",
|
|
@@ -19,7 +30,18 @@ const getAccountShape: GetAccountShape = async (info) => {
|
|
|
19
30
|
balance,
|
|
20
31
|
spendableBalance,
|
|
21
32
|
operations: newOperations,
|
|
33
|
+
lockedBalance,
|
|
34
|
+
nonvotingLockedBalance,
|
|
22
35
|
} = await getAccountDetails(address, accountId);
|
|
36
|
+
|
|
37
|
+
const accountRegistrationStatus = await getAccountRegistrationStatus(address);
|
|
38
|
+
|
|
39
|
+
const pendingWithdrawals = accountRegistrationStatus
|
|
40
|
+
? await getPendingWithdrawals(address)
|
|
41
|
+
: [];
|
|
42
|
+
|
|
43
|
+
const votes = accountRegistrationStatus ? await getVotes(address) : [];
|
|
44
|
+
|
|
23
45
|
const operations = mergeOps(oldOperations, newOperations);
|
|
24
46
|
const shape = {
|
|
25
47
|
id: accountId,
|
|
@@ -27,6 +49,16 @@ const getAccountShape: GetAccountShape = async (info) => {
|
|
|
27
49
|
spendableBalance,
|
|
28
50
|
operationsCount: operations.length,
|
|
29
51
|
blockHeight,
|
|
52
|
+
celoResources: {
|
|
53
|
+
registrationStatus: accountRegistrationStatus,
|
|
54
|
+
lockedBalance,
|
|
55
|
+
nonvotingLockedBalance,
|
|
56
|
+
pendingWithdrawals,
|
|
57
|
+
votes,
|
|
58
|
+
electionAddress: election.address,
|
|
59
|
+
lockedGoldAddress: lockedGold.address,
|
|
60
|
+
maxNumGroupsVotedFor: electionConfig.maxNumGroupsVotedFor,
|
|
61
|
+
},
|
|
30
62
|
};
|
|
31
63
|
return { ...shape, operations };
|
|
32
64
|
};
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CeloAccount,
|
|
3
|
+
CeloPendingWithdrawal,
|
|
4
|
+
CeloValidatorGroup,
|
|
5
|
+
CeloVote,
|
|
6
|
+
CeloVoteStatus,
|
|
7
|
+
PendingStakingOperationAmounts,
|
|
8
|
+
} from "./types";
|
|
9
|
+
import { BigNumber } from "bignumber.js";
|
|
10
|
+
import { Operation } from "@ledgerhq/types-live";
|
|
11
|
+
|
|
12
|
+
export const PRELOAD_MAX_AGE = 10 * 60 * 1000; // 10 minutes, used for max age in preload strategy
|
|
13
|
+
const LEDGER_BY_FIGMENT_VALIDATOR_GROUP_ADDRESS =
|
|
14
|
+
"0x0861a61Bf679A30680510EcC238ee43B82C5e843";
|
|
15
|
+
|
|
16
|
+
export const availablePendingWithdrawals = (
|
|
17
|
+
account: CeloAccount
|
|
18
|
+
): CeloPendingWithdrawal[] => {
|
|
19
|
+
const { pendingWithdrawals } = account.celoResources || {};
|
|
20
|
+
|
|
21
|
+
return (pendingWithdrawals || []).filter(
|
|
22
|
+
(withdrawal) => new Date(withdrawal.time.toNumber() * 1000) < new Date()
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const withdrawableBalance = (account: CeloAccount): BigNumber =>
|
|
27
|
+
availablePendingWithdrawals(account).reduce(
|
|
28
|
+
(sum, withdrawal) => sum.plus(withdrawal.value),
|
|
29
|
+
new BigNumber(0)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export const hasWithdrawableBalance = (account: CeloAccount): boolean =>
|
|
33
|
+
withdrawableBalance(account).isGreaterThan(0);
|
|
34
|
+
|
|
35
|
+
export const defaultValidatorGroupAddress = (): string =>
|
|
36
|
+
LEDGER_BY_FIGMENT_VALIDATOR_GROUP_ADDRESS;
|
|
37
|
+
|
|
38
|
+
export const isDefaultValidatorGroupAddress = (address: string): boolean =>
|
|
39
|
+
address === LEDGER_BY_FIGMENT_VALIDATOR_GROUP_ADDRESS;
|
|
40
|
+
|
|
41
|
+
export const isDefaultValidatorGroup = (
|
|
42
|
+
validatorGroup: CeloValidatorGroup
|
|
43
|
+
): boolean => isDefaultValidatorGroupAddress(validatorGroup.address);
|
|
44
|
+
|
|
45
|
+
export const activatableVotes = (account: CeloAccount): CeloVote[] => {
|
|
46
|
+
const { votes } = account.celoResources || {};
|
|
47
|
+
|
|
48
|
+
return (votes || []).filter((vote) => vote.activatable);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const hasActivatableVotes = (account: CeloAccount): boolean =>
|
|
52
|
+
activatableVotes(account).length > 0;
|
|
53
|
+
|
|
54
|
+
export const revokableVotes = (account: CeloAccount): CeloVote[] => {
|
|
55
|
+
const { votes } = account.celoResources || {};
|
|
56
|
+
|
|
57
|
+
return (votes || []).filter((vote) => vote.revokable);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const hasRevokableVotes = (account: CeloAccount): boolean =>
|
|
61
|
+
revokableVotes(account).length > 0;
|
|
62
|
+
|
|
63
|
+
export const getVote = (
|
|
64
|
+
account: CeloAccount,
|
|
65
|
+
validatorGroupAddress: string,
|
|
66
|
+
index: number | null | undefined
|
|
67
|
+
): CeloVote | undefined => {
|
|
68
|
+
const { votes } = account.celoResources || {};
|
|
69
|
+
return votes?.find(
|
|
70
|
+
(revoke) =>
|
|
71
|
+
revoke.validatorGroup === validatorGroupAddress && revoke.index == index
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const voteStatus = (vote: CeloVote): CeloVoteStatus =>
|
|
76
|
+
vote.type === "pending" && vote.activatable
|
|
77
|
+
? "awaitingActivation"
|
|
78
|
+
: vote.type;
|
|
79
|
+
|
|
80
|
+
export const fallbackValidatorGroup = (
|
|
81
|
+
address: string
|
|
82
|
+
): CeloValidatorGroup => ({
|
|
83
|
+
address: address,
|
|
84
|
+
name: address,
|
|
85
|
+
votes: new BigNumber(0),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const isAccountRegistrationPending = (
|
|
89
|
+
accountId: string,
|
|
90
|
+
accounts: CeloAccount[]
|
|
91
|
+
): boolean => {
|
|
92
|
+
// If there's a pending "REGISTER" operation and the
|
|
93
|
+
// account's registration status is false, then
|
|
94
|
+
// we know that the account is truly not registered yet.
|
|
95
|
+
const account = accounts.find(
|
|
96
|
+
(currentAccount) => accountId === currentAccount.id
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const isAccountRegistrationPending =
|
|
100
|
+
!!account &&
|
|
101
|
+
account.pendingOperations.some(
|
|
102
|
+
(currentAccount) => currentAccount.type === "REGISTER"
|
|
103
|
+
) &&
|
|
104
|
+
!account.celoResources?.registrationStatus;
|
|
105
|
+
|
|
106
|
+
return isAccountRegistrationPending;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const isOperationTrulyPending = (
|
|
110
|
+
operation: Operation,
|
|
111
|
+
activeOperations: Operation[]
|
|
112
|
+
): boolean => {
|
|
113
|
+
if (
|
|
114
|
+
activeOperations.some(
|
|
115
|
+
(activeOperation) => activeOperation.hash === operation.hash
|
|
116
|
+
)
|
|
117
|
+
) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return true;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const initialPendingStakingOperationAmounts: PendingStakingOperationAmounts = {
|
|
125
|
+
vote: new BigNumber(0),
|
|
126
|
+
lock: new BigNumber(0),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const getPendingStakingOperationAmounts = (
|
|
130
|
+
account: CeloAccount
|
|
131
|
+
): PendingStakingOperationAmounts => {
|
|
132
|
+
const operationAmounts = account.pendingOperations.reduce(
|
|
133
|
+
(acc, currentOperation) => {
|
|
134
|
+
if (
|
|
135
|
+
currentOperation.type !== "VOTE" &&
|
|
136
|
+
currentOperation.type !== "LOCK"
|
|
137
|
+
) {
|
|
138
|
+
return acc;
|
|
139
|
+
}
|
|
140
|
+
if (isOperationTrulyPending(currentOperation, account.operations)) {
|
|
141
|
+
const value = new BigNumber(currentOperation.value);
|
|
142
|
+
switch (currentOperation.type) {
|
|
143
|
+
case "VOTE":
|
|
144
|
+
return {
|
|
145
|
+
...acc,
|
|
146
|
+
vote: acc.vote.plus(value),
|
|
147
|
+
};
|
|
148
|
+
case "LOCK":
|
|
149
|
+
return {
|
|
150
|
+
...acc,
|
|
151
|
+
lock: acc.lock.plus(value),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return acc;
|
|
157
|
+
},
|
|
158
|
+
initialPendingStakingOperationAmounts
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
return operationAmounts;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const getValidatorGroupsByVotingActivity = (
|
|
165
|
+
validatorGroups: CeloValidatorGroup[],
|
|
166
|
+
votes: CeloVote[],
|
|
167
|
+
withVotes: boolean
|
|
168
|
+
): CeloValidatorGroup[] => {
|
|
169
|
+
return validatorGroups.filter(
|
|
170
|
+
(v) => votes.some((d) => d.validatorGroup === v.address) === withVotes
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const getValidatorGroupsWithVotes = (
|
|
175
|
+
validatorGroups: CeloValidatorGroup[],
|
|
176
|
+
votes: CeloVote[] | null
|
|
177
|
+
): CeloValidatorGroup[] =>
|
|
178
|
+
getValidatorGroupsByVotingActivity(validatorGroups, votes || [], true);
|
|
179
|
+
|
|
180
|
+
export const getValidatorGroupsWithoutVotes = (
|
|
181
|
+
validatorGroups: CeloValidatorGroup[],
|
|
182
|
+
votes: CeloVote[] | null = []
|
|
183
|
+
): CeloValidatorGroup[] =>
|
|
184
|
+
getValidatorGroupsByVotingActivity(validatorGroups, votes || [], false);
|