@ledgerhq/coin-hedera 1.16.0-nightly.20251212024049 → 1.16.0-nightly.20251215100948
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/CHANGELOG.md +12 -10
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +4 -3
- package/lib/api/index.js.map +1 -1
- package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib/bridge/buildOptimisticOperation.js +14 -43
- package/lib/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib/constants.d.ts +11 -6
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +20 -1
- package/lib/constants.js.map +1 -1
- package/lib/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/deviceTransactionConfig.js +1 -3
- package/lib/deviceTransactionConfig.js.map +1 -1
- package/lib/logic/getBalance.d.ts.map +1 -1
- package/lib/logic/getBalance.js +21 -4
- package/lib/logic/getBalance.js.map +1 -1
- package/lib/logic/getBlock.d.ts.map +1 -1
- package/lib/logic/getBlock.js +39 -2
- package/lib/logic/getBlock.js.map +1 -1
- package/lib/logic/getValidators.d.ts +3 -0
- package/lib/logic/getValidators.d.ts.map +1 -0
- package/lib/logic/getValidators.js +24 -0
- package/lib/logic/getValidators.js.map +1 -0
- package/lib/logic/index.d.ts +1 -0
- package/lib/logic/index.d.ts.map +1 -1
- package/lib/logic/index.js +3 -1
- package/lib/logic/index.js.map +1 -1
- package/lib/logic/listOperations.d.ts.map +1 -1
- package/lib/logic/listOperations.js +16 -2
- package/lib/logic/listOperations.js.map +1 -1
- package/lib/logic/utils.d.ts +17 -1
- package/lib/logic/utils.d.ts.map +1 -1
- package/lib/logic/utils.js +54 -1
- package/lib/logic/utils.js.map +1 -1
- package/lib/network/api.d.ts +22 -2
- package/lib/network/api.d.ts.map +1 -1
- package/lib/network/api.js +49 -14
- package/lib/network/api.js.map +1 -1
- package/lib/preload.js +2 -2
- package/lib/preload.js.map +1 -1
- package/lib/test/fixtures/account.fixture.d.ts +8 -0
- package/lib/test/fixtures/account.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/account.fixture.js +8 -0
- package/lib/test/fixtures/account.fixture.js.map +1 -1
- package/lib/test/fixtures/mirror.fixture.d.ts +2 -1
- package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/mirror.fixture.js +16 -1
- package/lib/test/fixtures/mirror.fixture.js.map +1 -1
- package/lib/types/bridge.d.ts +1 -0
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib/types/logic.d.ts +6 -0
- package/lib/types/logic.d.ts.map +1 -1
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +5 -4
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.js +15 -44
- package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib-es/constants.d.ts +11 -6
- package/lib-es/constants.d.ts.map +1 -1
- package/lib-es/constants.js +19 -0
- package/lib-es/constants.js.map +1 -1
- package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
- package/lib-es/deviceTransactionConfig.js +2 -4
- package/lib-es/deviceTransactionConfig.js.map +1 -1
- package/lib-es/logic/getBalance.d.ts.map +1 -1
- package/lib-es/logic/getBalance.js +21 -4
- package/lib-es/logic/getBalance.js.map +1 -1
- package/lib-es/logic/getBlock.d.ts.map +1 -1
- package/lib-es/logic/getBlock.js +40 -3
- package/lib-es/logic/getBlock.js.map +1 -1
- package/lib-es/logic/getValidators.d.ts +3 -0
- package/lib-es/logic/getValidators.d.ts.map +1 -0
- package/lib-es/logic/getValidators.js +20 -0
- package/lib-es/logic/getValidators.js.map +1 -0
- package/lib-es/logic/index.d.ts +1 -0
- package/lib-es/logic/index.d.ts.map +1 -1
- package/lib-es/logic/index.js +1 -0
- package/lib-es/logic/index.js.map +1 -1
- package/lib-es/logic/listOperations.d.ts.map +1 -1
- package/lib-es/logic/listOperations.js +17 -3
- package/lib-es/logic/listOperations.js.map +1 -1
- package/lib-es/logic/utils.d.ts +17 -1
- package/lib-es/logic/utils.d.ts.map +1 -1
- package/lib-es/logic/utils.js +52 -1
- package/lib-es/logic/utils.js.map +1 -1
- package/lib-es/network/api.d.ts +22 -2
- package/lib-es/network/api.d.ts.map +1 -1
- package/lib-es/network/api.js +49 -14
- package/lib-es/network/api.js.map +1 -1
- package/lib-es/preload.js +2 -2
- package/lib-es/preload.js.map +1 -1
- package/lib-es/test/fixtures/account.fixture.d.ts +8 -0
- package/lib-es/test/fixtures/account.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/account.fixture.js +8 -0
- package/lib-es/test/fixtures/account.fixture.js.map +1 -1
- package/lib-es/test/fixtures/mirror.fixture.d.ts +2 -1
- package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/mirror.fixture.js +14 -0
- package/lib-es/test/fixtures/mirror.fixture.js.map +1 -1
- package/lib-es/types/bridge.d.ts +1 -0
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/lib-es/types/logic.d.ts +6 -0
- package/lib-es/types/logic.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/api/index.integ.test.ts +226 -1
- package/src/api/index.test.ts +5 -2
- package/src/api/index.ts +5 -5
- package/src/bridge/{buildOptimisticOperation.integration.test.ts → buildOptimisticOperation.test.ts} +23 -68
- package/src/bridge/buildOptimisticOperation.ts +16 -45
- package/src/constants.ts +23 -1
- package/src/deviceTransactionConfig.test.ts +59 -43
- package/src/deviceTransactionConfig.ts +2 -5
- package/src/logic/getBalance.test.ts +50 -0
- package/src/logic/getBalance.ts +21 -4
- package/src/logic/getBlock.test.ts +283 -1
- package/src/logic/getBlock.ts +57 -6
- package/src/logic/getValidators.test.ts +50 -0
- package/src/logic/getValidators.ts +22 -0
- package/src/logic/index.ts +1 -0
- package/src/logic/listOperations.ts +33 -3
- package/src/logic/utils.test.ts +113 -0
- package/src/logic/utils.ts +67 -1
- package/src/network/api.test.ts +55 -9
- package/src/network/api.ts +66 -14
- package/src/preload.ts +2 -2
- package/src/test/fixtures/account.fixture.ts +8 -0
- package/src/test/fixtures/mirror.fixture.ts +18 -0
- package/src/types/bridge.ts +1 -0
- package/src/types/logic.ts +7 -0
package/src/bridge/{buildOptimisticOperation.integration.test.ts → buildOptimisticOperation.test.ts}
RENAMED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
2
|
import { buildOptimisticOperation } from "./buildOptimisticOperation";
|
|
3
|
-
import {
|
|
4
|
-
import { estimateFees } from "../logic/estimateFees";
|
|
3
|
+
import { HEDERA_TRANSACTION_MODES } from "../constants";
|
|
5
4
|
import { getMockedAccount, getMockedTokenAccount } from "../test/fixtures/account.fixture";
|
|
6
5
|
import {
|
|
7
6
|
getMockedERC20TokenCurrency,
|
|
@@ -17,16 +16,12 @@ describe("buildOptimisticOperation", () => {
|
|
|
17
16
|
mode: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
18
17
|
amount: new BigNumber(0),
|
|
19
18
|
recipient: "0.0.1234",
|
|
19
|
+
maxFee: new BigNumber(1000),
|
|
20
20
|
properties: {
|
|
21
21
|
token: mockedToken,
|
|
22
22
|
},
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
-
const estimatedFee = await estimateFees({
|
|
26
|
-
currency: mockedAccount.currency,
|
|
27
|
-
operationType: HEDERA_OPERATION_TYPES.TokenAssociate,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
25
|
const op = await buildOptimisticOperation({
|
|
31
26
|
account: mockedAccount,
|
|
32
27
|
transaction: mockedTransaction,
|
|
@@ -34,7 +29,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
34
29
|
|
|
35
30
|
expect(op.type).toBe("ASSOCIATE_TOKEN");
|
|
36
31
|
expect(op.extra).toEqual({ associatedTokenId: mockedToken.contractAddress });
|
|
37
|
-
expect(op.fee).toEqual(
|
|
32
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
38
33
|
expect(op.senders).toContain(mockedAccount.freshAddress);
|
|
39
34
|
expect(op.recipients).toContain("0.0.1234");
|
|
40
35
|
});
|
|
@@ -44,11 +39,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
44
39
|
const mockedTransaction = getMockedTransaction({
|
|
45
40
|
amount: new BigNumber(123),
|
|
46
41
|
recipient: "0.0.5678",
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const estimatedFee = await estimateFees({
|
|
50
|
-
currency: mockedAccount.currency,
|
|
51
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoTransfer,
|
|
42
|
+
maxFee: new BigNumber(1500),
|
|
52
43
|
});
|
|
53
44
|
|
|
54
45
|
const op = await buildOptimisticOperation({
|
|
@@ -57,14 +48,13 @@ describe("buildOptimisticOperation", () => {
|
|
|
57
48
|
});
|
|
58
49
|
|
|
59
50
|
expect(op.type).toBe("OUT");
|
|
60
|
-
expect(op.fee).toEqual(
|
|
51
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
61
52
|
expect(op.value).toEqual(new BigNumber(123));
|
|
62
53
|
expect(op.senders).toContain(mockedAccount.freshAddress);
|
|
63
54
|
expect(op.recipients).toContain("0.0.5678");
|
|
64
55
|
});
|
|
65
56
|
|
|
66
57
|
it("builds optimistic operation for HTS token", async () => {
|
|
67
|
-
const mockedAccount = getMockedAccount();
|
|
68
58
|
const mockedTokenCurrency = getMockedHTSTokenCurrency();
|
|
69
59
|
const tokenAccount = getMockedTokenAccount(mockedTokenCurrency);
|
|
70
60
|
const parentAccount = getMockedAccount({ subAccounts: [tokenAccount] });
|
|
@@ -72,11 +62,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
72
62
|
subAccountId: tokenAccount.id,
|
|
73
63
|
amount: new BigNumber(123),
|
|
74
64
|
recipient: "0.0.9999",
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const estimatedFee = await estimateFees({
|
|
78
|
-
currency: mockedAccount.currency,
|
|
79
|
-
operationType: HEDERA_OPERATION_TYPES.TokenTransfer,
|
|
65
|
+
maxFee: new BigNumber(2000),
|
|
80
66
|
});
|
|
81
67
|
|
|
82
68
|
const op = await buildOptimisticOperation({
|
|
@@ -86,11 +72,11 @@ describe("buildOptimisticOperation", () => {
|
|
|
86
72
|
const subOp = (op.subOperations ?? [])[0];
|
|
87
73
|
|
|
88
74
|
expect(op.type).toBe("FEES");
|
|
89
|
-
expect(op.value).toEqual(
|
|
75
|
+
expect(op.value).toEqual(mockedTransaction.maxFee);
|
|
90
76
|
expect(op.subOperations).toHaveLength(1);
|
|
91
77
|
expect(subOp.type).toBe("OUT");
|
|
92
78
|
expect(subOp.value).toEqual(new BigNumber(123));
|
|
93
|
-
expect(subOp.fee).toEqual(
|
|
79
|
+
expect(subOp.fee).toEqual(mockedTransaction.maxFee);
|
|
94
80
|
expect(subOp.accountId).toBe(tokenAccount.id);
|
|
95
81
|
expect(subOp.recipients).toContain("0.0.9999");
|
|
96
82
|
});
|
|
@@ -103,22 +89,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
103
89
|
subAccountId: tokenAccount.id,
|
|
104
90
|
amount: new BigNumber(123),
|
|
105
91
|
recipient: "0.0.9999",
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
const estimatedFee = await estimateFees({
|
|
109
|
-
operationType: HEDERA_OPERATION_TYPES.ContractCall,
|
|
110
|
-
txIntent: {
|
|
111
|
-
intentType: "transaction",
|
|
112
|
-
type: HEDERA_TRANSACTION_MODES.Send,
|
|
113
|
-
asset: {
|
|
114
|
-
type: "erc20",
|
|
115
|
-
assetReference: tokenAccount.token.contractAddress,
|
|
116
|
-
assetOwner: parentAccount.freshAddress,
|
|
117
|
-
},
|
|
118
|
-
amount: BigInt(mockedTransaction.amount.toString()),
|
|
119
|
-
sender: parentAccount.freshAddress,
|
|
120
|
-
recipient: mockedTransaction.recipient,
|
|
121
|
-
},
|
|
92
|
+
maxFee: new BigNumber(2500),
|
|
122
93
|
});
|
|
123
94
|
|
|
124
95
|
const op = await buildOptimisticOperation({
|
|
@@ -128,11 +99,11 @@ describe("buildOptimisticOperation", () => {
|
|
|
128
99
|
const subOp = (op.subOperations ?? [])[0];
|
|
129
100
|
|
|
130
101
|
expect(op.type).toBe("FEES");
|
|
131
|
-
expect(op.value).toEqual(
|
|
102
|
+
expect(op.value).toEqual(mockedTransaction.maxFee);
|
|
132
103
|
expect(op.subOperations).toHaveLength(1);
|
|
133
104
|
expect(subOp.type).toBe("OUT");
|
|
134
105
|
expect(subOp.value).toEqual(new BigNumber(123));
|
|
135
|
-
expect(subOp.fee).toEqual(
|
|
106
|
+
expect(subOp.fee).toEqual(mockedTransaction.maxFee);
|
|
136
107
|
expect(subOp.accountId).toBe(tokenAccount.id);
|
|
137
108
|
expect(subOp.recipients).toContain("0.0.9999");
|
|
138
109
|
});
|
|
@@ -144,23 +115,19 @@ describe("buildOptimisticOperation", () => {
|
|
|
144
115
|
mode: HEDERA_TRANSACTION_MODES.Delegate,
|
|
145
116
|
amount: new BigNumber(0),
|
|
146
117
|
recipient: "",
|
|
118
|
+
maxFee: new BigNumber(1200),
|
|
147
119
|
properties: {
|
|
148
120
|
stakingNodeId,
|
|
149
121
|
},
|
|
150
122
|
});
|
|
151
123
|
|
|
152
|
-
const estimatedFee = await estimateFees({
|
|
153
|
-
currency: mockedAccount.currency,
|
|
154
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoUpdate,
|
|
155
|
-
});
|
|
156
|
-
|
|
157
124
|
const op = await buildOptimisticOperation({
|
|
158
125
|
account: mockedAccount,
|
|
159
126
|
transaction: mockedTransaction,
|
|
160
127
|
});
|
|
161
128
|
|
|
162
|
-
expect(op.type).toBe("
|
|
163
|
-
expect(op.fee).toEqual(
|
|
129
|
+
expect(op.type).toBe("DELEGATE");
|
|
130
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
164
131
|
expect(op.value).toEqual(new BigNumber(0));
|
|
165
132
|
expect(op.senders).toContain(mockedAccount.freshAddress);
|
|
166
133
|
expect(op.extra).toEqual({
|
|
@@ -188,15 +155,11 @@ describe("buildOptimisticOperation", () => {
|
|
|
188
155
|
mode: HEDERA_TRANSACTION_MODES.Redelegate,
|
|
189
156
|
amount: new BigNumber(0),
|
|
190
157
|
recipient: "",
|
|
158
|
+
maxFee: new BigNumber(1300),
|
|
159
|
+
memo: "Redelegating to better validator",
|
|
191
160
|
properties: {
|
|
192
161
|
stakingNodeId: newNodeId,
|
|
193
162
|
},
|
|
194
|
-
memo: "Redelegating to better validator",
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
const estimatedFee = await estimateFees({
|
|
198
|
-
currency: mockedAccount.currency,
|
|
199
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoUpdate,
|
|
200
163
|
});
|
|
201
164
|
|
|
202
165
|
const op = await buildOptimisticOperation({
|
|
@@ -204,8 +167,8 @@ describe("buildOptimisticOperation", () => {
|
|
|
204
167
|
transaction: mockedTransaction,
|
|
205
168
|
});
|
|
206
169
|
|
|
207
|
-
expect(op.type).toBe("
|
|
208
|
-
expect(op.fee).toEqual(
|
|
170
|
+
expect(op.type).toBe("REDELEGATE");
|
|
171
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
209
172
|
expect(op.extra).toEqual({
|
|
210
173
|
memo: "Redelegating to better validator",
|
|
211
174
|
targetStakingNodeId: newNodeId,
|
|
@@ -230,23 +193,19 @@ describe("buildOptimisticOperation", () => {
|
|
|
230
193
|
mode: HEDERA_TRANSACTION_MODES.Undelegate,
|
|
231
194
|
amount: new BigNumber(0),
|
|
232
195
|
recipient: "",
|
|
196
|
+
maxFee: new BigNumber(1100),
|
|
233
197
|
properties: {
|
|
234
198
|
stakingNodeId: null,
|
|
235
199
|
},
|
|
236
200
|
});
|
|
237
201
|
|
|
238
|
-
const estimatedFee = await estimateFees({
|
|
239
|
-
currency: mockedAccount.currency,
|
|
240
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoUpdate,
|
|
241
|
-
});
|
|
242
|
-
|
|
243
202
|
const op = await buildOptimisticOperation({
|
|
244
203
|
account: mockedAccount,
|
|
245
204
|
transaction: mockedTransaction,
|
|
246
205
|
});
|
|
247
206
|
|
|
248
|
-
expect(op.type).toBe("
|
|
249
|
-
expect(op.fee).toEqual(
|
|
207
|
+
expect(op.type).toBe("UNDELEGATE");
|
|
208
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
250
209
|
expect(op.value).toEqual(new BigNumber(0));
|
|
251
210
|
expect(op.extra).toEqual({
|
|
252
211
|
memo: null,
|
|
@@ -272,21 +231,17 @@ describe("buildOptimisticOperation", () => {
|
|
|
272
231
|
mode: HEDERA_TRANSACTION_MODES.ClaimRewards,
|
|
273
232
|
amount: new BigNumber(0),
|
|
274
233
|
recipient: "",
|
|
234
|
+
maxFee: new BigNumber(1400),
|
|
275
235
|
memo: "Claiming staking rewards",
|
|
276
236
|
});
|
|
277
237
|
|
|
278
|
-
const estimatedFee = await estimateFees({
|
|
279
|
-
currency: mockedAccount.currency,
|
|
280
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoTransfer,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
238
|
const op = await buildOptimisticOperation({
|
|
284
239
|
account: mockedAccount,
|
|
285
240
|
transaction: mockedTransaction,
|
|
286
241
|
});
|
|
287
242
|
|
|
288
243
|
expect(op.type).toBe("OUT");
|
|
289
|
-
expect(op.fee).toEqual(
|
|
244
|
+
expect(op.fee).toEqual(mockedTransaction.maxFee);
|
|
290
245
|
expect(op.extra).toEqual({
|
|
291
246
|
memo: "Claiming staking rewards",
|
|
292
247
|
});
|
|
@@ -3,8 +3,7 @@ import invariant from "invariant";
|
|
|
3
3
|
import type { Account, Operation, OperationType, TokenAccount } from "@ledgerhq/types-live";
|
|
4
4
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
5
5
|
import { findSubAccountById } from "@ledgerhq/coin-framework/account/helpers";
|
|
6
|
-
import {
|
|
7
|
-
import { estimateFees } from "../logic/estimateFees";
|
|
6
|
+
import { HEDERA_TRANSACTION_MODES, MAP_STAKING_MODE_TO_OPERATION_TYPE } from "../constants";
|
|
8
7
|
import {
|
|
9
8
|
safeParseAccountId,
|
|
10
9
|
isTokenAssociateTransaction,
|
|
@@ -21,18 +20,15 @@ const buildOptimisticTokenAssociateOperation = async ({
|
|
|
21
20
|
}): Promise<Operation> => {
|
|
22
21
|
invariant(isTokenAssociateTransaction(transaction), "invalid transaction properties");
|
|
23
22
|
|
|
24
|
-
const
|
|
25
|
-
currency: account.currency,
|
|
26
|
-
operationType: HEDERA_OPERATION_TYPES.TokenAssociate,
|
|
27
|
-
});
|
|
23
|
+
const fee = transaction.maxFee ?? new BigNumber(0);
|
|
28
24
|
const type: OperationType = "ASSOCIATE_TOKEN";
|
|
29
25
|
|
|
30
26
|
const operation: Operation = {
|
|
31
27
|
id: encodeOperationId(account.id, "", type),
|
|
32
28
|
hash: "",
|
|
33
29
|
type,
|
|
34
|
-
value:
|
|
35
|
-
fee
|
|
30
|
+
value: fee,
|
|
31
|
+
fee,
|
|
36
32
|
blockHash: null,
|
|
37
33
|
blockHeight: null,
|
|
38
34
|
senders: [account.freshAddress.toString()],
|
|
@@ -56,13 +52,8 @@ const buildOptimisticCoinOperation = async ({
|
|
|
56
52
|
transaction: Transaction;
|
|
57
53
|
transactionType?: OperationType;
|
|
58
54
|
}): Promise<Operation> => {
|
|
59
|
-
const
|
|
60
|
-
transactionType === "FEES"
|
|
61
|
-
? transaction.amount
|
|
62
|
-
: await estimateFees({
|
|
63
|
-
currency: account.currency,
|
|
64
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoTransfer,
|
|
65
|
-
});
|
|
55
|
+
const fee =
|
|
56
|
+
transactionType === "FEES" ? transaction.amount : transaction.maxFee ?? new BigNumber(0);
|
|
66
57
|
const value = transaction.amount;
|
|
67
58
|
const type: OperationType = transactionType ?? "OUT";
|
|
68
59
|
const [_, recipientAddress] = safeParseAccountId(transaction.recipient);
|
|
@@ -74,7 +65,7 @@ const buildOptimisticCoinOperation = async ({
|
|
|
74
65
|
hash: "",
|
|
75
66
|
type,
|
|
76
67
|
value,
|
|
77
|
-
fee
|
|
68
|
+
fee,
|
|
78
69
|
blockHash: null,
|
|
79
70
|
blockHeight: null,
|
|
80
71
|
senders: [account.freshAddress.toString()],
|
|
@@ -98,10 +89,7 @@ const buildOptimisticHTSTokenOperation = async ({
|
|
|
98
89
|
tokenAccount: TokenAccount;
|
|
99
90
|
transaction: Transaction;
|
|
100
91
|
}): Promise<Operation> => {
|
|
101
|
-
const
|
|
102
|
-
currency: account.currency,
|
|
103
|
-
operationType: HEDERA_OPERATION_TYPES.TokenTransfer,
|
|
104
|
-
});
|
|
92
|
+
const fee = transaction.maxFee ?? new BigNumber(0);
|
|
105
93
|
const value = transaction.amount;
|
|
106
94
|
const type: OperationType = "OUT";
|
|
107
95
|
const [_, recipientAddress] = safeParseAccountId(transaction.recipient);
|
|
@@ -112,7 +100,7 @@ const buildOptimisticHTSTokenOperation = async ({
|
|
|
112
100
|
account,
|
|
113
101
|
transaction: {
|
|
114
102
|
...transaction,
|
|
115
|
-
amount:
|
|
103
|
+
amount: fee,
|
|
116
104
|
},
|
|
117
105
|
transactionType: "FEES",
|
|
118
106
|
});
|
|
@@ -125,7 +113,7 @@ const buildOptimisticHTSTokenOperation = async ({
|
|
|
125
113
|
hash: "",
|
|
126
114
|
type,
|
|
127
115
|
value,
|
|
128
|
-
fee
|
|
116
|
+
fee,
|
|
129
117
|
blockHash: null,
|
|
130
118
|
blockHeight: null,
|
|
131
119
|
senders: [account.freshAddress.toString()],
|
|
@@ -151,21 +139,7 @@ const buildOptimisticERC20TokenOperation = async ({
|
|
|
151
139
|
tokenAccount: TokenAccount;
|
|
152
140
|
transaction: Transaction;
|
|
153
141
|
}): Promise<Operation> => {
|
|
154
|
-
const
|
|
155
|
-
operationType: HEDERA_OPERATION_TYPES.ContractCall,
|
|
156
|
-
txIntent: {
|
|
157
|
-
intentType: "transaction",
|
|
158
|
-
type: HEDERA_TRANSACTION_MODES.Send,
|
|
159
|
-
asset: {
|
|
160
|
-
type: "erc20",
|
|
161
|
-
assetReference: tokenAccount.token.contractAddress,
|
|
162
|
-
assetOwner: account.freshAddress,
|
|
163
|
-
},
|
|
164
|
-
amount: BigInt(transaction.amount.toString()),
|
|
165
|
-
sender: account.freshAddress,
|
|
166
|
-
recipient: transaction.recipient,
|
|
167
|
-
},
|
|
168
|
-
});
|
|
142
|
+
const fee = transaction.maxFee ?? new BigNumber(0);
|
|
169
143
|
const value = transaction.amount;
|
|
170
144
|
const type: OperationType = "OUT";
|
|
171
145
|
const memo = transaction.memo;
|
|
@@ -174,7 +148,7 @@ const buildOptimisticERC20TokenOperation = async ({
|
|
|
174
148
|
account,
|
|
175
149
|
transaction: {
|
|
176
150
|
...transaction,
|
|
177
|
-
amount:
|
|
151
|
+
amount: fee,
|
|
178
152
|
},
|
|
179
153
|
transactionType: "FEES",
|
|
180
154
|
});
|
|
@@ -187,7 +161,7 @@ const buildOptimisticERC20TokenOperation = async ({
|
|
|
187
161
|
hash: "",
|
|
188
162
|
type,
|
|
189
163
|
value,
|
|
190
|
-
fee
|
|
164
|
+
fee,
|
|
191
165
|
blockHash: null,
|
|
192
166
|
blockHeight: null,
|
|
193
167
|
senders: [account.freshAddress.toString()],
|
|
@@ -213,19 +187,16 @@ const buildOptimisticUpdateAccountOperation = async ({
|
|
|
213
187
|
}): Promise<Operation> => {
|
|
214
188
|
invariant(isStakingTransaction(transaction), "invalid transaction properties");
|
|
215
189
|
|
|
216
|
-
const
|
|
217
|
-
operationType: HEDERA_OPERATION_TYPES.CryptoUpdate,
|
|
218
|
-
currency: account.currency,
|
|
219
|
-
});
|
|
190
|
+
const fee = transaction.maxFee ?? new BigNumber(0);
|
|
220
191
|
const value = transaction.amount;
|
|
221
|
-
const type: OperationType =
|
|
192
|
+
const type: OperationType = MAP_STAKING_MODE_TO_OPERATION_TYPE[transaction.mode];
|
|
222
193
|
|
|
223
194
|
const operation: Operation = {
|
|
224
195
|
id: encodeOperationId(account.id, "", type),
|
|
225
196
|
hash: "",
|
|
226
197
|
type,
|
|
227
198
|
value,
|
|
228
|
-
fee
|
|
199
|
+
fee,
|
|
229
200
|
blockHash: null,
|
|
230
201
|
blockHeight: null,
|
|
231
202
|
senders: [account.freshAddress.toString()],
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
+
import type { OperationType } from "@ledgerhq/types-live";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Internal types to distinguish custom Hedera transaction behaviors.
|
|
@@ -13,6 +14,14 @@ export enum HEDERA_TRANSACTION_MODES {
|
|
|
13
14
|
ClaimRewards = "claim-rewards",
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Enum representing Hedera transaction names used in the Hedera Mirror Node API.
|
|
19
|
+
*/
|
|
20
|
+
export enum HEDERA_TRANSACTION_NAMES {
|
|
21
|
+
ContractCall = "CONTRACTCALL",
|
|
22
|
+
UpdateAccount = "CRYPTOUPDATEACCOUNT",
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
/**
|
|
17
26
|
* Enum representing the supported Hedera operation types for fee estimation
|
|
18
27
|
*/
|
|
@@ -100,9 +109,22 @@ export const SUPPORTED_ERC20_TOKENS = [
|
|
|
100
109
|
},
|
|
101
110
|
];
|
|
102
111
|
|
|
103
|
-
export const MAP_STAKING_MODE_TO_MEMO = {
|
|
112
|
+
export const MAP_STAKING_MODE_TO_MEMO: Record<string, string> = {
|
|
104
113
|
[HEDERA_TRANSACTION_MODES.ClaimRewards]: "Collect Staking Rewards",
|
|
105
114
|
[HEDERA_TRANSACTION_MODES.Delegate]: "Stake",
|
|
106
115
|
[HEDERA_TRANSACTION_MODES.Undelegate]: "Unstake",
|
|
107
116
|
[HEDERA_TRANSACTION_MODES.Redelegate]: "Restake",
|
|
108
117
|
} as const;
|
|
118
|
+
|
|
119
|
+
export const MAP_STAKING_MODE_TO_OPERATION_TYPE: Record<string, OperationType> = {
|
|
120
|
+
[HEDERA_TRANSACTION_MODES.Delegate]: "DELEGATE",
|
|
121
|
+
[HEDERA_TRANSACTION_MODES.Undelegate]: "UNDELEGATE",
|
|
122
|
+
[HEDERA_TRANSACTION_MODES.Redelegate]: "REDELEGATE",
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export const MAP_STAKING_MODE_TO_METHOD: Record<string, string> = {
|
|
126
|
+
[HEDERA_TRANSACTION_MODES.Delegate]: "Delegate",
|
|
127
|
+
[HEDERA_TRANSACTION_MODES.Undelegate]: "Undelegate",
|
|
128
|
+
[HEDERA_TRANSACTION_MODES.Redelegate]: "Redelegate",
|
|
129
|
+
[HEDERA_TRANSACTION_MODES.ClaimRewards]: "Claim Rewards",
|
|
130
|
+
};
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import type { Account } from "@ledgerhq/types-live";
|
|
3
2
|
import { HEDERA_TRANSACTION_MODES } from "./constants";
|
|
4
3
|
import getDeviceTransactionConfig from "./deviceTransactionConfig";
|
|
5
|
-
import type {
|
|
4
|
+
import type { TransactionStatus } from "./types";
|
|
5
|
+
import { getMockedAccount } from "./test/fixtures/account.fixture";
|
|
6
|
+
import { getMockedTransaction } from "./test/fixtures/transaction.fixture";
|
|
6
7
|
|
|
7
8
|
describe("getDeviceTransactionConfig", () => {
|
|
8
|
-
const mockAccount = {
|
|
9
|
-
id: "mock-account-id",
|
|
10
|
-
currency: { id: "hedera" },
|
|
11
|
-
} as Account;
|
|
9
|
+
const mockAccount = getMockedAccount({ id: "mock-account-id" });
|
|
12
10
|
|
|
13
11
|
const createMockStatus = (estimatedFees: BigNumber): TransactionStatus => ({
|
|
14
12
|
errors: {},
|
|
@@ -20,13 +18,11 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
20
18
|
|
|
21
19
|
describe("staking transactions", () => {
|
|
22
20
|
it("should return correct fields for ClaimRewards transaction", async () => {
|
|
23
|
-
const transaction = {
|
|
24
|
-
family: "hedera",
|
|
21
|
+
const transaction = getMockedTransaction({
|
|
25
22
|
mode: HEDERA_TRANSACTION_MODES.ClaimRewards,
|
|
26
23
|
amount: new BigNumber(0),
|
|
27
|
-
recipient: "",
|
|
28
24
|
memo: "Claiming rewards",
|
|
29
|
-
}
|
|
25
|
+
});
|
|
30
26
|
|
|
31
27
|
const status = createMockStatus(new BigNumber(100000));
|
|
32
28
|
|
|
@@ -55,15 +51,48 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
55
51
|
});
|
|
56
52
|
|
|
57
53
|
it("should return correct fields for Delegate transaction", async () => {
|
|
58
|
-
const transaction = {
|
|
59
|
-
family: "hedera",
|
|
54
|
+
const transaction = getMockedTransaction({
|
|
60
55
|
mode: HEDERA_TRANSACTION_MODES.Delegate,
|
|
61
56
|
amount: new BigNumber(0),
|
|
62
|
-
recipient: "",
|
|
63
57
|
properties: {
|
|
64
58
|
stakingNodeId: 10,
|
|
65
59
|
},
|
|
66
|
-
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const status = createMockStatus(new BigNumber(100000));
|
|
63
|
+
|
|
64
|
+
const fields = await getDeviceTransactionConfig({
|
|
65
|
+
account: mockAccount,
|
|
66
|
+
transaction,
|
|
67
|
+
status,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
expect(fields).toEqual([
|
|
71
|
+
{
|
|
72
|
+
type: "text",
|
|
73
|
+
label: "Method",
|
|
74
|
+
value: "Delegate",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: "Fees",
|
|
78
|
+
type: "fees",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
label: "Staked Node ID",
|
|
83
|
+
value: "10",
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should return correct fields for Redelegate transaction", async () => {
|
|
89
|
+
const transaction = getMockedTransaction({
|
|
90
|
+
mode: HEDERA_TRANSACTION_MODES.Redelegate,
|
|
91
|
+
amount: new BigNumber(0),
|
|
92
|
+
properties: {
|
|
93
|
+
stakingNodeId: 10,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
67
96
|
|
|
68
97
|
const status = createMockStatus(new BigNumber(100000));
|
|
69
98
|
|
|
@@ -77,7 +106,7 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
77
106
|
{
|
|
78
107
|
type: "text",
|
|
79
108
|
label: "Method",
|
|
80
|
-
value: "
|
|
109
|
+
value: "Redelegate",
|
|
81
110
|
},
|
|
82
111
|
{
|
|
83
112
|
label: "Fees",
|
|
@@ -92,13 +121,10 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
92
121
|
});
|
|
93
122
|
|
|
94
123
|
it("should not include staking node ID if not provided", async () => {
|
|
95
|
-
const transaction = {
|
|
96
|
-
family: "hedera",
|
|
124
|
+
const transaction = getMockedTransaction({
|
|
97
125
|
mode: HEDERA_TRANSACTION_MODES.Undelegate,
|
|
98
126
|
amount: new BigNumber(0),
|
|
99
|
-
|
|
100
|
-
properties: {},
|
|
101
|
-
} as Transaction;
|
|
127
|
+
});
|
|
102
128
|
|
|
103
129
|
const status = createMockStatus(new BigNumber(100000));
|
|
104
130
|
|
|
@@ -112,7 +138,7 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
112
138
|
{
|
|
113
139
|
type: "text",
|
|
114
140
|
label: "Method",
|
|
115
|
-
value: "
|
|
141
|
+
value: "Undelegate",
|
|
116
142
|
},
|
|
117
143
|
{
|
|
118
144
|
label: "Fees",
|
|
@@ -124,14 +150,11 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
124
150
|
|
|
125
151
|
describe("token associate transactions", () => {
|
|
126
152
|
it("should return correct fields for TokenAssociate transaction", async () => {
|
|
127
|
-
const transaction = {
|
|
128
|
-
family: "hedera",
|
|
153
|
+
const transaction = getMockedTransaction({
|
|
129
154
|
mode: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
130
|
-
amount: new BigNumber(0),
|
|
131
|
-
recipient: "",
|
|
132
155
|
subAccountId: "token-account-id",
|
|
133
156
|
memo: "Associating token",
|
|
134
|
-
}
|
|
157
|
+
});
|
|
135
158
|
|
|
136
159
|
const status = createMockStatus(new BigNumber(50000));
|
|
137
160
|
|
|
@@ -160,13 +183,10 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
160
183
|
});
|
|
161
184
|
|
|
162
185
|
it("should not include fees if they are zero", async () => {
|
|
163
|
-
const transaction = {
|
|
164
|
-
family: "hedera",
|
|
186
|
+
const transaction = getMockedTransaction({
|
|
165
187
|
mode: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
166
|
-
amount: new BigNumber(0),
|
|
167
|
-
recipient: "",
|
|
168
188
|
subAccountId: "token-account-id",
|
|
169
|
-
}
|
|
189
|
+
});
|
|
170
190
|
|
|
171
191
|
const status = createMockStatus(new BigNumber(0));
|
|
172
192
|
|
|
@@ -188,14 +208,13 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
188
208
|
|
|
189
209
|
describe("regular transfer transactions", () => {
|
|
190
210
|
it("should return correct fields for regular Send transaction", async () => {
|
|
191
|
-
const transaction = {
|
|
192
|
-
family: "hedera",
|
|
211
|
+
const transaction = getMockedTransaction({
|
|
193
212
|
mode: HEDERA_TRANSACTION_MODES.Send,
|
|
194
213
|
amount: new BigNumber(1000000),
|
|
195
214
|
recipient: "0.0.12345",
|
|
196
215
|
useAllAmount: false,
|
|
197
216
|
memo: "Payment",
|
|
198
|
-
}
|
|
217
|
+
});
|
|
199
218
|
|
|
200
219
|
const status = createMockStatus(new BigNumber(100000));
|
|
201
220
|
|
|
@@ -228,13 +247,12 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
228
247
|
});
|
|
229
248
|
|
|
230
249
|
it("should show 'Transfer All' method when useAllAmount is true", async () => {
|
|
231
|
-
const transaction = {
|
|
232
|
-
family: "hedera",
|
|
250
|
+
const transaction = getMockedTransaction({
|
|
233
251
|
mode: HEDERA_TRANSACTION_MODES.Send,
|
|
234
252
|
amount: new BigNumber(0),
|
|
235
253
|
recipient: "0.0.12345",
|
|
236
254
|
useAllAmount: true,
|
|
237
|
-
}
|
|
255
|
+
});
|
|
238
256
|
|
|
239
257
|
const status = createMockStatus(new BigNumber(100000));
|
|
240
258
|
|
|
@@ -252,14 +270,13 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
252
270
|
});
|
|
253
271
|
|
|
254
272
|
it("should include gas limit for Send transactions with gasLimit", async () => {
|
|
255
|
-
const transaction = {
|
|
256
|
-
family: "hedera",
|
|
273
|
+
const transaction = getMockedTransaction({
|
|
257
274
|
mode: HEDERA_TRANSACTION_MODES.Send,
|
|
258
275
|
amount: new BigNumber(1000000),
|
|
259
276
|
recipient: "0.0.12345",
|
|
260
277
|
useAllAmount: false,
|
|
261
278
|
gasLimit: new BigNumber(300000),
|
|
262
|
-
}
|
|
279
|
+
});
|
|
263
280
|
|
|
264
281
|
const status = createMockStatus(new BigNumber(100000));
|
|
265
282
|
|
|
@@ -292,13 +309,12 @@ describe("getDeviceTransactionConfig", () => {
|
|
|
292
309
|
});
|
|
293
310
|
|
|
294
311
|
it("should not include memo if not provided", async () => {
|
|
295
|
-
const transaction = {
|
|
296
|
-
family: "hedera",
|
|
312
|
+
const transaction = getMockedTransaction({
|
|
297
313
|
mode: HEDERA_TRANSACTION_MODES.Send,
|
|
298
314
|
amount: new BigNumber(1000000),
|
|
299
315
|
recipient: "0.0.12345",
|
|
300
316
|
useAllAmount: false,
|
|
301
|
-
}
|
|
317
|
+
});
|
|
302
318
|
|
|
303
319
|
const status = createMockStatus(new BigNumber(100000));
|
|
304
320
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommonDeviceTransactionField as DeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
|
|
2
2
|
import type { AccountLike, Account } from "@ledgerhq/types-live";
|
|
3
|
-
import { HEDERA_TRANSACTION_MODES } from "./constants";
|
|
3
|
+
import { HEDERA_TRANSACTION_MODES, MAP_STAKING_MODE_TO_METHOD } from "./constants";
|
|
4
4
|
import { isTokenAssociateTransaction, isStakingTransaction } from "./logic/utils";
|
|
5
5
|
import type { Transaction, TransactionStatus } from "./types";
|
|
6
6
|
|
|
@@ -19,10 +19,7 @@ async function getDeviceTransactionConfig({
|
|
|
19
19
|
fields.push({
|
|
20
20
|
type: "text",
|
|
21
21
|
label: "Method",
|
|
22
|
-
value:
|
|
23
|
-
transaction.mode === HEDERA_TRANSACTION_MODES.ClaimRewards
|
|
24
|
-
? "Claim Rewards"
|
|
25
|
-
: "Update Account",
|
|
22
|
+
value: MAP_STAKING_MODE_TO_METHOD[transaction.mode],
|
|
26
23
|
});
|
|
27
24
|
|
|
28
25
|
if (!estimatedFees.isZero()) {
|