@ledgerhq/live-common 21.21.2 → 21.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/Ethereum.d.ts.map +1 -1
- package/lib/api/Ethereum.js +2 -1
- package/lib/api/Ethereum.js.map +1 -1
- package/lib/apps/polyfill.d.ts.map +1 -1
- package/lib/apps/polyfill.js +1 -0
- package/lib/apps/polyfill.js.map +1 -1
- package/lib/bot/engine.js +1 -1
- package/lib/bot/engine.js.map +1 -1
- package/lib/bot/specs.d.ts +1 -0
- package/lib/bot/specs.d.ts.map +1 -1
- package/lib/bot/specs.js +3 -1
- package/lib/bot/specs.js.map +1 -1
- package/lib/env.js +2 -2
- package/lib/env.js.map +1 -1
- package/lib/families/ethereum/signOperation.d.ts.map +1 -1
- package/lib/families/ethereum/signOperation.js +2 -2
- package/lib/families/ethereum/signOperation.js.map +1 -1
- package/lib/families/tezos/bridge/js.d.ts.map +1 -1
- package/lib/families/tezos/bridge/js.js +90 -50
- package/lib/families/tezos/bridge/js.js.map +1 -1
- package/lib/families/tezos/bridge/libcore.d.ts.map +1 -1
- package/lib/families/tezos/bridge/libcore.js +2 -1
- package/lib/families/tezos/bridge/libcore.js.map +1 -1
- package/lib/families/tezos/bridge/mock.d.ts.map +1 -1
- package/lib/families/tezos/bridge/mock.js +2 -1
- package/lib/families/tezos/bridge/mock.js.map +1 -1
- package/lib/families/tezos/signOperation.d.ts.map +1 -1
- package/lib/families/tezos/signOperation.js +28 -19
- package/lib/families/tezos/signOperation.js.map +1 -1
- package/lib/families/tezos/specs.d.ts.map +1 -1
- package/lib/families/tezos/specs.js +8 -4
- package/lib/families/tezos/specs.js.map +1 -1
- package/lib/families/tezos/speculos-deviceActions.js +6 -7
- package/lib/families/tezos/speculos-deviceActions.js.map +1 -1
- package/lib/families/tezos/synchronisation.d.ts.map +1 -1
- package/lib/families/tezos/synchronisation.js +7 -4
- package/lib/families/tezos/synchronisation.js.map +1 -1
- package/lib/families/tezos/synchronisation.test.d.ts.map +1 -1
- package/lib/families/tezos/synchronisation.test.js +0 -3
- package/lib/families/tezos/synchronisation.test.js.map +1 -1
- package/lib/families/tezos/test-dataset.d.ts +2 -2
- package/lib/families/tezos/test-dataset.d.ts.map +1 -1
- package/lib/families/tezos/test-dataset.js +45 -319
- package/lib/families/tezos/test-dataset.js.map +1 -1
- package/lib/families/tezos/transaction.d.ts +2 -2
- package/lib/families/tezos/transaction.d.ts.map +1 -1
- package/lib/families/tezos/transaction.js +4 -4
- package/lib/families/tezos/transaction.js.map +1 -1
- package/lib/families/tezos/types.d.ts +2 -0
- package/lib/families/tezos/types.d.ts.map +1 -1
- package/lib/families/tezos/types.js.map +1 -1
- package/lib/generated/transaction.d.ts +1 -1
- package/package.json +9 -9
- package/src/api/Ethereum.ts +3 -1
- package/src/apps/polyfill.ts +1 -0
- package/src/bot/engine.ts +1 -1
- package/src/bot/specs.ts +7 -1
- package/src/env.ts +2 -2
- package/src/families/ethereum/signOperation.ts +2 -2
- package/src/families/tezos/bridge/js.ts +77 -36
- package/src/families/tezos/bridge/libcore.ts +1 -0
- package/src/families/tezos/bridge/mock.ts +1 -0
- package/src/families/tezos/signOperation.ts +19 -8
- package/src/families/tezos/specs.ts +16 -5
- package/src/families/tezos/speculos-deviceActions.ts +5 -5
- package/src/families/tezos/synchronisation.test.ts +0 -3
- package/src/families/tezos/synchronisation.ts +6 -3
- package/src/families/tezos/test-dataset.ts +33 -363
- package/src/families/tezos/transaction.ts +7 -1
- package/src/families/tezos/types.ts +2 -0
package/src/api/Ethereum.ts
CHANGED
|
@@ -210,7 +210,9 @@ export const apiForCurrency = (currency: CryptoCurrency): API => {
|
|
|
210
210
|
async getNFTMetadata(input) {
|
|
211
211
|
const { data }: { data: NFTMetadataResponse[] } = await network({
|
|
212
212
|
method: "POST",
|
|
213
|
-
url:
|
|
213
|
+
url:
|
|
214
|
+
getEnv("NFT_ETH_METADATA_SERVICE") +
|
|
215
|
+
"/v1/ethereum/1/contracts/tokens/infos",
|
|
214
216
|
data: input,
|
|
215
217
|
});
|
|
216
218
|
|
package/src/apps/polyfill.ts
CHANGED
|
@@ -52,6 +52,7 @@ export const whitelistDependencies = ["Decred", "Decred Testnet"];
|
|
|
52
52
|
["RocketPool", "Ethereum"],
|
|
53
53
|
["POAP", "Ethereum"],
|
|
54
54
|
["OlympusDAO", "Ethereum"],
|
|
55
|
+
["Rarible", "Ethereum"],
|
|
55
56
|
].forEach(([name, dep]) => declareDep(name, dep));
|
|
56
57
|
export const getDependencies = (appName: string): string[] =>
|
|
57
58
|
directDep[appName] || [];
|
package/src/bot/engine.ts
CHANGED
|
@@ -678,7 +678,7 @@ function transactionTest<T>({
|
|
|
678
678
|
const dt = Date.now().valueOf() - operation.date.valueOf();
|
|
679
679
|
invariant(dt > 0, "operation.date must not be in in future");
|
|
680
680
|
expect(dt).toBeLessThan(timingThreshold);
|
|
681
|
-
invariant(!operation.hasFailed, "operation
|
|
681
|
+
invariant(!operation.hasFailed, "operation has failed");
|
|
682
682
|
const { blockAvgTime } = account.currency;
|
|
683
683
|
|
|
684
684
|
if (blockAvgTime && account.blockHeight) {
|
package/src/bot/specs.ts
CHANGED
|
@@ -6,6 +6,9 @@ import sample from "lodash/sample";
|
|
|
6
6
|
import { isAccountEmpty } from "../account";
|
|
7
7
|
import type { DeviceAction, DeviceActionArg } from "./types";
|
|
8
8
|
import type { Account, Transaction } from "../types";
|
|
9
|
+
|
|
10
|
+
const stepValueTransformDefault = (s) => s.trim();
|
|
11
|
+
|
|
9
12
|
// TODO should weight the choice to favorize accounts with small amounts
|
|
10
13
|
export function pickSiblings(siblings: Account[], maxAccount = 5): Account {
|
|
11
14
|
const withoutEmpties = siblings.filter((a) => a.used);
|
|
@@ -37,6 +40,7 @@ type State<T extends Transaction> = {
|
|
|
37
40
|
};
|
|
38
41
|
type Step<T extends Transaction> = {
|
|
39
42
|
title: string;
|
|
43
|
+
stepValueTransform?: (string) => string;
|
|
40
44
|
expectedValue?: (
|
|
41
45
|
arg0: DeviceActionArg<T, State<T>>,
|
|
42
46
|
acc: Array<{
|
|
@@ -79,10 +83,12 @@ export function deviceActionFlow<T extends Transaction>(
|
|
|
79
83
|
// there were accumulated text and we are on new step, we need to release it and compare to expected
|
|
80
84
|
if (currentStep && currentStep.expectedValue) {
|
|
81
85
|
const { expectedValue, ignoreAssertionFailure } = currentStep;
|
|
86
|
+
const stepValueTransform =
|
|
87
|
+
currentStep.stepValueTransform || stepValueTransformDefault;
|
|
82
88
|
|
|
83
89
|
if (!ignoreAssertionFailure) {
|
|
84
90
|
expect({
|
|
85
|
-
[stepTitle]: stepValue
|
|
91
|
+
[stepTitle]: stepValueTransform(stepValue),
|
|
86
92
|
}).toMatchObject({
|
|
87
93
|
[stepTitle]: expectedValue(arg, acc).trim(),
|
|
88
94
|
});
|
package/src/env.ts
CHANGED
|
@@ -111,7 +111,7 @@ const envDefinitions = {
|
|
|
111
111
|
desc: "Ledger explorer API for tezos",
|
|
112
112
|
},
|
|
113
113
|
API_TEZOS_TZKT_API: {
|
|
114
|
-
def: "
|
|
114
|
+
def: "https://xtz-tzkt-explorer.api.live.ledger.com",
|
|
115
115
|
parser: stringParser,
|
|
116
116
|
desc: "tzkt.io explorer",
|
|
117
117
|
},
|
|
@@ -387,7 +387,7 @@ const envDefinitions = {
|
|
|
387
387
|
desc: "set the currencies where NFT is active",
|
|
388
388
|
},
|
|
389
389
|
NFT_ETH_METADATA_SERVICE: {
|
|
390
|
-
def: "https://nft.api.live.ledger.com
|
|
390
|
+
def: "https://nft.api.live.ledger.com",
|
|
391
391
|
parser: stringParser,
|
|
392
392
|
desc: "service uri used to get the metadata of an nft",
|
|
393
393
|
},
|
|
@@ -14,6 +14,7 @@ import { apiForCurrency } from "../../api/Ethereum";
|
|
|
14
14
|
import { withDevice } from "../../hw/deviceAccess";
|
|
15
15
|
import { modes } from "./modules";
|
|
16
16
|
import { isNFTActive } from "../../nft";
|
|
17
|
+
import { getEnv } from "../../env";
|
|
17
18
|
export const signOperation = ({
|
|
18
19
|
account,
|
|
19
20
|
deviceId,
|
|
@@ -63,9 +64,8 @@ export const signOperation = ({
|
|
|
63
64
|
const eth = new Eth(transport);
|
|
64
65
|
if (isNFTActive(account.currency)) {
|
|
65
66
|
eth.setLoadConfig({
|
|
66
|
-
// FIXME drop this after LL-8001
|
|
67
67
|
nftExplorerBaseURL:
|
|
68
|
-
"
|
|
68
|
+
getEnv("NFT_ETH_METADATA_SERVICE") + "/v1/ethereum",
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
// FIXME this part is still required for compound to correctly display info on the device
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
NotEnoughBalance,
|
|
7
7
|
NotEnoughBalanceToDelegate,
|
|
8
8
|
FeeTooHigh,
|
|
9
|
-
NotSupportedLegacyAddress,
|
|
10
9
|
InvalidAddressBecauseDestinationIsAlsoSource,
|
|
11
10
|
RecommendUndelegation,
|
|
12
11
|
} from "@ledgerhq/errors";
|
|
@@ -45,6 +44,7 @@ const createTransaction: () => Transaction = () => ({
|
|
|
45
44
|
networkInfo: null,
|
|
46
45
|
useAllAmount: false,
|
|
47
46
|
taquitoError: null,
|
|
47
|
+
estimatedFees: null,
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
const updateTransaction = (t, patch) => ({ ...t, ...patch });
|
|
@@ -65,7 +65,7 @@ const getTransactionStatus = async (
|
|
|
65
65
|
recipient?: Error;
|
|
66
66
|
} = {};
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
const estimatedFees = t.estimatedFees || new BigNumber(0);
|
|
69
69
|
|
|
70
70
|
const { tezosResources } = account;
|
|
71
71
|
if (!tezosResources) throw new Error("tezosResources is missing");
|
|
@@ -90,17 +90,6 @@ const getTransactionStatus = async (
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
if (t.recipient.startsWith("KT") && !errors.recipient) {
|
|
94
|
-
errors.recipient = new NotSupportedLegacyAddress();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// no fee / not enough balance already handled by taquitoError
|
|
98
|
-
if (!tezosResources.revealed) {
|
|
99
|
-
// FIXME
|
|
100
|
-
// https://github.com/ecadlabs/taquito/commit/48a11cfaffe4c6bdfa6f04ebbd0b756f4b135865#diff-3b138622526cbaa55605b79011aa411652367136a3e92e43faecc654da3854e7
|
|
101
|
-
estimatedFees = estimatedFees.plus(374 || DEFAULT_FEE.REVEAL);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
93
|
if (t.mode === "send") {
|
|
105
94
|
if (!errors.amount && t.amount.eq(0)) {
|
|
106
95
|
errors.amount = new AmountRequired();
|
|
@@ -120,7 +109,11 @@ const getTransactionStatus = async (
|
|
|
120
109
|
.lt(thresholdWarning)
|
|
121
110
|
) {
|
|
122
111
|
if (isAccountDelegating(account)) {
|
|
123
|
-
|
|
112
|
+
if (t.useAllAmount) {
|
|
113
|
+
errors.amount = new RecommendUndelegation();
|
|
114
|
+
} else {
|
|
115
|
+
warnings.amount = new RecommendUndelegation();
|
|
116
|
+
}
|
|
124
117
|
}
|
|
125
118
|
}
|
|
126
119
|
}
|
|
@@ -128,15 +121,22 @@ const getTransactionStatus = async (
|
|
|
128
121
|
log("taquitoerror", String(t.taquitoError));
|
|
129
122
|
|
|
130
123
|
// remap taquito errors
|
|
131
|
-
if (t.taquitoError
|
|
124
|
+
if (t.taquitoError.endsWith("balance_too_low")) {
|
|
132
125
|
if (t.mode === "send") {
|
|
133
126
|
errors.amount = new NotEnoughBalance();
|
|
134
127
|
} else {
|
|
135
128
|
errors.amount = new NotEnoughBalanceToDelegate();
|
|
136
129
|
}
|
|
130
|
+
} else {
|
|
131
|
+
// unidentified error case
|
|
132
|
+
errors.amount = new Error(t.taquitoError);
|
|
137
133
|
}
|
|
138
134
|
}
|
|
139
135
|
|
|
136
|
+
if (!errors.amount && account.balance.lte(0)) {
|
|
137
|
+
errors.amount = new NotEnoughBalance();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
140
|
const result = {
|
|
141
141
|
errors,
|
|
142
142
|
warnings,
|
|
@@ -154,8 +154,25 @@ const prepareTransaction = async (
|
|
|
154
154
|
const { tezosResources } = account;
|
|
155
155
|
if (!tezosResources) throw new Error("tezosResources is missing");
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
if (account.balance.lte(0)) {
|
|
158
|
+
return Promise.resolve(transaction);
|
|
159
|
+
}
|
|
158
160
|
|
|
161
|
+
// basic check to confirm the transaction is "complete"
|
|
162
|
+
if (transaction.mode !== "undelegate") {
|
|
163
|
+
if (!transaction.recipient) {
|
|
164
|
+
return Promise.resolve(transaction);
|
|
165
|
+
}
|
|
166
|
+
const { recipientError } = await validateRecipient(
|
|
167
|
+
account.currency,
|
|
168
|
+
transaction.recipient
|
|
169
|
+
);
|
|
170
|
+
if (recipientError) {
|
|
171
|
+
return Promise.resolve(transaction);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
|
|
159
176
|
tezos.setProvider({
|
|
160
177
|
signer: {
|
|
161
178
|
publicKeyHash: async () => account.freshAddress,
|
|
@@ -165,20 +182,21 @@ const prepareTransaction = async (
|
|
|
165
182
|
},
|
|
166
183
|
});
|
|
167
184
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
185
|
+
if (transaction.useAllAmount) {
|
|
186
|
+
// taquito does not accept 0, so we do 1
|
|
187
|
+
// only failing case is when the account precisely has fees + 1. which is
|
|
188
|
+
// unlikely
|
|
189
|
+
transaction.amount = new BigNumber(1);
|
|
190
|
+
}
|
|
175
191
|
|
|
192
|
+
try {
|
|
176
193
|
let out;
|
|
177
194
|
switch (transaction.mode) {
|
|
178
195
|
case "send":
|
|
179
196
|
out = await tezos.estimate.transfer({
|
|
197
|
+
mutez: true,
|
|
180
198
|
to: transaction.recipient,
|
|
181
|
-
amount: transaction.amount.
|
|
199
|
+
amount: transaction.amount.toNumber(),
|
|
182
200
|
});
|
|
183
201
|
break;
|
|
184
202
|
case "delegate":
|
|
@@ -193,14 +211,15 @@ const prepareTransaction = async (
|
|
|
193
211
|
});
|
|
194
212
|
break;
|
|
195
213
|
default:
|
|
196
|
-
throw "
|
|
214
|
+
throw new Error("unsupported mode=" + transaction.mode);
|
|
197
215
|
}
|
|
198
216
|
|
|
199
|
-
transaction.fees = new BigNumber(out.suggestedFeeMutez);
|
|
200
|
-
transaction.gasLimit = new BigNumber(out.gasLimit);
|
|
201
|
-
transaction.storageLimit = new BigNumber(out.storageLimit);
|
|
202
|
-
|
|
203
217
|
if (transaction.useAllAmount) {
|
|
218
|
+
const totalFees = out.suggestedFeeMutez + out.burnFeeMutez;
|
|
219
|
+
const maxAmount = account.balance
|
|
220
|
+
.minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
|
|
221
|
+
.toNumber();
|
|
222
|
+
// from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
|
|
204
223
|
// Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
|
|
205
224
|
// we need to increase the gasLimit and fee returned by the estimation
|
|
206
225
|
const gasBuffer = 500;
|
|
@@ -208,15 +227,37 @@ const prepareTransaction = async (
|
|
|
208
227
|
const increasedFee = (gasBuffer: number, opSize: number) => {
|
|
209
228
|
return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
|
|
210
229
|
};
|
|
211
|
-
|
|
212
|
-
|
|
230
|
+
const incr = increasedFee(gasBuffer, Number(out.opSize));
|
|
231
|
+
transaction.fees = new BigNumber(out.suggestedFeeMutez + incr);
|
|
232
|
+
transaction.gasLimit = new BigNumber(out.gasLimit + gasBuffer);
|
|
233
|
+
transaction.amount = new BigNumber(maxAmount - incr);
|
|
234
|
+
} else {
|
|
235
|
+
transaction.fees = new BigNumber(out.suggestedFeeMutez);
|
|
236
|
+
transaction.gasLimit = new BigNumber(out.gasLimit);
|
|
237
|
+
transaction.storageLimit = new BigNumber(out.storageLimit);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
transaction.storageLimit = new BigNumber(out.storageLimit);
|
|
241
|
+
transaction.estimatedFees = transaction.fees;
|
|
242
|
+
if (!tezosResources.revealed) {
|
|
243
|
+
transaction.estimatedFees = transaction.estimatedFees.plus(
|
|
244
|
+
DEFAULT_FEE.REVEAL
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
} catch (e) {
|
|
248
|
+
if (typeof e !== "object" || !e) throw e;
|
|
249
|
+
if ("id" in e) {
|
|
250
|
+
transaction.taquitoError = (e as { id: string }).id;
|
|
251
|
+
} else if ("status" in e) {
|
|
252
|
+
// in case of http 400, log & ignore (more case to handle)
|
|
253
|
+
log(
|
|
254
|
+
"taquito-network-error",
|
|
255
|
+
String((e as { message: string }).message || ""),
|
|
256
|
+
{ transaction }
|
|
213
257
|
);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
transaction.amount = account.balance.minus(s.estimatedFees);
|
|
258
|
+
} else {
|
|
259
|
+
throw e;
|
|
217
260
|
}
|
|
218
|
-
} catch (e: any) {
|
|
219
|
-
transaction.taquitoError = e.id;
|
|
220
261
|
}
|
|
221
262
|
|
|
222
263
|
return transaction;
|
|
@@ -38,40 +38,51 @@ export const signOperation = ({
|
|
|
38
38
|
);
|
|
39
39
|
tezos.setProvider({ signer: ledgerSigner });
|
|
40
40
|
|
|
41
|
+
// disable the broadcast because we want to do it in a second phase (broadcast hook)
|
|
41
42
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
42
43
|
// @ts-ignore
|
|
43
|
-
tezos.contract.context.injector.inject = async () => "";
|
|
44
|
+
tezos.contract.context.injector.inject = async () => "";
|
|
44
45
|
|
|
45
46
|
o.next({ type: "device-signature-requested" });
|
|
46
47
|
|
|
48
|
+
let type = "OUT";
|
|
49
|
+
|
|
47
50
|
let res, signature, opbytes;
|
|
51
|
+
const params = {
|
|
52
|
+
fee: transaction.fees?.toNumber() || 0,
|
|
53
|
+
storageLimit: transaction.storageLimit?.toNumber() || 0,
|
|
54
|
+
gasLimit: transaction.gasLimit?.toNumber() || 0,
|
|
55
|
+
};
|
|
48
56
|
switch (transaction.mode) {
|
|
49
57
|
case "send":
|
|
50
58
|
res = await tezos.contract.transfer({
|
|
59
|
+
mutez: true,
|
|
51
60
|
to: transaction.recipient,
|
|
52
|
-
amount: transaction.amount.
|
|
53
|
-
|
|
54
|
-
storageLimit: transaction.storageLimit?.toNumber() || 0,
|
|
55
|
-
gasLimit: transaction.gasLimit?.toNumber() || 0,
|
|
61
|
+
amount: transaction.amount.toNumber(),
|
|
62
|
+
...params,
|
|
56
63
|
});
|
|
57
64
|
signature = res.raw.opOb.signature;
|
|
58
65
|
opbytes = res.raw.opbytes;
|
|
59
66
|
break;
|
|
60
67
|
case "delegate":
|
|
61
68
|
res = await tezos.contract.setDelegate({
|
|
69
|
+
...params,
|
|
62
70
|
source: freshAddress,
|
|
63
71
|
delegate: transaction.recipient,
|
|
64
72
|
});
|
|
65
73
|
opbytes = res.raw.opbytes;
|
|
74
|
+
type = "DELEGATE";
|
|
66
75
|
break;
|
|
67
76
|
case "undelegate":
|
|
68
77
|
res = await tezos.contract.setDelegate({
|
|
78
|
+
...params,
|
|
69
79
|
source: freshAddress,
|
|
70
80
|
});
|
|
71
81
|
opbytes = res.raw.opbytes;
|
|
82
|
+
type = "UNDELEGATE";
|
|
72
83
|
break;
|
|
73
84
|
default:
|
|
74
|
-
throw "not supported";
|
|
85
|
+
throw new Error("not supported");
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
if (cancelled) {
|
|
@@ -88,9 +99,9 @@ export const signOperation = ({
|
|
|
88
99
|
|
|
89
100
|
// currently, all mode are always at least one OUT tx on ETH parent
|
|
90
101
|
const operation = {
|
|
91
|
-
id: `${accountId}-${txHash}
|
|
102
|
+
id: `${accountId}-${txHash}-${type}`,
|
|
92
103
|
hash: txHash,
|
|
93
|
-
type
|
|
104
|
+
type,
|
|
94
105
|
value: transaction.amount,
|
|
95
106
|
fee: fees,
|
|
96
107
|
extra: {
|
|
@@ -6,7 +6,7 @@ import { getCryptoCurrencyById, parseCurrencyUnit } from "../../currencies";
|
|
|
6
6
|
import { pickSiblings } from "../../bot/specs";
|
|
7
7
|
import type { AppSpec } from "../../bot/types";
|
|
8
8
|
import { DeviceModelId } from "@ledgerhq/devices";
|
|
9
|
-
import { getAccountDelegationSync } from "./bakers";
|
|
9
|
+
import { getAccountDelegationSync, isAccountDelegating } from "./bakers";
|
|
10
10
|
import whitelist from "./bakers.whitelist-default";
|
|
11
11
|
|
|
12
12
|
const maxAccount = 12;
|
|
@@ -31,10 +31,11 @@ const tezos: AppSpec<Transaction> = {
|
|
|
31
31
|
model: DeviceModelId.nanoS,
|
|
32
32
|
appName: "TezosWallet",
|
|
33
33
|
},
|
|
34
|
+
testTimeout: 2 * 60 * 1000,
|
|
34
35
|
transactionCheck: ({ maxSpendable }) => {
|
|
35
36
|
invariant(
|
|
36
37
|
maxSpendable.gt(
|
|
37
|
-
parseCurrencyUnit(getCryptoCurrencyById("tezos").units[0], "0.
|
|
38
|
+
parseCurrencyUnit(getCryptoCurrencyById("tezos").units[0], "0.02")
|
|
38
39
|
),
|
|
39
40
|
"balance is too low"
|
|
40
41
|
);
|
|
@@ -69,9 +70,13 @@ const tezos: AppSpec<Transaction> = {
|
|
|
69
70
|
},
|
|
70
71
|
},
|
|
71
72
|
{
|
|
72
|
-
name: "send max",
|
|
73
|
+
name: "send max (non delegating)",
|
|
73
74
|
maxRun: 3,
|
|
74
75
|
transaction: ({ account, siblings, bridge }) => {
|
|
76
|
+
invariant(
|
|
77
|
+
!isAccountDelegating(account),
|
|
78
|
+
"account must not be delegating"
|
|
79
|
+
);
|
|
75
80
|
const sibling = pickSiblings(siblings, maxAccount);
|
|
76
81
|
const recipient = sibling.freshAddress;
|
|
77
82
|
return {
|
|
@@ -85,7 +90,10 @@ const tezos: AppSpec<Transaction> = {
|
|
|
85
90
|
maxRun: 1,
|
|
86
91
|
transaction: ({ account, bridge }) => {
|
|
87
92
|
expectUnrevealed(account);
|
|
88
|
-
const
|
|
93
|
+
const d = getAccountDelegationSync(account);
|
|
94
|
+
const recipient = sample(
|
|
95
|
+
d ? whitelist.filter((w) => w !== d.address) : whitelist
|
|
96
|
+
);
|
|
89
97
|
return {
|
|
90
98
|
transaction: bridge.createTransaction(account),
|
|
91
99
|
updates: [{ recipient, mode: "delegate" }],
|
|
@@ -97,7 +105,10 @@ const tezos: AppSpec<Transaction> = {
|
|
|
97
105
|
maxRun: 1,
|
|
98
106
|
transaction: ({ account, bridge }) => {
|
|
99
107
|
expectRevealed(account);
|
|
100
|
-
const
|
|
108
|
+
const d = getAccountDelegationSync(account);
|
|
109
|
+
const recipient = sample(
|
|
110
|
+
d ? whitelist.filter((w) => w !== d.address) : whitelist
|
|
111
|
+
);
|
|
101
112
|
return {
|
|
102
113
|
transaction: bridge.createTransaction(account),
|
|
103
114
|
updates: [{ recipient, mode: "delegate" }],
|
|
@@ -15,13 +15,13 @@ const acceptTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
|
|
|
15
15
|
button: "Rr",
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
+
title: "Custom Delegate",
|
|
19
|
+
button: "Rr",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
// device sometimes know the text of a given delegator, we're not validating the actual text
|
|
18
23
|
title: "Delegate",
|
|
19
24
|
button: "Rr",
|
|
20
|
-
expectedValue: ({ transaction }) => {
|
|
21
|
-
return transaction.mode === "undelegate"
|
|
22
|
-
? "None"
|
|
23
|
-
: transaction.recipient;
|
|
24
|
-
},
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
title: "Delegate Name",
|
|
@@ -9,8 +9,6 @@ import { makeSync } from "../../bridge/jsHelpers";
|
|
|
9
9
|
import { getAccountShape } from "./synchronisation";
|
|
10
10
|
|
|
11
11
|
const accounts = [
|
|
12
|
-
// "tz1cf8diKsP1WoeucTQm1BcVfdyrmaBnL4nC", // FIXME
|
|
13
|
-
// "tz1ZshTmtorFVkcZ7CpceCAxCn7HBJqTfmpk", // FIXME
|
|
14
12
|
"tz1ZL36Xw6LJ9RK6tb7QW85o7SVYfFKSMw8c",
|
|
15
13
|
"tz1VacAyLcnHU3pEY3VNNK45F1CvVyTYXA3z",
|
|
16
14
|
"tz1hpWkvAVVgftPy4CW8rD3u6tdVd8g1RU58",
|
|
@@ -24,7 +22,6 @@ const accounts = [
|
|
|
24
22
|
"tz1PTxfn1fge2tJwGGpW9zNuYf6BseM3GJXt",
|
|
25
23
|
"tz1SBHto1BasGvxojr48r5PFiGb1Wq4cynGY",
|
|
26
24
|
"tz1fAfYNSkgci3ko2xikDtYtcSf1X1YdAKoK",
|
|
27
|
-
"tz1hobi4RsAeswm9JA7mHB96vqc1eAWRzxDc",
|
|
28
25
|
];
|
|
29
26
|
|
|
30
27
|
jest.setTimeout(30 * 1000);
|
|
@@ -75,6 +75,11 @@ export const getAccountShape: GetAccountShape = async (infoInput) => {
|
|
|
75
75
|
id: accountId,
|
|
76
76
|
blockHeight,
|
|
77
77
|
lastSyncDate: new Date(),
|
|
78
|
+
tezosResources: {
|
|
79
|
+
revealed: false,
|
|
80
|
+
counter: 0,
|
|
81
|
+
publicKey: "",
|
|
82
|
+
},
|
|
78
83
|
};
|
|
79
84
|
}
|
|
80
85
|
invariant(
|
|
@@ -232,9 +237,7 @@ const txToOp =
|
|
|
232
237
|
blockHash,
|
|
233
238
|
accountId,
|
|
234
239
|
date: new Date(timestamp),
|
|
235
|
-
extra: {
|
|
236
|
-
id,
|
|
237
|
-
},
|
|
240
|
+
extra: { id },
|
|
238
241
|
hasFailed,
|
|
239
242
|
};
|
|
240
243
|
};
|