@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.
Files changed (149) hide show
  1. package/CHANGELOG.md +14 -10
  2. package/lib/api/index.d.ts.map +1 -1
  3. package/lib/api/index.js +4 -3
  4. package/lib/api/index.js.map +1 -1
  5. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
  6. package/lib/bridge/buildOptimisticOperation.js +14 -43
  7. package/lib/bridge/buildOptimisticOperation.js.map +1 -1
  8. package/lib/bridge/index.d.ts.map +1 -1
  9. package/lib/bridge/index.js +2 -0
  10. package/lib/bridge/index.js.map +1 -1
  11. package/lib/bridge/validateAddress.d.ts +3 -0
  12. package/lib/bridge/validateAddress.d.ts.map +1 -0
  13. package/lib/bridge/validateAddress.js +10 -0
  14. package/lib/bridge/validateAddress.js.map +1 -0
  15. package/lib/constants.d.ts +11 -6
  16. package/lib/constants.d.ts.map +1 -1
  17. package/lib/constants.js +20 -1
  18. package/lib/constants.js.map +1 -1
  19. package/lib/deviceTransactionConfig.d.ts.map +1 -1
  20. package/lib/deviceTransactionConfig.js +1 -3
  21. package/lib/deviceTransactionConfig.js.map +1 -1
  22. package/lib/logic/getBalance.d.ts.map +1 -1
  23. package/lib/logic/getBalance.js +21 -4
  24. package/lib/logic/getBalance.js.map +1 -1
  25. package/lib/logic/getBlock.d.ts.map +1 -1
  26. package/lib/logic/getBlock.js +39 -2
  27. package/lib/logic/getBlock.js.map +1 -1
  28. package/lib/logic/getValidators.d.ts +3 -0
  29. package/lib/logic/getValidators.d.ts.map +1 -0
  30. package/lib/logic/getValidators.js +24 -0
  31. package/lib/logic/getValidators.js.map +1 -0
  32. package/lib/logic/index.d.ts +1 -0
  33. package/lib/logic/index.d.ts.map +1 -1
  34. package/lib/logic/index.js +3 -1
  35. package/lib/logic/index.js.map +1 -1
  36. package/lib/logic/listOperations.d.ts.map +1 -1
  37. package/lib/logic/listOperations.js +16 -2
  38. package/lib/logic/listOperations.js.map +1 -1
  39. package/lib/logic/utils.d.ts +17 -1
  40. package/lib/logic/utils.d.ts.map +1 -1
  41. package/lib/logic/utils.js +54 -1
  42. package/lib/logic/utils.js.map +1 -1
  43. package/lib/network/api.d.ts +22 -2
  44. package/lib/network/api.d.ts.map +1 -1
  45. package/lib/network/api.js +49 -14
  46. package/lib/network/api.js.map +1 -1
  47. package/lib/preload.js +2 -2
  48. package/lib/preload.js.map +1 -1
  49. package/lib/test/fixtures/account.fixture.d.ts +8 -0
  50. package/lib/test/fixtures/account.fixture.d.ts.map +1 -1
  51. package/lib/test/fixtures/account.fixture.js +8 -0
  52. package/lib/test/fixtures/account.fixture.js.map +1 -1
  53. package/lib/test/fixtures/mirror.fixture.d.ts +2 -1
  54. package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -1
  55. package/lib/test/fixtures/mirror.fixture.js +16 -1
  56. package/lib/test/fixtures/mirror.fixture.js.map +1 -1
  57. package/lib/types/bridge.d.ts +1 -0
  58. package/lib/types/bridge.d.ts.map +1 -1
  59. package/lib/types/logic.d.ts +6 -0
  60. package/lib/types/logic.d.ts.map +1 -1
  61. package/lib-es/api/index.d.ts.map +1 -1
  62. package/lib-es/api/index.js +5 -4
  63. package/lib-es/api/index.js.map +1 -1
  64. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
  65. package/lib-es/bridge/buildOptimisticOperation.js +15 -44
  66. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
  67. package/lib-es/bridge/index.d.ts.map +1 -1
  68. package/lib-es/bridge/index.js +2 -0
  69. package/lib-es/bridge/index.js.map +1 -1
  70. package/lib-es/bridge/validateAddress.d.ts +3 -0
  71. package/lib-es/bridge/validateAddress.d.ts.map +1 -0
  72. package/lib-es/bridge/validateAddress.js +6 -0
  73. package/lib-es/bridge/validateAddress.js.map +1 -0
  74. package/lib-es/constants.d.ts +11 -6
  75. package/lib-es/constants.d.ts.map +1 -1
  76. package/lib-es/constants.js +19 -0
  77. package/lib-es/constants.js.map +1 -1
  78. package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
  79. package/lib-es/deviceTransactionConfig.js +2 -4
  80. package/lib-es/deviceTransactionConfig.js.map +1 -1
  81. package/lib-es/logic/getBalance.d.ts.map +1 -1
  82. package/lib-es/logic/getBalance.js +21 -4
  83. package/lib-es/logic/getBalance.js.map +1 -1
  84. package/lib-es/logic/getBlock.d.ts.map +1 -1
  85. package/lib-es/logic/getBlock.js +40 -3
  86. package/lib-es/logic/getBlock.js.map +1 -1
  87. package/lib-es/logic/getValidators.d.ts +3 -0
  88. package/lib-es/logic/getValidators.d.ts.map +1 -0
  89. package/lib-es/logic/getValidators.js +20 -0
  90. package/lib-es/logic/getValidators.js.map +1 -0
  91. package/lib-es/logic/index.d.ts +1 -0
  92. package/lib-es/logic/index.d.ts.map +1 -1
  93. package/lib-es/logic/index.js +1 -0
  94. package/lib-es/logic/index.js.map +1 -1
  95. package/lib-es/logic/listOperations.d.ts.map +1 -1
  96. package/lib-es/logic/listOperations.js +17 -3
  97. package/lib-es/logic/listOperations.js.map +1 -1
  98. package/lib-es/logic/utils.d.ts +17 -1
  99. package/lib-es/logic/utils.d.ts.map +1 -1
  100. package/lib-es/logic/utils.js +52 -1
  101. package/lib-es/logic/utils.js.map +1 -1
  102. package/lib-es/network/api.d.ts +22 -2
  103. package/lib-es/network/api.d.ts.map +1 -1
  104. package/lib-es/network/api.js +49 -14
  105. package/lib-es/network/api.js.map +1 -1
  106. package/lib-es/preload.js +2 -2
  107. package/lib-es/preload.js.map +1 -1
  108. package/lib-es/test/fixtures/account.fixture.d.ts +8 -0
  109. package/lib-es/test/fixtures/account.fixture.d.ts.map +1 -1
  110. package/lib-es/test/fixtures/account.fixture.js +8 -0
  111. package/lib-es/test/fixtures/account.fixture.js.map +1 -1
  112. package/lib-es/test/fixtures/mirror.fixture.d.ts +2 -1
  113. package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -1
  114. package/lib-es/test/fixtures/mirror.fixture.js +14 -0
  115. package/lib-es/test/fixtures/mirror.fixture.js.map +1 -1
  116. package/lib-es/types/bridge.d.ts +1 -0
  117. package/lib-es/types/bridge.d.ts.map +1 -1
  118. package/lib-es/types/logic.d.ts +6 -0
  119. package/lib-es/types/logic.d.ts.map +1 -1
  120. package/package.json +10 -10
  121. package/src/api/index.integ.test.ts +226 -1
  122. package/src/api/index.test.ts +5 -2
  123. package/src/api/index.ts +5 -5
  124. package/src/bridge/{buildOptimisticOperation.integration.test.ts → buildOptimisticOperation.test.ts} +23 -68
  125. package/src/bridge/buildOptimisticOperation.ts +16 -45
  126. package/src/bridge/index.ts +2 -0
  127. package/src/bridge/validateAddress.test.ts +31 -0
  128. package/src/bridge/validateAddress.ts +10 -0
  129. package/src/constants.ts +23 -1
  130. package/src/deviceTransactionConfig.test.ts +59 -43
  131. package/src/deviceTransactionConfig.ts +2 -5
  132. package/src/logic/getBalance.test.ts +50 -0
  133. package/src/logic/getBalance.ts +21 -4
  134. package/src/logic/getBlock.test.ts +283 -1
  135. package/src/logic/getBlock.ts +57 -6
  136. package/src/logic/getValidators.test.ts +50 -0
  137. package/src/logic/getValidators.ts +22 -0
  138. package/src/logic/index.ts +1 -0
  139. package/src/logic/listOperations.ts +33 -3
  140. package/src/logic/utils.test.ts +113 -0
  141. package/src/logic/utils.ts +67 -1
  142. package/src/network/api.test.ts +55 -9
  143. package/src/network/api.ts +66 -14
  144. package/src/preload.ts +2 -2
  145. package/src/test/fixtures/account.fixture.ts +8 -0
  146. package/src/test/fixtures/mirror.fixture.ts +18 -0
  147. package/src/types/bridge.ts +1 -0
  148. package/src/types/logic.ts +7 -0
  149. package/tsconfig.json +17 -12
