@ledgerhq/coin-hedera 1.15.0-nightly.20251126023856 → 1.15.0-nightly.20251127023715

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 (280) hide show
  1. package/CHANGELOG.md +10 -8
  2. package/lib/api/index.d.ts.map +1 -1
  3. package/lib/api/index.js +6 -2
  4. package/lib/api/index.js.map +1 -1
  5. package/lib/bridge/broadcast.js +1 -1
  6. package/lib/bridge/broadcast.js.map +1 -1
  7. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
  8. package/lib/bridge/buildOptimisticOperation.js +80 -15
  9. package/lib/bridge/buildOptimisticOperation.js.map +1 -1
  10. package/lib/bridge/estimateMaxSpendable.js +5 -2
  11. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  12. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  13. package/lib/bridge/getTransactionStatus.js +70 -13
  14. package/lib/bridge/getTransactionStatus.js.map +1 -1
  15. package/lib/bridge/index.js +1 -1
  16. package/lib/bridge/index.js.map +1 -1
  17. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  18. package/lib/bridge/prepareTransaction.js +40 -7
  19. package/lib/bridge/prepareTransaction.js.map +1 -1
  20. package/lib/bridge/signOperation.d.ts.map +1 -1
  21. package/lib/bridge/signOperation.js +19 -2
  22. package/lib/bridge/signOperation.js.map +1 -1
  23. package/lib/bridge/synchronisation.d.ts +2 -0
  24. package/lib/bridge/synchronisation.d.ts.map +1 -1
  25. package/lib/bridge/synchronisation.js +101 -30
  26. package/lib/bridge/synchronisation.js.map +1 -1
  27. package/lib/bridge/utils.d.ts +35 -2
  28. package/lib/bridge/utils.d.ts.map +1 -1
  29. package/lib/bridge/utils.js +215 -16
  30. package/lib/bridge/utils.js.map +1 -1
  31. package/lib/constants.d.ts +22 -2
  32. package/lib/constants.d.ts.map +1 -1
  33. package/lib/constants.js +42 -2
  34. package/lib/constants.js.map +1 -1
  35. package/lib/deviceTransactionConfig.d.ts +1 -1
  36. package/lib/deviceTransactionConfig.d.ts.map +1 -1
  37. package/lib/deviceTransactionConfig.js +8 -0
  38. package/lib/deviceTransactionConfig.js.map +1 -1
  39. package/lib/errors.d.ts +3 -0
  40. package/lib/errors.d.ts.map +1 -1
  41. package/lib/errors.js +2 -1
  42. package/lib/errors.js.map +1 -1
  43. package/lib/logic/craftTransaction.d.ts +4 -4
  44. package/lib/logic/craftTransaction.d.ts.map +1 -1
  45. package/lib/logic/craftTransaction.js +46 -5
  46. package/lib/logic/craftTransaction.js.map +1 -1
  47. package/lib/logic/estimateFees.d.ts +2 -4
  48. package/lib/logic/estimateFees.d.ts.map +1 -1
  49. package/lib/logic/estimateFees.js +45 -5
  50. package/lib/logic/estimateFees.js.map +1 -1
  51. package/lib/logic/listOperations.d.ts.map +1 -1
  52. package/lib/logic/listOperations.js +7 -3
  53. package/lib/logic/listOperations.js.map +1 -1
  54. package/lib/logic/utils.d.ts +24 -2
  55. package/lib/logic/utils.d.ts.map +1 -1
  56. package/lib/logic/utils.js +66 -13
  57. package/lib/logic/utils.js.map +1 -1
  58. package/lib/network/api.d.ts +12 -1
  59. package/lib/network/api.d.ts.map +1 -1
  60. package/lib/network/api.js +91 -19
  61. package/lib/network/api.js.map +1 -1
  62. package/lib/network/rpc.d.ts.map +1 -1
  63. package/lib/network/rpc.js +1 -0
  64. package/lib/network/rpc.js.map +1 -1
  65. package/lib/network/thirdweb.d.ts +21 -0
  66. package/lib/network/thirdweb.d.ts.map +1 -0
  67. package/lib/network/thirdweb.js +72 -0
  68. package/lib/network/thirdweb.js.map +1 -0
  69. package/lib/network/utils.d.ts +4 -1
  70. package/lib/network/utils.d.ts.map +1 -1
  71. package/lib/network/utils.js +53 -1
  72. package/lib/network/utils.js.map +1 -1
  73. package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
  74. package/lib/test/bridgeDatasetTest.js +4 -4
  75. package/lib/test/bridgeDatasetTest.js.map +1 -1
  76. package/lib/test/fixtures/account.fixture.js +1 -1
  77. package/lib/test/fixtures/account.fixture.js.map +1 -1
  78. package/lib/test/fixtures/common.fixture.d.ts +12 -0
  79. package/lib/test/fixtures/common.fixture.d.ts.map +1 -0
  80. package/lib/test/fixtures/common.fixture.js +66 -0
  81. package/lib/test/fixtures/common.fixture.js.map +1 -0
  82. package/lib/test/fixtures/currency.fixture.d.ts +3 -1
  83. package/lib/test/fixtures/currency.fixture.d.ts.map +1 -1
  84. package/lib/test/fixtures/currency.fixture.js +63 -16
  85. package/lib/test/fixtures/currency.fixture.js.map +1 -1
  86. package/lib/test/fixtures/mirror.fixture.d.ts +3 -1
  87. package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -1
  88. package/lib/test/fixtures/mirror.fixture.js +12 -1
  89. package/lib/test/fixtures/mirror.fixture.js.map +1 -1
  90. package/lib/test/fixtures/thirdweb.fixture.d.ts +3 -0
  91. package/lib/test/fixtures/thirdweb.fixture.d.ts.map +1 -0
  92. package/lib/test/fixtures/thirdweb.fixture.js +34 -0
  93. package/lib/test/fixtures/thirdweb.fixture.js.map +1 -0
  94. package/lib/transaction.d.ts.map +1 -1
  95. package/lib/transaction.js +2 -0
  96. package/lib/transaction.js.map +1 -1
  97. package/lib/types/alpaca.d.ts +5 -1
  98. package/lib/types/alpaca.d.ts.map +1 -1
  99. package/lib/types/bridge.d.ts +6 -1
  100. package/lib/types/bridge.d.ts.map +1 -1
  101. package/lib/types/index.d.ts +2 -0
  102. package/lib/types/index.d.ts.map +1 -1
  103. package/lib/types/index.js +2 -0
  104. package/lib/types/index.js.map +1 -1
  105. package/lib/types/logic.d.ts +39 -0
  106. package/lib/types/logic.d.ts.map +1 -0
  107. package/lib/types/logic.js +3 -0
  108. package/lib/types/logic.js.map +1 -0
  109. package/lib/types/mirror.d.ts +29 -0
  110. package/lib/types/mirror.d.ts.map +1 -1
  111. package/lib/types/thirdweb.d.ts +34 -0
  112. package/lib/types/thirdweb.d.ts.map +1 -0
  113. package/lib/types/thirdweb.js +3 -0
  114. package/lib/types/thirdweb.js.map +1 -0
  115. package/lib-es/api/index.d.ts.map +1 -1
  116. package/lib-es/api/index.js +7 -3
  117. package/lib-es/api/index.js.map +1 -1
  118. package/lib-es/bridge/broadcast.js +2 -2
  119. package/lib-es/bridge/broadcast.js.map +1 -1
  120. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
  121. package/lib-es/bridge/buildOptimisticOperation.js +83 -18
  122. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
  123. package/lib-es/bridge/estimateMaxSpendable.js +5 -2
  124. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  125. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  126. package/lib-es/bridge/getTransactionStatus.js +73 -16
  127. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  128. package/lib-es/bridge/index.js +2 -2
  129. package/lib-es/bridge/index.js.map +1 -1
  130. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  131. package/lib-es/bridge/prepareTransaction.js +42 -9
  132. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  133. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  134. package/lib-es/bridge/signOperation.js +21 -4
  135. package/lib-es/bridge/signOperation.js.map +1 -1
  136. package/lib-es/bridge/synchronisation.d.ts +2 -0
  137. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  138. package/lib-es/bridge/synchronisation.js +97 -27
  139. package/lib-es/bridge/synchronisation.js.map +1 -1
  140. package/lib-es/bridge/utils.d.ts +35 -2
  141. package/lib-es/bridge/utils.d.ts.map +1 -1
  142. package/lib-es/bridge/utils.js +211 -16
  143. package/lib-es/bridge/utils.js.map +1 -1
  144. package/lib-es/constants.d.ts +22 -2
  145. package/lib-es/constants.d.ts.map +1 -1
  146. package/lib-es/constants.js +38 -1
  147. package/lib-es/constants.js.map +1 -1
  148. package/lib-es/deviceTransactionConfig.d.ts +1 -1
  149. package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
  150. package/lib-es/deviceTransactionConfig.js +8 -0
  151. package/lib-es/deviceTransactionConfig.js.map +1 -1
  152. package/lib-es/errors.d.ts +3 -0
  153. package/lib-es/errors.d.ts.map +1 -1
  154. package/lib-es/errors.js +1 -0
  155. package/lib-es/errors.js.map +1 -1
  156. package/lib-es/logic/craftTransaction.d.ts +4 -4
  157. package/lib-es/logic/craftTransaction.d.ts.map +1 -1
  158. package/lib-es/logic/craftTransaction.js +48 -7
  159. package/lib-es/logic/craftTransaction.js.map +1 -1
  160. package/lib-es/logic/estimateFees.d.ts +2 -4
  161. package/lib-es/logic/estimateFees.d.ts.map +1 -1
  162. package/lib-es/logic/estimateFees.js +47 -7
  163. package/lib-es/logic/estimateFees.js.map +1 -1
  164. package/lib-es/logic/listOperations.d.ts.map +1 -1
  165. package/lib-es/logic/listOperations.js +7 -3
  166. package/lib-es/logic/listOperations.js.map +1 -1
  167. package/lib-es/logic/utils.d.ts +24 -2
  168. package/lib-es/logic/utils.d.ts.map +1 -1
  169. package/lib-es/logic/utils.js +63 -13
  170. package/lib-es/logic/utils.js.map +1 -1
  171. package/lib-es/network/api.d.ts +12 -1
  172. package/lib-es/network/api.d.ts.map +1 -1
  173. package/lib-es/network/api.js +91 -19
  174. package/lib-es/network/api.js.map +1 -1
  175. package/lib-es/network/rpc.d.ts.map +1 -1
  176. package/lib-es/network/rpc.js +1 -0
  177. package/lib-es/network/rpc.js.map +1 -1
  178. package/lib-es/network/thirdweb.d.ts +21 -0
  179. package/lib-es/network/thirdweb.d.ts.map +1 -0
  180. package/lib-es/network/thirdweb.js +66 -0
  181. package/lib-es/network/thirdweb.js.map +1 -0
  182. package/lib-es/network/utils.d.ts +4 -1
  183. package/lib-es/network/utils.d.ts.map +1 -1
  184. package/lib-es/network/utils.js +49 -0
  185. package/lib-es/network/utils.js.map +1 -1
  186. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
  187. package/lib-es/test/bridgeDatasetTest.js +4 -4
  188. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  189. package/lib-es/test/fixtures/account.fixture.js +2 -2
  190. package/lib-es/test/fixtures/account.fixture.js.map +1 -1
  191. package/lib-es/test/fixtures/common.fixture.d.ts +12 -0
  192. package/lib-es/test/fixtures/common.fixture.d.ts.map +1 -0
  193. package/lib-es/test/fixtures/common.fixture.js +57 -0
  194. package/lib-es/test/fixtures/common.fixture.js.map +1 -0
  195. package/lib-es/test/fixtures/currency.fixture.d.ts +3 -1
  196. package/lib-es/test/fixtures/currency.fixture.d.ts.map +1 -1
  197. package/lib-es/test/fixtures/currency.fixture.js +59 -14
  198. package/lib-es/test/fixtures/currency.fixture.js.map +1 -1
  199. package/lib-es/test/fixtures/mirror.fixture.d.ts +3 -1
  200. package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -1
  201. package/lib-es/test/fixtures/mirror.fixture.js +9 -0
  202. package/lib-es/test/fixtures/mirror.fixture.js.map +1 -1
  203. package/lib-es/test/fixtures/thirdweb.fixture.d.ts +3 -0
  204. package/lib-es/test/fixtures/thirdweb.fixture.d.ts.map +1 -0
  205. package/lib-es/test/fixtures/thirdweb.fixture.js +30 -0
  206. package/lib-es/test/fixtures/thirdweb.fixture.js.map +1 -0
  207. package/lib-es/transaction.d.ts.map +1 -1
  208. package/lib-es/transaction.js +2 -0
  209. package/lib-es/transaction.js.map +1 -1
  210. package/lib-es/types/alpaca.d.ts +5 -1
  211. package/lib-es/types/alpaca.d.ts.map +1 -1
  212. package/lib-es/types/bridge.d.ts +6 -1
  213. package/lib-es/types/bridge.d.ts.map +1 -1
  214. package/lib-es/types/index.d.ts +2 -0
  215. package/lib-es/types/index.d.ts.map +1 -1
  216. package/lib-es/types/index.js +2 -0
  217. package/lib-es/types/index.js.map +1 -1
  218. package/lib-es/types/logic.d.ts +39 -0
  219. package/lib-es/types/logic.d.ts.map +1 -0
  220. package/lib-es/types/logic.js +2 -0
  221. package/lib-es/types/logic.js.map +1 -0
  222. package/lib-es/types/mirror.d.ts +29 -0
  223. package/lib-es/types/mirror.d.ts.map +1 -1
  224. package/lib-es/types/thirdweb.d.ts +34 -0
  225. package/lib-es/types/thirdweb.d.ts.map +1 -0
  226. package/lib-es/types/thirdweb.js +2 -0
  227. package/lib-es/types/thirdweb.js.map +1 -0
  228. package/package.json +9 -8
  229. package/src/api/index.integ.test.ts +11 -8
  230. package/src/api/index.ts +10 -3
  231. package/src/bridge/broadcast.ts +2 -2
  232. package/src/bridge/buildOptimisticOperation.integration.test.ts +70 -19
  233. package/src/bridge/buildOptimisticOperation.ts +98 -20
  234. package/src/bridge/estimateMaxSpendable.ts +5 -5
  235. package/src/bridge/getTransactionStatus.test.ts +57 -12
  236. package/src/bridge/getTransactionStatus.ts +88 -15
  237. package/src/bridge/index.ts +2 -2
  238. package/src/bridge/js-estimateMaxSpendable.integration.test.ts +12 -9
  239. package/src/bridge/prepareTransaction.test.ts +3 -1
  240. package/src/bridge/prepareTransaction.ts +45 -10
  241. package/src/bridge/signOperation.ts +23 -5
  242. package/src/bridge/synchronisation.test.ts +67 -0
  243. package/src/bridge/synchronisation.ts +114 -34
  244. package/src/bridge/utils.integration.test.ts +486 -180
  245. package/src/bridge/utils.test.ts +404 -0
  246. package/src/bridge/utils.ts +330 -27
  247. package/src/constants.ts +47 -2
  248. package/src/deviceTransactionConfig.ts +10 -1
  249. package/src/errors.ts +3 -0
  250. package/src/logic/craftTransaction.test.ts +49 -9
  251. package/src/logic/craftTransaction.ts +76 -11
  252. package/src/logic/estimateFees.test.ts +180 -31
  253. package/src/logic/estimateFees.ts +68 -7
  254. package/src/logic/getAssetFromToken.test.ts +2 -2
  255. package/src/logic/getBalance.test.ts +18 -57
  256. package/src/logic/getTokenFromAsset.test.ts +2 -2
  257. package/src/logic/listOperations.ts +9 -5
  258. package/src/logic/utils.test.ts +157 -69
  259. package/src/logic/utils.ts +75 -13
  260. package/src/network/api.test.ts +211 -3
  261. package/src/network/api.ts +118 -24
  262. package/src/network/rpc.test.ts +1 -0
  263. package/src/network/rpc.ts +1 -0
  264. package/src/network/thirdweb.test.ts +188 -0
  265. package/src/network/thirdweb.ts +101 -0
  266. package/src/network/utils.test.ts +364 -164
  267. package/src/network/utils.ts +83 -1
  268. package/src/test/bridgeDatasetTest.ts +4 -5
  269. package/src/test/fixtures/account.fixture.ts +2 -2
  270. package/src/test/fixtures/common.fixture.ts +74 -0
  271. package/src/test/fixtures/currency.fixture.ts +66 -14
  272. package/src/test/fixtures/mirror.fixture.ts +23 -1
  273. package/src/test/fixtures/thirdweb.fixture.ts +33 -0
  274. package/src/transaction.ts +2 -0
  275. package/src/types/alpaca.ts +8 -1
  276. package/src/types/bridge.ts +6 -1
  277. package/src/types/index.ts +2 -0
  278. package/src/types/logic.ts +44 -0
  279. package/src/types/mirror.ts +35 -0
  280. package/src/types/thirdweb.ts +36 -0
