@ledgerhq/coin-hedera 1.16.0-nightly.20251211024123 → 1.16.0-nightly.20251213023821
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 +14 -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/bridge/index.d.ts.map +1 -1
- package/lib/bridge/index.js +2 -0
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/validateAddress.d.ts +3 -0
- package/lib/bridge/validateAddress.d.ts.map +1 -0
- package/lib/bridge/validateAddress.js +10 -0
- package/lib/bridge/validateAddress.js.map +1 -0
- 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/bridge/index.d.ts.map +1 -1
- package/lib-es/bridge/index.js +2 -0
- package/lib-es/bridge/index.js.map +1 -1
- package/lib-es/bridge/validateAddress.d.ts +3 -0
- package/lib-es/bridge/validateAddress.d.ts.map +1 -0
- package/lib-es/bridge/validateAddress.js +6 -0
- package/lib-es/bridge/validateAddress.js.map +1 -0
- 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/bridge/index.ts +2 -0
- package/src/bridge/validateAddress.test.ts +31 -0
- package/src/bridge/validateAddress.ts +10 -0
- 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/tsconfig.json +17 -12
package/src/api/index.test.ts
CHANGED
|
@@ -21,10 +21,13 @@ describe("createApi", () => {
|
|
|
21
21
|
expect(api.combine).toBeInstanceOf(Function);
|
|
22
22
|
expect(api.craftTransaction).toBeInstanceOf(Function);
|
|
23
23
|
expect(api.estimateFees).toBeInstanceOf(Function);
|
|
24
|
+
expect(api.getAssetFromToken).toBeInstanceOf(Function);
|
|
24
25
|
expect(api.getBalance).toBeInstanceOf(Function);
|
|
26
|
+
expect(api.getBlock).toBeInstanceOf(Function);
|
|
27
|
+
expect(api.getBlockInfo).toBeInstanceOf(Function);
|
|
28
|
+
expect(api.getTokenFromAsset).toBeInstanceOf(Function);
|
|
29
|
+
expect(api.getValidators).toBeInstanceOf(Function);
|
|
25
30
|
expect(api.lastBlock).toBeInstanceOf(Function);
|
|
26
31
|
expect(api.listOperations).toBeInstanceOf(Function);
|
|
27
|
-
expect(api.getAssetFromToken).toBeInstanceOf(Function);
|
|
28
|
-
expect(api.getTokenFromAsset).toBeInstanceOf(Function);
|
|
29
32
|
});
|
|
30
33
|
});
|
package/src/api/index.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Api,
|
|
3
3
|
CraftedTransaction,
|
|
4
|
-
Cursor,
|
|
5
4
|
Operation,
|
|
6
5
|
Page,
|
|
7
6
|
Reward,
|
|
8
7
|
Stake,
|
|
9
8
|
TransactionValidation,
|
|
10
|
-
Validator,
|
|
11
9
|
} from "@ledgerhq/coin-framework/api/index";
|
|
12
10
|
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
|
|
13
11
|
import coinConfig from "../config";
|
|
@@ -24,6 +22,7 @@ import {
|
|
|
24
22
|
getAssetFromToken,
|
|
25
23
|
getTokenFromAsset,
|
|
26
24
|
lastBlock,
|
|
25
|
+
getValidators,
|
|
27
26
|
} from "../logic/index";
|
|
28
27
|
import { mapIntentToSDKOperation, getOperationValue } from "../logic/utils";
|
|
29
28
|
import { apiClient } from "../network/api";
|
|
@@ -116,6 +115,9 @@ export function createApi(config: Record<string, never>): Api<HederaMemo> {
|
|
|
116
115
|
...liveOp.extra,
|
|
117
116
|
ledgerOpType: liveOp.type,
|
|
118
117
|
...(asset.type !== "native" && { assetAmount: liveOp.value.toFixed(0) }),
|
|
118
|
+
...(liveOp.extra.stakedAmount && {
|
|
119
|
+
stakedAmount: BigInt(liveOp.extra.stakedAmount.toFixed(0)),
|
|
120
|
+
}),
|
|
119
121
|
},
|
|
120
122
|
tx: {
|
|
121
123
|
hash: liveOp.hash,
|
|
@@ -133,6 +135,7 @@ export function createApi(config: Record<string, never>): Api<HederaMemo> {
|
|
|
133
135
|
},
|
|
134
136
|
getTokenFromAsset: asset => getTokenFromAsset(currency, asset),
|
|
135
137
|
getAssetFromToken,
|
|
138
|
+
getValidators: cursor => getValidators(cursor),
|
|
136
139
|
validateIntent: async (_transactionIntent, _customFees): Promise<TransactionValidation> => {
|
|
137
140
|
throw new Error("validateIntent is not supported");
|
|
138
141
|
},
|
|
@@ -145,8 +148,5 @@ export function createApi(config: Record<string, never>): Api<HederaMemo> {
|
|
|
145
148
|
getRewards: async (_address, _cursor): Promise<Page<Reward>> => {
|
|
146
149
|
throw new Error("getRewards is not supported");
|
|
147
150
|
},
|
|
148
|
-
getValidators(_cursor?: Cursor): Promise<Page<Validator>> {
|
|
149
|
-
throw new Error("getValidators is not supported");
|
|
150
|
-
},
|
|
151
151
|
};
|
|
152
152
|
}
|
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/bridge/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { getAccountShape, buildIterateResult, postSync } from "./synchronisation
|
|
|
19
19
|
import { assignFromAccountRaw, assignToAccountRaw } from "./serialization";
|
|
20
20
|
import resolver from "../signer/index";
|
|
21
21
|
import type { Transaction, TransactionStatus, HederaSigner, HederaAccount } from "../types";
|
|
22
|
+
import { validateAddress } from "./validateAddress";
|
|
22
23
|
|
|
23
24
|
function buildCurrencyBridge(signerContext: SignerContext<HederaSigner>): CurrencyBridge {
|
|
24
25
|
const getAddress = resolver(signerContext);
|
|
@@ -62,6 +63,7 @@ function buildAccountBridge(
|
|
|
62
63
|
},
|
|
63
64
|
broadcast,
|
|
64
65
|
getSerializedAddressParameters,
|
|
66
|
+
validateAddress,
|
|
65
67
|
};
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { safeParseAccountId } from "../logic/utils";
|
|
2
|
+
import { validateAddress } from "./validateAddress";
|
|
3
|
+
|
|
4
|
+
jest.mock("../logic/utils");
|
|
5
|
+
|
|
6
|
+
describe("validateAddress", () => {
|
|
7
|
+
const mockedSafeParseAccountId = jest.mocked(safeParseAccountId);
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockedSafeParseAccountId.mockClear();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it.each([true, false])(
|
|
14
|
+
"should call safeParseAccountId and return expected value (%s)",
|
|
15
|
+
async (expectedValue: boolean) => {
|
|
16
|
+
if (expectedValue) {
|
|
17
|
+
mockedSafeParseAccountId.mockReturnValueOnce([null, { accountId: "", checksum: "" }]);
|
|
18
|
+
} else {
|
|
19
|
+
mockedSafeParseAccountId.mockReturnValueOnce([new Error(), null]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const address = "some random address";
|
|
23
|
+
const parameters = {};
|
|
24
|
+
const result = await validateAddress(address, parameters);
|
|
25
|
+
expect(result).toEqual(expectedValue);
|
|
26
|
+
|
|
27
|
+
expect(mockedSafeParseAccountId).toHaveBeenCalledTimes(1);
|
|
28
|
+
expect(mockedSafeParseAccountId).toHaveBeenCalledWith(address);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AddressValidationCurrencyParameters } from "@ledgerhq/types-live";
|
|
2
|
+
import { safeParseAccountId } from "../logic/utils";
|
|
3
|
+
|
|
4
|
+
export async function validateAddress(
|
|
5
|
+
address: string,
|
|
6
|
+
_parameters: Partial<AddressValidationCurrencyParameters>,
|
|
7
|
+
): Promise<boolean> {
|
|
8
|
+
const [error] = safeParseAccountId(address);
|
|
9
|
+
return error === null;
|
|
10
|
+
}
|
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
|
+
};
|