@@ -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
  }
@@ -1,7 +1,6 @@
1
1
  import BigNumber from "bignumber.js";
2
2
  import { buildOptimisticOperation } from "./buildOptimisticOperation";
3
- import { HEDERA_OPERATION_TYPES, HEDERA_TRANSACTION_MODES } from "../constants";
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(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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("UPDATE_ACCOUNT");
163
- expect(op.fee).toEqual(estimatedFee.tinybars);
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("UPDATE_ACCOUNT");
208
- expect(op.fee).toEqual(estimatedFee.tinybars);
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("UPDATE_ACCOUNT");
249
- expect(op.fee).toEqual(estimatedFee.tinybars);
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(estimatedFee.tinybars);
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 { HEDERA_OPERATION_TYPES, HEDERA_TRANSACTION_MODES } from "../constants";
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 estimatedFee = await estimateFees({
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: estimatedFee.tinybars,
35
- fee: estimatedFee.tinybars,
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 estimatedFee =
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: BigNumber.isBigNumber(estimatedFee) ? estimatedFee : estimatedFee.tinybars,
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 estimatedFee = await estimateFees({
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: estimatedFee.tinybars,
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: estimatedFee.tinybars,
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 estimatedFees = await estimateFees({
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: estimatedFees.tinybars,
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: estimatedFees.tinybars,
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 estimatedFee = await estimateFees({
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 = "UPDATE_ACCOUNT";
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: estimatedFee.tinybars,
199
+ fee,
229
200
  blockHash: null,
230
201
  blockHeight: null,
231
202
  senders: [account.freshAddress.toString()],
@@ -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
+ };