@@ -8,18 +8,29 @@ import type {
8
8
  } from "@ledgerhq/coin-framework/bridge/jsHelpers";
9
9
  import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
10
10
  import { encodeAccountId, getSyncHash } from "@ledgerhq/coin-framework/account";
11
- import { listOperations } from "../logic/listOperations";
11
+ import type { Account, Operation } from "@ledgerhq/types-live";
12
+ import { toEVMAddress } from "../logic/utils";
13
+ import { listOperations } from "../logic";
12
14
  import { apiClient } from "../network/api";
15
+ import { thirdwebClient } from "../network/thirdweb";
16
+ import { getERC20BalancesForAccount } from "../network/utils";
13
17
  import type { HederaAccount } from "../types";
14
- import { getSubAccounts, prepareOperations, applyPendingExtras, mergeSubAccounts } from "./utils";
18
+ import {
19
+ getSubAccounts,
20
+ prepareOperations,
21
+ applyPendingExtras,
22
+ mergeSubAccounts,
23
+ integrateERC20Operations,
24
+ } from "./utils";
15
25
 
16
26
  export const getAccountShape: GetAccountShape<HederaAccount> = async (
17
27
  info,
18
28
  { blacklistedTokenIds },
19
29
  ): Promise<Partial<HederaAccount>> => {
20
30
  const { currency, derivationMode, address, initialAccount } = info;
21
-
22
- invariant(address, "an hedera address is expected");
31
+ invariant(address, "hedera: address is expected");
32
+ const evmAddress = toEVMAddress(address);
33
+ invariant(evmAddress, "hedera: evm address is missing");
23
34
 
24
35
  const liveAccountId = encodeAccountId({
25
36
  type: "js",
@@ -32,9 +43,10 @@ export const getAccountShape: GetAccountShape<HederaAccount> = async (
32
43
  // get current account balance and tokens
33
44
  // tokens are fetched with separate requests to get "created_timestamp" for each token
34
45
  // based on this, ASSOCIATE_TOKEN operations can be connected with tokens
35
- const [mirrorAccount, mirrorTokens] = await Promise.all([
46
+ const [mirrorAccount, mirrorTokens, erc20TokenBalances] = await Promise.all([
36
47
  apiClient.getAccount(address),
37
48
  apiClient.getAccountTokens(address),
49
+ getERC20BalancesForAccount(evmAddress),
38
50
  ]);
39
51
 
40
52
  const accountBalance = new BigNumber(mirrorAccount.balance.balance);
@@ -44,35 +56,49 @@ export const getAccountShape: GetAccountShape<HederaAccount> = async (
44
56
  const syncHash = await getSyncHash(currency.id, blacklistedTokenIds);
45
57
  const shouldSyncFromScratch = !initialAccount || syncHash !== initialAccount?.syncHash;
46
58
 
47
- const oldOperations = initialAccount?.operations ?? [];
48
- const pendingOperations = initialAccount?.pendingOperations ?? [];
49
-
50
- // grab latest operation's consensus timestamp for incremental sync
59
+ const pendingOperations = shouldSyncFromScratch ? [] : initialAccount?.pendingOperations ?? [];
60
+ const oldOperations = shouldSyncFromScratch ? [] : initialAccount?.operations ?? [];
61
+ const oldERC20Operations = oldOperations.filter(item => item.standard === "erc20");
51
62
  const latestOperation = oldOperations[0];
52
- const latestOperationTimestamp =
53
- !shouldSyncFromScratch && latestOperation
54
- ? new BigNumber(Math.floor(latestOperation.date.getTime() / 1000))
55
- : null;
56
- const latestAccountOperations = await listOperations({
57
- currency,
58
- address,
59
- mirrorTokens,
60
- pagination: {
61
- minHeight: 0,
62
- ...(latestOperationTimestamp && { lastPagingToken: latestOperationTimestamp.toString() }),
63
- },
64
- fetchAllPages: true,
65
- skipFeesForTokenOperations: false,
66
- useEncodedHash: true,
67
- useSyntheticBlocks: false,
68
- });
63
+ const erc20LatestOperation = oldERC20Operations[0];
64
+ const pendingOperationHashes = new Set(pendingOperations.map(op => op.hash));
65
+ const erc20OperationHashes = new Set(oldERC20Operations.map(op => op.hash));
66
+
67
+ // grab latest operation timestamps for incremental sync
68
+ let latestOperationTimestamp: string | null = null;
69
+ let erc20LatestOperationTimestamp: string | null = null;
70
+
71
+ if (!shouldSyncFromScratch && latestOperation) {
72
+ const timestamp = Math.floor(latestOperation.date.getTime() / 1000);
73
+ latestOperationTimestamp = new BigNumber(timestamp).toString();
74
+ }
75
+
76
+ if (!shouldSyncFromScratch && erc20LatestOperation) {
77
+ const timestamp = Math.floor(erc20LatestOperation.date.getTime() / 1000);
78
+ erc20LatestOperationTimestamp = new BigNumber(timestamp).toString();
79
+ }
80
+
81
+ const [latestAccountOperations, erc20Transactions] = await Promise.all([
82
+ listOperations({
83
+ currency,
84
+ address,
85
+ mirrorTokens,
86
+ pagination: {
87
+ minHeight: 0,
88
+ ...(latestOperationTimestamp && { lastPagingToken: latestOperationTimestamp.toString() }),
89
+ },
90
+ fetchAllPages: true,
91
+ skipFeesForTokenOperations: false,
92
+ useEncodedHash: true,
93
+ useSyntheticBlocks: false,
94
+ }),
95
+ thirdwebClient.getERC20TransactionsForAccount({
96
+ address,
97
+ contractAddresses: erc20TokenBalances.map(token => token.token.contractAddress),
98
+ since: erc20LatestOperationTimestamp,
99
+ }),
100
+ ]);
69
101
 
70
- const newSubAccounts = await getSubAccounts(
71
- liveAccountId,
72
- latestAccountOperations.tokenOperations,
73
- mirrorTokens,
74
- );
75
- const subAccounts = mergeSubAccounts(initialAccount, newSubAccounts);
76
102
  const newOperations = await prepareOperations(
77
103
  latestAccountOperations.coinOperations,
78
104
  latestAccountOperations.tokenOperations,
@@ -82,6 +108,41 @@ export const getAccountShape: GetAccountShape<HederaAccount> = async (
82
108
  ? enrichedNewOperations
83
109
  : mergeOps(oldOperations, enrichedNewOperations);
84
110
 
111
+ // how ERC20 operations are handled:
112
+ // - mirror node doesn't include "IN" erc20 token transactions
113
+ // - mirror node returns "CONTRACT_CALL" (OUT) erc20 token transactions made from given account address
114
+ // - mirror node doesn't return "CONTRACT_CALL" (OUT) erc20 token transactions made from 3rd party with allowance
115
+ //
116
+ // 1. mirror node transactions are already transformed into operations at this point + we have raw erc20 transactions fetched from thirdweb
117
+ // 2. related mirror node transaction must be fetched for each erc20 transaction (to get fee and consensus timestamp)
118
+ // 3. CONTRACTCALL operations must be removed if existing operations already include erc20 operation with the same tx.hash
119
+ // 4. ERC20 transactions must be classified into two groups: patchList and addList
120
+ // - patchList: transactions which are already present in mirror operations (we can have CONTRACT_CALL from mirror node that we can transform into "FEES")
121
+ // - addList should include transactions which are missing in mirror operations (e.g. "IN" erc20 token transaction and "OUT" made by 3rd party with allowance)
122
+ // 5. list of all operations must be updated based on prepared `patchList` and `addList`
123
+ // 6. sub accounts must get erc20 tokens and erc20 operations in addition to hts tokens and hts operations
124
+ // 7. postSync must remove pending operations that are already confirmed as erc20 operations
125
+ const { updatedOperations, newERC20TokenOperations } = await integrateERC20Operations({
126
+ ledgerAccountId: liveAccountId,
127
+ address,
128
+ allOperations: operations,
129
+ latestERC20Transactions: erc20Transactions,
130
+ pendingOperationHashes,
131
+ erc20OperationHashes,
132
+ });
133
+
134
+ const newSubAccounts = await getSubAccounts({
135
+ ledgerAccountId: liveAccountId,
136
+ latestHTSTokenOperations: latestAccountOperations.tokenOperations,
137
+ latestERC20TokenOperations: newERC20TokenOperations,
138
+ mirrorTokens,
139
+ erc20Tokens: erc20TokenBalances,
140
+ });
141
+
142
+ const subAccounts = shouldSyncFromScratch
143
+ ? newSubAccounts
144
+ : mergeSubAccounts(initialAccount, newSubAccounts);
145
+
85
146
  return {
86
147
  id: liveAccountId,
87
148
  freshAddress: address,
@@ -89,8 +150,8 @@ export const getAccountShape: GetAccountShape<HederaAccount> = async (
89
150
  lastSyncDate: new Date(),
90
151
  balance: accountBalance,
91
152
  spendableBalance: accountBalance,
92
- operations,
93
- operationsCount: operations.length,
153
+ operations: updatedOperations,
154
+ operationsCount: updatedOperations.length,
94
155
  // NOTE: there are no "blocks" in hedera
95
156
  // Set a value just so that operations are considered confirmed according to isConfirmedOperation
96
157
  blockHeight: 10,
@@ -124,3 +185,22 @@ export const buildIterateResult: IterateResultBuilder = async ({ result: rootRes
124
185
  : null;
125
186
  };
126
187
  };
188
+
189
+ // it might be necessary to remove pending operations after ERC20 patching done by `integrateERC20Operations`
190
+ export const postSync = (_initial: Account, synced: Account): Account => {
191
+ const erc20Operations = synced.operations.filter(op => op.standard === "erc20");
192
+ const erc20Hashes = new Set(erc20Operations.map(op => op.hash));
193
+
194
+ const excludeConfirmedERC20Operations = (o: Operation) => !erc20Hashes.has(o.hash);
195
+
196
+ return {
197
+ ...synced,
198
+ pendingOperations: synced.pendingOperations.filter(excludeConfirmedERC20Operations),
199
+ subAccounts: (synced.subAccounts ?? []).map(subAccount => {
200
+ return {
201
+ ...subAccount,
202
+ pendingOperations: subAccount.pendingOperations.filter(excludeConfirmedERC20Operations),
203
+ };
204
+ }),
205
+ };
206
+ };