@ledgerhq/coin-near 0.3.8
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 +14 -0
- package/LICENSE.txt +21 -0
- package/jest.config.js +6 -0
- package/lib/account.d.ts +7 -0
- package/lib/account.d.ts.map +1 -0
- package/lib/account.js +31 -0
- package/lib/account.js.map +1 -0
- package/lib/api/archive-node-sdk.d.ts +21 -0
- package/lib/api/archive-node-sdk.d.ts.map +1 -0
- package/lib/api/archive-node-sdk.js +276 -0
- package/lib/api/archive-node-sdk.js.map +1 -0
- package/lib/api/datahub-indexer-sdk.d.ts +3 -0
- package/lib/api/datahub-indexer-sdk.d.ts.map +1 -0
- package/lib/api/datahub-indexer-sdk.js +80 -0
- package/lib/api/datahub-indexer-sdk.js.map +1 -0
- package/lib/api/index.d.ts +4 -0
- package/lib/api/index.d.ts.map +1 -0
- package/lib/api/index.js +18 -0
- package/lib/api/index.js.map +1 -0
- package/lib/api/near-staking-positions-sdk.d.ts +3 -0
- package/lib/api/near-staking-positions-sdk.d.ts.map +1 -0
- package/lib/api/near-staking-positions-sdk.js +27 -0
- package/lib/api/near-staking-positions-sdk.js.map +1 -0
- package/lib/api/sdk.types.d.ts +81 -0
- package/lib/api/sdk.types.d.ts.map +1 -0
- package/lib/api/sdk.types.js +3 -0
- package/lib/api/sdk.types.js.map +1 -0
- package/lib/bridge/js.d.ts +11 -0
- package/lib/bridge/js.d.ts.map +1 -0
- package/lib/bridge/js.js +58 -0
- package/lib/bridge/js.js.map +1 -0
- package/lib/bridge.integration.test.d.ts +14 -0
- package/lib/bridge.integration.test.d.ts.map +1 -0
- package/lib/bridge.integration.test.js +226 -0
- package/lib/bridge.integration.test.js.map +1 -0
- package/lib/cli-transaction.d.ts +16 -0
- package/lib/cli-transaction.d.ts.map +1 -0
- package/lib/cli-transaction.js +28 -0
- package/lib/cli-transaction.js.map +1 -0
- package/lib/constants.d.ts +8 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/constants.js +11 -0
- package/lib/constants.js.map +1 -0
- package/lib/deviceTransactionConfig.d.ts +7 -0
- package/lib/deviceTransactionConfig.d.ts.map +1 -0
- package/lib/deviceTransactionConfig.js +54 -0
- package/lib/deviceTransactionConfig.js.map +1 -0
- package/lib/errors.d.ts +28 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +41 -0
- package/lib/errors.js.map +1 -0
- package/lib/hw-getAddress.d.ts +6 -0
- package/lib/hw-getAddress.d.ts.map +1 -0
- package/lib/hw-getAddress.js +23 -0
- package/lib/hw-getAddress.js.map +1 -0
- package/lib/js-broadcast.d.ts +6 -0
- package/lib/js-broadcast.d.ts.map +1 -0
- package/lib/js-broadcast.js +19 -0
- package/lib/js-broadcast.js.map +1 -0
- package/lib/js-buildTransaction.d.ts +5 -0
- package/lib/js-buildTransaction.d.ts.map +1 -0
- package/lib/js-buildTransaction.js +79 -0
- package/lib/js-buildTransaction.js.map +1 -0
- package/lib/js-estimateMaxSpendable.d.ts +11 -0
- package/lib/js-estimateMaxSpendable.d.ts.map +1 -0
- package/lib/js-estimateMaxSpendable.js +31 -0
- package/lib/js-estimateMaxSpendable.js.map +1 -0
- package/lib/js-getFeesForTransaction.d.ts +5 -0
- package/lib/js-getFeesForTransaction.d.ts.map +1 -0
- package/lib/js-getFeesForTransaction.js +33 -0
- package/lib/js-getFeesForTransaction.js.map +1 -0
- package/lib/js-getTransactionStatus.d.ts +4 -0
- package/lib/js-getTransactionStatus.d.ts.map +1 -0
- package/lib/js-getTransactionStatus.js +142 -0
- package/lib/js-getTransactionStatus.js.map +1 -0
- package/lib/js-signOperation.d.ts +10 -0
- package/lib/js-signOperation.d.ts.map +1 -0
- package/lib/js-signOperation.js +112 -0
- package/lib/js-signOperation.js.map +1 -0
- package/lib/js-synchronisation.d.ts +5 -0
- package/lib/js-synchronisation.d.ts.map +1 -0
- package/lib/js-synchronisation.js +50 -0
- package/lib/js-synchronisation.js.map +1 -0
- package/lib/js-transaction.d.ts +5 -0
- package/lib/js-transaction.d.ts.map +1 -0
- package/lib/js-transaction.js +41 -0
- package/lib/js-transaction.js.map +1 -0
- package/lib/logic.d.ts +15 -0
- package/lib/logic.d.ts.map +1 -0
- package/lib/logic.js +141 -0
- package/lib/logic.js.map +1 -0
- package/lib/preload.d.ts +11 -0
- package/lib/preload.d.ts.map +1 -0
- package/lib/preload.js +133 -0
- package/lib/preload.js.map +1 -0
- package/lib/serialization.d.ts +7 -0
- package/lib/serialization.d.ts.map +1 -0
- package/lib/serialization.js +52 -0
- package/lib/serialization.js.map +1 -0
- package/lib/signer.d.ts +11 -0
- package/lib/signer.d.ts.map +1 -0
- package/lib/signer.js +3 -0
- package/lib/signer.js.map +1 -0
- package/lib/specs.d.ts +7 -0
- package/lib/specs.d.ts.map +1 -0
- package/lib/specs.js +133 -0
- package/lib/specs.js.map +1 -0
- package/lib/speculos-deviceActions.d.ts +4 -0
- package/lib/speculos-deviceActions.d.ts.map +1 -0
- package/lib/speculos-deviceActions.js +94 -0
- package/lib/speculos-deviceActions.js.map +1 -0
- package/lib/transaction.d.ts +15 -0
- package/lib/transaction.d.ts.map +1 -0
- package/lib/transaction.js +38 -0
- package/lib/transaction.js.map +1 -0
- package/lib/types.d.ts +74 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/lib-es/account.d.ts +7 -0
- package/lib-es/account.d.ts.map +1 -0
- package/lib-es/account.js +29 -0
- package/lib-es/account.js.map +1 -0
- package/lib-es/api/archive-node-sdk.d.ts +21 -0
- package/lib-es/api/archive-node-sdk.d.ts.map +1 -0
- package/lib-es/api/archive-node-sdk.js +240 -0
- package/lib-es/api/archive-node-sdk.js.map +1 -0
- package/lib-es/api/datahub-indexer-sdk.d.ts +3 -0
- package/lib-es/api/datahub-indexer-sdk.d.ts.map +1 -0
- package/lib-es/api/datahub-indexer-sdk.js +73 -0
- package/lib-es/api/datahub-indexer-sdk.js.map +1 -0
- package/lib-es/api/index.d.ts +4 -0
- package/lib-es/api/index.d.ts.map +1 -0
- package/lib-es/api/index.js +4 -0
- package/lib-es/api/index.js.map +1 -0
- package/lib-es/api/near-staking-positions-sdk.d.ts +3 -0
- package/lib-es/api/near-staking-positions-sdk.d.ts.map +1 -0
- package/lib-es/api/near-staking-positions-sdk.js +20 -0
- package/lib-es/api/near-staking-positions-sdk.js.map +1 -0
- package/lib-es/api/sdk.types.d.ts +81 -0
- package/lib-es/api/sdk.types.d.ts.map +1 -0
- package/lib-es/api/sdk.types.js +2 -0
- package/lib-es/api/sdk.types.js.map +1 -0
- package/lib-es/bridge/js.d.ts +11 -0
- package/lib-es/bridge/js.d.ts.map +1 -0
- package/lib-es/bridge/js.js +49 -0
- package/lib-es/bridge/js.js.map +1 -0
- package/lib-es/bridge.integration.test.d.ts +14 -0
- package/lib-es/bridge.integration.test.d.ts.map +1 -0
- package/lib-es/bridge.integration.test.js +223 -0
- package/lib-es/bridge.integration.test.js.map +1 -0
- package/lib-es/cli-transaction.d.ts +16 -0
- package/lib-es/cli-transaction.d.ts.map +1 -0
- package/lib-es/cli-transaction.js +22 -0
- package/lib-es/cli-transaction.js.map +1 -0
- package/lib-es/constants.d.ts +8 -0
- package/lib-es/constants.d.ts.map +1 -0
- package/lib-es/constants.js +8 -0
- package/lib-es/constants.js.map +1 -0
- package/lib-es/deviceTransactionConfig.d.ts +7 -0
- package/lib-es/deviceTransactionConfig.d.ts.map +1 -0
- package/lib-es/deviceTransactionConfig.js +52 -0
- package/lib-es/deviceTransactionConfig.js.map +1 -0
- package/lib-es/errors.d.ts +28 -0
- package/lib-es/errors.d.ts.map +1 -0
- package/lib-es/errors.js +38 -0
- package/lib-es/errors.js.map +1 -0
- package/lib-es/hw-getAddress.d.ts +6 -0
- package/lib-es/hw-getAddress.d.ts.map +1 -0
- package/lib-es/hw-getAddress.js +21 -0
- package/lib-es/hw-getAddress.js.map +1 -0
- package/lib-es/js-broadcast.d.ts +6 -0
- package/lib-es/js-broadcast.d.ts.map +1 -0
- package/lib-es/js-broadcast.js +17 -0
- package/lib-es/js-broadcast.js.map +1 -0
- package/lib-es/js-buildTransaction.d.ts +5 -0
- package/lib-es/js-buildTransaction.d.ts.map +1 -0
- package/lib-es/js-buildTransaction.js +52 -0
- package/lib-es/js-buildTransaction.js.map +1 -0
- package/lib-es/js-estimateMaxSpendable.d.ts +11 -0
- package/lib-es/js-estimateMaxSpendable.d.ts.map +1 -0
- package/lib-es/js-estimateMaxSpendable.js +26 -0
- package/lib-es/js-estimateMaxSpendable.js.map +1 -0
- package/lib-es/js-getFeesForTransaction.d.ts +5 -0
- package/lib-es/js-getFeesForTransaction.d.ts.map +1 -0
- package/lib-es/js-getFeesForTransaction.js +31 -0
- package/lib-es/js-getFeesForTransaction.js.map +1 -0
- package/lib-es/js-getTransactionStatus.d.ts +4 -0
- package/lib-es/js-getTransactionStatus.d.ts.map +1 -0
- package/lib-es/js-getTransactionStatus.js +140 -0
- package/lib-es/js-getTransactionStatus.js.map +1 -0
- package/lib-es/js-signOperation.d.ts +10 -0
- package/lib-es/js-signOperation.d.ts.map +1 -0
- package/lib-es/js-signOperation.js +85 -0
- package/lib-es/js-signOperation.js.map +1 -0
- package/lib-es/js-synchronisation.d.ts +5 -0
- package/lib-es/js-synchronisation.d.ts.map +1 -0
- package/lib-es/js-synchronisation.js +46 -0
- package/lib-es/js-synchronisation.js.map +1 -0
- package/lib-es/js-transaction.d.ts +5 -0
- package/lib-es/js-transaction.d.ts.map +1 -0
- package/lib-es/js-transaction.js +33 -0
- package/lib-es/js-transaction.js.map +1 -0
- package/lib-es/logic.d.ts +15 -0
- package/lib-es/logic.d.ts.map +1 -0
- package/lib-es/logic.js +127 -0
- package/lib-es/logic.js.map +1 -0
- package/lib-es/preload.d.ts +11 -0
- package/lib-es/preload.d.ts.map +1 -0
- package/lib-es/preload.js +124 -0
- package/lib-es/preload.js.map +1 -0
- package/lib-es/serialization.d.ts +7 -0
- package/lib-es/serialization.d.ts.map +1 -0
- package/lib-es/serialization.js +45 -0
- package/lib-es/serialization.js.map +1 -0
- package/lib-es/signer.d.ts +11 -0
- package/lib-es/signer.d.ts.map +1 -0
- package/lib-es/signer.js +2 -0
- package/lib-es/signer.js.map +1 -0
- package/lib-es/specs.d.ts +7 -0
- package/lib-es/specs.d.ts.map +1 -0
- package/lib-es/specs.js +128 -0
- package/lib-es/specs.js.map +1 -0
- package/lib-es/speculos-deviceActions.d.ts +4 -0
- package/lib-es/speculos-deviceActions.d.ts.map +1 -0
- package/lib-es/speculos-deviceActions.js +68 -0
- package/lib-es/speculos-deviceActions.js.map +1 -0
- package/lib-es/transaction.d.ts +15 -0
- package/lib-es/transaction.d.ts.map +1 -0
- package/lib-es/transaction.js +32 -0
- package/lib-es/transaction.js.map +1 -0
- package/lib-es/types.d.ts +74 -0
- package/lib-es/types.d.ts.map +1 -0
- package/lib-es/types.js +2 -0
- package/lib-es/types.js.map +1 -0
- package/package.json +80 -0
- package/src/account.ts +38 -0
- package/src/api/archive-node-sdk.ts +302 -0
- package/src/api/datahub-indexer-sdk.ts +84 -0
- package/src/api/index.ts +13 -0
- package/src/api/near-staking-positions-sdk.ts +15 -0
- package/src/api/sdk.types.ts +88 -0
- package/src/bridge/js.ts +69 -0
- package/src/bridge.integration.test.ts +241 -0
- package/src/cli-transaction.ts +38 -0
- package/src/constants.ts +7 -0
- package/src/deviceTransactionConfig.ts +81 -0
- package/src/errors.ts +46 -0
- package/src/hw-getAddress.ts +21 -0
- package/src/js-broadcast.ts +15 -0
- package/src/js-buildTransaction.ts +89 -0
- package/src/js-estimateMaxSpendable.ts +38 -0
- package/src/js-getFeesForTransaction.ts +39 -0
- package/src/js-getTransactionStatus.ts +186 -0
- package/src/js-signOperation.ts +125 -0
- package/src/js-synchronisation.ts +52 -0
- package/src/js-transaction.ts +29 -0
- package/src/logic.ts +176 -0
- package/src/preload.ts +143 -0
- package/src/serialization.ts +61 -0
- package/src/signer.ts +9 -0
- package/src/specs.ts +177 -0
- package/src/speculos-deviceActions.ts +75 -0
- package/src/transaction.ts +57 -0
- package/src/types.ts +91 -0
- package/tsconfig.json +12 -0
package/src/preload.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { BigNumber } from "bignumber.js";
|
|
2
|
+
import { Observable, Subject } from "rxjs";
|
|
3
|
+
import { log } from "@ledgerhq/logs";
|
|
4
|
+
import type { NearPreloadedData } from "./types";
|
|
5
|
+
import { getProtocolConfig, getValidators, getCommission, getGasPrice } from "./api";
|
|
6
|
+
import { FALLBACK_STORAGE_AMOUNT_PER_BYTE } from "./constants";
|
|
7
|
+
import { NearProtocolConfigNotLoaded } from "./errors";
|
|
8
|
+
|
|
9
|
+
const PRELOAD_MAX_AGE = 30 * 60 * 1000;
|
|
10
|
+
|
|
11
|
+
let currentPreloadedData: NearPreloadedData = {
|
|
12
|
+
storageCost: new BigNumber(FALLBACK_STORAGE_AMOUNT_PER_BYTE),
|
|
13
|
+
gasPrice: new BigNumber(0),
|
|
14
|
+
createAccountCostSend: new BigNumber(0),
|
|
15
|
+
createAccountCostExecution: new BigNumber(0),
|
|
16
|
+
transferCostSend: new BigNumber(0),
|
|
17
|
+
transferCostExecution: new BigNumber(0),
|
|
18
|
+
addKeyCostSend: new BigNumber(0),
|
|
19
|
+
addKeyCostExecution: new BigNumber(0),
|
|
20
|
+
receiptCreationSend: new BigNumber(0),
|
|
21
|
+
receiptCreationExecution: new BigNumber(0),
|
|
22
|
+
validators: [],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function fromHydratePreloadData(data: any): NearPreloadedData {
|
|
26
|
+
const hydratedData = Object.assign({}, currentPreloadedData);
|
|
27
|
+
|
|
28
|
+
if (typeof data === "object" && data) {
|
|
29
|
+
if (data.storageCost) {
|
|
30
|
+
hydratedData.storageCost = new BigNumber(data.storageCost);
|
|
31
|
+
}
|
|
32
|
+
if (data.gasPrice) {
|
|
33
|
+
hydratedData.gasPrice = new BigNumber(data.gasPrice);
|
|
34
|
+
}
|
|
35
|
+
if (data.createAccountCostSend) {
|
|
36
|
+
hydratedData.createAccountCostSend = new BigNumber(data.createAccountCostSend);
|
|
37
|
+
}
|
|
38
|
+
if (data.createAccountCostExecution) {
|
|
39
|
+
hydratedData.createAccountCostExecution = new BigNumber(data.createAccountCostExecution);
|
|
40
|
+
}
|
|
41
|
+
if (data.transferCostSend) {
|
|
42
|
+
hydratedData.transferCostSend = new BigNumber(data.transferCostSend);
|
|
43
|
+
}
|
|
44
|
+
if (data.transferCostExecution) {
|
|
45
|
+
hydratedData.transferCostExecution = new BigNumber(data.transferCostExecution);
|
|
46
|
+
}
|
|
47
|
+
if (data.addKeyCostSend) {
|
|
48
|
+
hydratedData.addKeyCostSend = new BigNumber(data.addKeyCostSend);
|
|
49
|
+
}
|
|
50
|
+
if (data.addKeyCostExecution) {
|
|
51
|
+
hydratedData.addKeyCostExecution = new BigNumber(data.addKeyCostExecution);
|
|
52
|
+
}
|
|
53
|
+
if (data.receiptCreationSend) {
|
|
54
|
+
hydratedData.receiptCreationSend = new BigNumber(data.receiptCreationSend);
|
|
55
|
+
}
|
|
56
|
+
if (data.receiptCreationExecution) {
|
|
57
|
+
hydratedData.receiptCreationExecution = new BigNumber(data.receiptCreationExecution);
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(data.validators) && data.validators.length) {
|
|
60
|
+
hydratedData.validators = data.validators;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return hydratedData;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const updates = new Subject<NearPreloadedData>();
|
|
68
|
+
|
|
69
|
+
export function getCurrentNearPreloadData(): NearPreloadedData {
|
|
70
|
+
return currentPreloadedData;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function setNearPreloadData(data: NearPreloadedData): void {
|
|
74
|
+
if (data === currentPreloadedData) return;
|
|
75
|
+
|
|
76
|
+
currentPreloadedData = data;
|
|
77
|
+
|
|
78
|
+
updates.next(data);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function getNearPreloadDataUpdates(): Observable<NearPreloadedData> {
|
|
82
|
+
return updates.asObservable();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const getPreloadStrategy = () => ({
|
|
86
|
+
preloadMaxAge: PRELOAD_MAX_AGE,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export const preload = async (): Promise<NearPreloadedData> => {
|
|
90
|
+
log("near/preload", "preloading near data...");
|
|
91
|
+
|
|
92
|
+
const [protocolConfig, rawValidators, gasPrice] = await Promise.all([
|
|
93
|
+
getProtocolConfig(),
|
|
94
|
+
getValidators(),
|
|
95
|
+
getGasPrice(),
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
const validators = await Promise.all(
|
|
99
|
+
rawValidators.map(async ({ account_id, stake }) => {
|
|
100
|
+
const commission = await getCommission(account_id);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
validatorAddress: account_id,
|
|
104
|
+
tokens: stake,
|
|
105
|
+
commission,
|
|
106
|
+
};
|
|
107
|
+
}),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (!protocolConfig) {
|
|
111
|
+
throw new NearProtocolConfigNotLoaded();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const { storage_amount_per_byte, transaction_costs } = protocolConfig.runtime_config;
|
|
115
|
+
|
|
116
|
+
const { action_creation_config, action_receipt_creation_config } = transaction_costs;
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
storageCost: new BigNumber(storage_amount_per_byte),
|
|
120
|
+
gasPrice: new BigNumber(gasPrice),
|
|
121
|
+
createAccountCostSend: new BigNumber(action_creation_config.create_account_cost.send_not_sir),
|
|
122
|
+
createAccountCostExecution: new BigNumber(action_creation_config.create_account_cost.execution),
|
|
123
|
+
transferCostSend: new BigNumber(action_creation_config.transfer_cost.send_not_sir),
|
|
124
|
+
transferCostExecution: new BigNumber(action_creation_config.transfer_cost.execution),
|
|
125
|
+
addKeyCostSend: new BigNumber(
|
|
126
|
+
action_creation_config.add_key_cost.full_access_cost.send_not_sir,
|
|
127
|
+
),
|
|
128
|
+
addKeyCostExecution: new BigNumber(
|
|
129
|
+
action_creation_config.add_key_cost.full_access_cost.execution,
|
|
130
|
+
),
|
|
131
|
+
receiptCreationSend: new BigNumber(action_receipt_creation_config.send_not_sir),
|
|
132
|
+
receiptCreationExecution: new BigNumber(action_receipt_creation_config.execution),
|
|
133
|
+
validators,
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const hydrate = (data: any): void => {
|
|
138
|
+
const hydrated = fromHydratePreloadData(data);
|
|
139
|
+
|
|
140
|
+
log("near/preload", `hydrated storageCost with ${hydrated.storageCost}`);
|
|
141
|
+
|
|
142
|
+
setNearPreloadData(hydrated);
|
|
143
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BigNumber } from "bignumber.js";
|
|
2
|
+
import type { NearAccount, NearAccountRaw, NearResources, NearResourcesRaw } from "./types";
|
|
3
|
+
import { Account, AccountRaw } from "@ledgerhq/types-live";
|
|
4
|
+
|
|
5
|
+
export function toNearResourcesRaw(r: NearResources): NearResourcesRaw {
|
|
6
|
+
const { stakedBalance, pendingBalance, availableBalance, storageUsageBalance, stakingPositions } =
|
|
7
|
+
r;
|
|
8
|
+
return {
|
|
9
|
+
stakedBalance: stakedBalance.toString(),
|
|
10
|
+
pendingBalance: pendingBalance.toString(),
|
|
11
|
+
availableBalance: availableBalance.toString(),
|
|
12
|
+
storageUsageBalance: storageUsageBalance.toString(),
|
|
13
|
+
stakingPositions: stakingPositions.map(
|
|
14
|
+
({ staked, validatorId, available, pending, rewards }) => ({
|
|
15
|
+
staked: staked.toString(),
|
|
16
|
+
available: available.toString(),
|
|
17
|
+
pending: pending.toString(),
|
|
18
|
+
rewards: rewards.toString(),
|
|
19
|
+
validatorId,
|
|
20
|
+
}),
|
|
21
|
+
),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function fromNearResourcesRaw(r: NearResourcesRaw): NearResources {
|
|
26
|
+
const {
|
|
27
|
+
stakedBalance,
|
|
28
|
+
pendingBalance,
|
|
29
|
+
availableBalance,
|
|
30
|
+
storageUsageBalance,
|
|
31
|
+
stakingPositions = [],
|
|
32
|
+
} = r;
|
|
33
|
+
return {
|
|
34
|
+
stakedBalance: new BigNumber(stakedBalance),
|
|
35
|
+
pendingBalance: new BigNumber(pendingBalance),
|
|
36
|
+
availableBalance: new BigNumber(availableBalance),
|
|
37
|
+
storageUsageBalance: new BigNumber(storageUsageBalance),
|
|
38
|
+
stakingPositions: stakingPositions.map(
|
|
39
|
+
({ staked, validatorId, available, pending, rewards }) => ({
|
|
40
|
+
staked: new BigNumber(staked),
|
|
41
|
+
available: new BigNumber(available),
|
|
42
|
+
pending: new BigNumber(pending),
|
|
43
|
+
rewards: new BigNumber(rewards),
|
|
44
|
+
validatorId,
|
|
45
|
+
}),
|
|
46
|
+
),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function assignToAccountRaw(account: Account, accountRaw: AccountRaw) {
|
|
51
|
+
const nearAccount = account as NearAccount;
|
|
52
|
+
if (nearAccount.nearResources) {
|
|
53
|
+
(accountRaw as NearAccountRaw).nearResources = toNearResourcesRaw(nearAccount.nearResources);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function assignFromAccountRaw(accountRaw: AccountRaw, account: Account) {
|
|
58
|
+
const nearResourcesRaw = (accountRaw as NearAccountRaw).nearResources;
|
|
59
|
+
if (nearResourcesRaw)
|
|
60
|
+
(account as NearAccount).nearResources = fromNearResourcesRaw(nearResourcesRaw);
|
|
61
|
+
}
|
package/src/signer.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type NearAddress = {
|
|
2
|
+
publicKey: string;
|
|
3
|
+
address: string;
|
|
4
|
+
};
|
|
5
|
+
export type NearSignature = Buffer | undefined;
|
|
6
|
+
export interface NearSigner {
|
|
7
|
+
getAddress(path: string, verify?: boolean): Promise<NearAddress>;
|
|
8
|
+
signTransaction(transaction: Uint8Array, path: string): Promise<NearSignature>;
|
|
9
|
+
}
|
package/src/specs.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
2
|
+
import expect from "expect";
|
|
3
|
+
import { BigNumber } from "bignumber.js";
|
|
4
|
+
import type { Transaction, NearAccount } from "./types";
|
|
5
|
+
import {
|
|
6
|
+
getCryptoCurrencyById,
|
|
7
|
+
parseCurrencyUnit,
|
|
8
|
+
} from "@ledgerhq/coin-framework/currencies/index";
|
|
9
|
+
import { botTest, pickSiblings } from "@ledgerhq/coin-framework/bot/specs";
|
|
10
|
+
import type { AppSpec } from "@ledgerhq/coin-framework/bot/types";
|
|
11
|
+
import { DeviceModelId } from "@ledgerhq/devices";
|
|
12
|
+
import { acceptTransaction } from "./speculos-deviceActions";
|
|
13
|
+
|
|
14
|
+
const currency = getCryptoCurrencyById("near");
|
|
15
|
+
const minimalAmount = parseCurrencyUnit(currency.units[0], "0.00001");
|
|
16
|
+
const stakingFee = parseCurrencyUnit(currency.units[0], "0.002");
|
|
17
|
+
const maxAccount = 8;
|
|
18
|
+
const validator = "ledgerbyfigment.poolv1.near";
|
|
19
|
+
|
|
20
|
+
const near: AppSpec<Transaction> = {
|
|
21
|
+
name: "NEAR",
|
|
22
|
+
currency,
|
|
23
|
+
appQuery: {
|
|
24
|
+
model: DeviceModelId.nanoS,
|
|
25
|
+
appName: "NEAR",
|
|
26
|
+
},
|
|
27
|
+
genericDeviceAction: acceptTransaction,
|
|
28
|
+
testTimeout: 2 * 60 * 1000,
|
|
29
|
+
mutations: [
|
|
30
|
+
{
|
|
31
|
+
name: "Move 50% to another account",
|
|
32
|
+
maxRun: 1,
|
|
33
|
+
transaction: ({ account, siblings, bridge, maxSpendable }) => {
|
|
34
|
+
invariant(maxSpendable.gt(minimalAmount), "balance is too low");
|
|
35
|
+
const sibling = pickSiblings(siblings, maxAccount);
|
|
36
|
+
const recipient = sibling.freshAddress;
|
|
37
|
+
const amount = maxSpendable.div(2).integerValue();
|
|
38
|
+
return {
|
|
39
|
+
transaction: bridge.createTransaction(account),
|
|
40
|
+
updates: [{ recipient }, { amount }],
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
test: ({ accountBeforeTransaction, operation, account }) => {
|
|
44
|
+
botTest("account spendable balance decreased with operation", () =>
|
|
45
|
+
expect(account.spendableBalance).toEqual(
|
|
46
|
+
accountBeforeTransaction.spendableBalance.minus(operation.value),
|
|
47
|
+
),
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "Send max to another account",
|
|
53
|
+
maxRun: 1,
|
|
54
|
+
transaction: ({ account, siblings, bridge, maxSpendable }) => {
|
|
55
|
+
invariant(maxSpendable.gt(minimalAmount), "balance is too low");
|
|
56
|
+
const sibling = pickSiblings(siblings, maxAccount);
|
|
57
|
+
const recipient = sibling.freshAddress;
|
|
58
|
+
return {
|
|
59
|
+
transaction: bridge.createTransaction(account),
|
|
60
|
+
updates: [{ recipient }, { useAllAmount: true }],
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
test: ({ account }) => {
|
|
64
|
+
botTest("account spendable balance is zero", () =>
|
|
65
|
+
expect(account.spendableBalance.toString()).toBe("0"),
|
|
66
|
+
);
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "Stake",
|
|
71
|
+
maxRun: 1,
|
|
72
|
+
transaction: ({ account, bridge, maxSpendable }) => {
|
|
73
|
+
invariant(maxSpendable.gt(minimalAmount.plus(stakingFee)), "balance is too low");
|
|
74
|
+
|
|
75
|
+
const amount = minimalAmount.times(10).times(Math.random()).integerValue();
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
transaction: bridge.createTransaction(account),
|
|
79
|
+
updates: [{ mode: "stake", recipient: validator }, { amount }],
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
test: ({ accountBeforeTransaction, operation, account }) => {
|
|
83
|
+
const { nearResources } = account as NearAccount;
|
|
84
|
+
const { nearResources: beforeTransactionNearResources } =
|
|
85
|
+
accountBeforeTransaction as NearAccount;
|
|
86
|
+
|
|
87
|
+
// Sometimes, 1 yoctoNEAR gets deducted from the staked amount, so we assert against a range.
|
|
88
|
+
botTest("account staked balance increased with operation", () => {
|
|
89
|
+
expect(
|
|
90
|
+
nearResources.stakedBalance.gte(
|
|
91
|
+
beforeTransactionNearResources.stakedBalance.plus(operation.value.minus("1")),
|
|
92
|
+
),
|
|
93
|
+
).toBe(true);
|
|
94
|
+
expect(
|
|
95
|
+
nearResources.stakedBalance.lte(
|
|
96
|
+
beforeTransactionNearResources.stakedBalance.plus(operation.value),
|
|
97
|
+
),
|
|
98
|
+
).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "Unstake",
|
|
104
|
+
maxRun: 1,
|
|
105
|
+
transaction: ({ account, bridge, maxSpendable }) => {
|
|
106
|
+
invariant(maxSpendable.gt(stakingFee), "balance is too low for fees");
|
|
107
|
+
|
|
108
|
+
const { nearResources } = account as NearAccount;
|
|
109
|
+
|
|
110
|
+
const staked = nearResources?.stakedBalance || new BigNumber(0);
|
|
111
|
+
|
|
112
|
+
invariant(staked.gt(minimalAmount), "staked balance is too low for unstaking");
|
|
113
|
+
|
|
114
|
+
const halfStaked = staked.div(2);
|
|
115
|
+
|
|
116
|
+
const amount = halfStaked.gt(minimalAmount)
|
|
117
|
+
? halfStaked.integerValue()
|
|
118
|
+
: staked.integerValue();
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
transaction: bridge.createTransaction(account),
|
|
122
|
+
updates: [{ mode: "unstake", recipient: validator }, { amount }],
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
test: ({ accountBeforeTransaction, account }) => {
|
|
126
|
+
const { nearResources } = account as NearAccount;
|
|
127
|
+
const { nearResources: beforeTransactionNearResources } =
|
|
128
|
+
accountBeforeTransaction as NearAccount;
|
|
129
|
+
|
|
130
|
+
botTest("account pending balance increased", () =>
|
|
131
|
+
expect(
|
|
132
|
+
nearResources.pendingBalance.gt(beforeTransactionNearResources.pendingBalance),
|
|
133
|
+
).toBe(true),
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "Withdraw",
|
|
139
|
+
maxRun: 1,
|
|
140
|
+
transaction: ({ account, bridge, maxSpendable }) => {
|
|
141
|
+
invariant(maxSpendable.gt(stakingFee), "balance is too low for fees");
|
|
142
|
+
|
|
143
|
+
const { nearResources } = account as NearAccount;
|
|
144
|
+
|
|
145
|
+
const available = nearResources?.availableBalance || new BigNumber(0);
|
|
146
|
+
|
|
147
|
+
invariant(available.gt(minimalAmount), "available balance is too low for withdrawing");
|
|
148
|
+
|
|
149
|
+
const halfAvailable = available.div(2);
|
|
150
|
+
|
|
151
|
+
const amount = halfAvailable.gt(minimalAmount)
|
|
152
|
+
? halfAvailable.integerValue()
|
|
153
|
+
: available.integerValue();
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
transaction: bridge.createTransaction(account),
|
|
157
|
+
updates: [{ mode: "withdraw", recipient: validator }, { amount }],
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
test: ({ accountBeforeTransaction, account }) => {
|
|
161
|
+
const { nearResources } = account as NearAccount;
|
|
162
|
+
const { nearResources: beforeTransactionNearResources } =
|
|
163
|
+
accountBeforeTransaction as NearAccount;
|
|
164
|
+
|
|
165
|
+
botTest("account withdrawable balance decreased", () =>
|
|
166
|
+
expect(
|
|
167
|
+
nearResources.availableBalance.lt(beforeTransactionNearResources.availableBalance),
|
|
168
|
+
).toBe(true),
|
|
169
|
+
);
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export default {
|
|
176
|
+
near,
|
|
177
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as nearAPI from "near-api-js";
|
|
2
|
+
import { getAccountUnit } from "@ledgerhq/coin-framework/account/index";
|
|
3
|
+
import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/index";
|
|
4
|
+
import type { DeviceAction } from "@ledgerhq/coin-framework/bot/types";
|
|
5
|
+
import type { Transaction } from "./types";
|
|
6
|
+
import { deviceActionFlow, SpeculosButton } from "@ledgerhq/coin-framework/bot/specs";
|
|
7
|
+
const confirmWording: Record<string, string> = {
|
|
8
|
+
send: "transfer",
|
|
9
|
+
stake: "deposit_and_stake",
|
|
10
|
+
unstake: "unstake",
|
|
11
|
+
withdraw: "withdraw",
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const acceptTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
|
|
15
|
+
steps: [
|
|
16
|
+
{
|
|
17
|
+
title: "Confirm",
|
|
18
|
+
button: SpeculosButton.RIGHT,
|
|
19
|
+
expectedValue: ({ transaction }) => confirmWording[transaction.mode],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
title: "Deposit",
|
|
23
|
+
button: SpeculosButton.RIGHT,
|
|
24
|
+
expectedValue: ({ transaction, account }) => {
|
|
25
|
+
if (transaction.mode === "stake") {
|
|
26
|
+
return formatCurrencyUnit(getAccountUnit(account), transaction.amount, {
|
|
27
|
+
disableRounding: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return "0";
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: "Amount",
|
|
36
|
+
button: SpeculosButton.RIGHT,
|
|
37
|
+
expectedValue: ({ transaction, account }) =>
|
|
38
|
+
formatCurrencyUnit(getAccountUnit(account), transaction.amount, {
|
|
39
|
+
disableRounding: true,
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: "To",
|
|
44
|
+
button: SpeculosButton.RIGHT,
|
|
45
|
+
expectedValue: ({ transaction }) => transaction.recipient,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: "From",
|
|
49
|
+
button: SpeculosButton.RIGHT,
|
|
50
|
+
expectedValue: ({ account }) => account.freshAddress,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: "Args",
|
|
54
|
+
button: SpeculosButton.RIGHT,
|
|
55
|
+
expectedValue: ({ transaction, account }) => {
|
|
56
|
+
if (transaction.mode === "stake") {
|
|
57
|
+
return "{}";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return JSON.stringify({
|
|
61
|
+
amount: nearAPI.utils.format.parseNearAmount(
|
|
62
|
+
formatCurrencyUnit(getAccountUnit(account), transaction.amount, {
|
|
63
|
+
disableRounding: true,
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
title: "Approve",
|
|
71
|
+
button: SpeculosButton.BOTH,
|
|
72
|
+
final: true,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Transaction, TransactionRaw } from "./types";
|
|
2
|
+
import { BigNumber } from "bignumber.js";
|
|
3
|
+
import {
|
|
4
|
+
formatTransactionStatusCommon as formatTransactionStatus,
|
|
5
|
+
fromTransactionCommonRaw,
|
|
6
|
+
fromTransactionStatusRawCommon as fromTransactionStatusRaw,
|
|
7
|
+
toTransactionCommonRaw,
|
|
8
|
+
toTransactionStatusRawCommon as toTransactionStatusRaw,
|
|
9
|
+
} from "@ledgerhq/coin-framework/transaction/common";
|
|
10
|
+
import type { Account } from "@ledgerhq/types-live";
|
|
11
|
+
import { getAccountUnit } from "@ledgerhq/coin-framework/account/index";
|
|
12
|
+
import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/index";
|
|
13
|
+
|
|
14
|
+
export const formatTransaction = (
|
|
15
|
+
{ mode, amount, recipient, useAllAmount }: Transaction,
|
|
16
|
+
account: Account,
|
|
17
|
+
): string => `
|
|
18
|
+
${mode.toUpperCase()} ${
|
|
19
|
+
useAllAmount
|
|
20
|
+
? "MAX"
|
|
21
|
+
: amount.isZero()
|
|
22
|
+
? ""
|
|
23
|
+
: " " +
|
|
24
|
+
formatCurrencyUnit(getAccountUnit(account), amount, {
|
|
25
|
+
showCode: true,
|
|
26
|
+
disableRounding: true,
|
|
27
|
+
})
|
|
28
|
+
}${recipient ? `\nTO ${recipient}` : ""}`;
|
|
29
|
+
|
|
30
|
+
export const fromTransactionRaw = (tr: TransactionRaw): Transaction => {
|
|
31
|
+
const common = fromTransactionCommonRaw(tr);
|
|
32
|
+
return {
|
|
33
|
+
...common,
|
|
34
|
+
family: tr.family,
|
|
35
|
+
mode: tr.mode,
|
|
36
|
+
fees: new BigNumber(tr?.fees || 0),
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const toTransactionRaw = (t: Transaction): TransactionRaw => {
|
|
41
|
+
const common = toTransactionCommonRaw(t);
|
|
42
|
+
return {
|
|
43
|
+
...common,
|
|
44
|
+
family: t.family,
|
|
45
|
+
mode: t.mode,
|
|
46
|
+
fees: t.fees?.toString(),
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default {
|
|
51
|
+
formatTransaction,
|
|
52
|
+
fromTransactionRaw,
|
|
53
|
+
toTransactionRaw,
|
|
54
|
+
fromTransactionStatusRaw,
|
|
55
|
+
toTransactionStatusRaw,
|
|
56
|
+
formatTransactionStatus,
|
|
57
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { BigNumber } from "bignumber.js";
|
|
2
|
+
import {
|
|
3
|
+
Account,
|
|
4
|
+
AccountRaw,
|
|
5
|
+
TransactionCommon,
|
|
6
|
+
TransactionCommonRaw,
|
|
7
|
+
TransactionStatusCommon,
|
|
8
|
+
TransactionStatusCommonRaw,
|
|
9
|
+
} from "@ledgerhq/types-live";
|
|
10
|
+
import type { NearStakingPosition } from "./api/sdk.types";
|
|
11
|
+
|
|
12
|
+
export type { NearStakingPosition } from "./api/sdk.types";
|
|
13
|
+
|
|
14
|
+
export type Transaction = TransactionCommon & {
|
|
15
|
+
family: "near";
|
|
16
|
+
mode: string;
|
|
17
|
+
fees?: BigNumber;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type TransactionRaw = TransactionCommonRaw & {
|
|
21
|
+
family: "near";
|
|
22
|
+
mode: string;
|
|
23
|
+
fees?: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type NearPreloadedData = {
|
|
27
|
+
storageCost: BigNumber;
|
|
28
|
+
gasPrice: BigNumber;
|
|
29
|
+
createAccountCostSend: BigNumber;
|
|
30
|
+
createAccountCostExecution: BigNumber;
|
|
31
|
+
transferCostSend: BigNumber;
|
|
32
|
+
transferCostExecution: BigNumber;
|
|
33
|
+
addKeyCostSend: BigNumber;
|
|
34
|
+
addKeyCostExecution: BigNumber;
|
|
35
|
+
receiptCreationSend: BigNumber;
|
|
36
|
+
receiptCreationExecution: BigNumber;
|
|
37
|
+
validators: NearValidatorItem[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type NearResources = {
|
|
41
|
+
stakedBalance: BigNumber;
|
|
42
|
+
availableBalance: BigNumber;
|
|
43
|
+
pendingBalance: BigNumber;
|
|
44
|
+
storageUsageBalance: BigNumber;
|
|
45
|
+
stakingPositions: NearStakingPosition[];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type NearResourcesRaw = {
|
|
49
|
+
stakedBalance: string;
|
|
50
|
+
availableBalance: string;
|
|
51
|
+
pendingBalance: string;
|
|
52
|
+
storageUsageBalance: string;
|
|
53
|
+
stakingPositions: {
|
|
54
|
+
staked: string;
|
|
55
|
+
available: string;
|
|
56
|
+
pending: string;
|
|
57
|
+
rewards: string;
|
|
58
|
+
validatorId: string;
|
|
59
|
+
}[];
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type NearAccount = Account & { nearResources: NearResources };
|
|
63
|
+
|
|
64
|
+
export type NearAccountRaw = AccountRaw & {
|
|
65
|
+
nearResources: NearResourcesRaw;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type NearValidatorItem = {
|
|
69
|
+
validatorAddress: string;
|
|
70
|
+
commission: number | null;
|
|
71
|
+
tokens: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type NearMappedStakingPosition = NearStakingPosition & {
|
|
75
|
+
formattedAmount: string;
|
|
76
|
+
formattedRewards: string;
|
|
77
|
+
formattedPending: string;
|
|
78
|
+
formattedAvailable: string;
|
|
79
|
+
rank: number;
|
|
80
|
+
validator: NearValidatorItem | null | undefined;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type StatusErrorMap = {
|
|
84
|
+
recipient?: Error;
|
|
85
|
+
amount?: Error;
|
|
86
|
+
fees?: Error;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type TransactionStatus = TransactionStatusCommon;
|
|
90
|
+
|
|
91
|
+
export type TransactionStatusRaw = TransactionStatusCommonRaw;
|
package/tsconfig.json
ADDED