@ledgerhq/coin-aptos 2.0.0-nightly.4 → 2.0.0-nightly.5

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 (159) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +9 -0
  3. package/lib/__tests__/api/index.test.js +5 -61
  4. package/lib/__tests__/api/index.test.js.map +1 -1
  5. package/lib/__tests__/bridge/buildTransaction.test.js +2 -57
  6. package/lib/__tests__/bridge/buildTransaction.test.js.map +1 -1
  7. package/lib/__tests__/bridge/getFeesForTransaction.test.js +8 -109
  8. package/lib/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  9. package/lib/__tests__/bridge/getTransactionStatus.test.js +37 -175
  10. package/lib/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  11. package/lib/__tests__/bridge/logic.test.js +115 -889
  12. package/lib/__tests__/bridge/logic.test.js.map +1 -1
  13. package/lib/__tests__/bridge/signOperation.test.js +2 -128
  14. package/lib/__tests__/bridge/signOperation.test.js.map +1 -1
  15. package/lib/__tests__/bridge/synchronisation.test.js +67 -1214
  16. package/lib/__tests__/bridge/synchronisation.test.js.map +1 -1
  17. package/lib/api/graphql/queries.js +6 -6
  18. package/lib/api/graphql/types.d.ts +9 -9
  19. package/lib/api/graphql/types.d.ts.map +1 -1
  20. package/lib/api/index.d.ts +2 -5
  21. package/lib/api/index.d.ts.map +1 -1
  22. package/lib/api/index.js +4 -30
  23. package/lib/api/index.js.map +1 -1
  24. package/lib/bridge/bridge.fixture.d.ts +0 -2
  25. package/lib/bridge/bridge.fixture.d.ts.map +1 -1
  26. package/lib/bridge/bridge.fixture.js +13 -85
  27. package/lib/bridge/bridge.fixture.js.map +1 -1
  28. package/lib/bridge/buildTransaction.d.ts.map +1 -1
  29. package/lib/bridge/buildTransaction.js +3 -29
  30. package/lib/bridge/buildTransaction.js.map +1 -1
  31. package/lib/bridge/estimateMaxSpendable.js +1 -1
  32. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  33. package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
  34. package/lib/bridge/getFeesForTransaction.js +7 -12
  35. package/lib/bridge/getFeesForTransaction.js.map +1 -1
  36. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  37. package/lib/bridge/getTransactionStatus.js +14 -28
  38. package/lib/bridge/getTransactionStatus.js.map +1 -1
  39. package/lib/bridge/logic.d.ts +8 -13
  40. package/lib/bridge/logic.d.ts.map +1 -1
  41. package/lib/bridge/logic.js +54 -152
  42. package/lib/bridge/logic.js.map +1 -1
  43. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  44. package/lib/bridge/prepareTransaction.js +2 -2
  45. package/lib/bridge/prepareTransaction.js.map +1 -1
  46. package/lib/bridge/signOperation.d.ts.map +1 -1
  47. package/lib/bridge/signOperation.js +3 -17
  48. package/lib/bridge/signOperation.js.map +1 -1
  49. package/lib/bridge/synchronisation.d.ts +0 -15
  50. package/lib/bridge/synchronisation.d.ts.map +1 -1
  51. package/lib/bridge/synchronisation.js +4 -127
  52. package/lib/bridge/synchronisation.js.map +1 -1
  53. package/lib/constants.d.ts +1 -5
  54. package/lib/constants.d.ts.map +1 -1
  55. package/lib/constants.js +2 -6
  56. package/lib/constants.js.map +1 -1
  57. package/lib/test/bot-specs.d.ts.map +1 -1
  58. package/lib/test/bot-specs.js +1 -40
  59. package/lib/test/bot-specs.js.map +1 -1
  60. package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
  61. package/lib/test/bridgeDatasetTest.js +62 -43
  62. package/lib/test/bridgeDatasetTest.js.map +1 -1
  63. package/lib/test/speculos-deviceActions.d.ts +0 -1
  64. package/lib/test/speculos-deviceActions.d.ts.map +1 -1
  65. package/lib/test/speculos-deviceActions.js +5 -37
  66. package/lib/test/speculos-deviceActions.js.map +1 -1
  67. package/lib/types/index.d.ts +7 -18
  68. package/lib/types/index.d.ts.map +1 -1
  69. package/lib-es/__tests__/api/index.test.js +5 -61
  70. package/lib-es/__tests__/api/index.test.js.map +1 -1
  71. package/lib-es/__tests__/bridge/buildTransaction.test.js +3 -58
  72. package/lib-es/__tests__/bridge/buildTransaction.test.js.map +1 -1
  73. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js +9 -110
  74. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  75. package/lib-es/__tests__/bridge/getTransactionStatus.test.js +39 -177
  76. package/lib-es/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  77. package/lib-es/__tests__/bridge/logic.test.js +117 -891
  78. package/lib-es/__tests__/bridge/logic.test.js.map +1 -1
  79. package/lib-es/__tests__/bridge/signOperation.test.js +2 -128
  80. package/lib-es/__tests__/bridge/signOperation.test.js.map +1 -1
  81. package/lib-es/__tests__/bridge/synchronisation.test.js +69 -1213
  82. package/lib-es/__tests__/bridge/synchronisation.test.js.map +1 -1
  83. package/lib-es/api/graphql/queries.js +6 -6
  84. package/lib-es/api/graphql/types.d.ts +9 -9
  85. package/lib-es/api/graphql/types.d.ts.map +1 -1
  86. package/lib-es/api/index.d.ts +2 -5
  87. package/lib-es/api/index.d.ts.map +1 -1
  88. package/lib-es/api/index.js +4 -30
  89. package/lib-es/api/index.js.map +1 -1
  90. package/lib-es/bridge/bridge.fixture.d.ts +0 -2
  91. package/lib-es/bridge/bridge.fixture.d.ts.map +1 -1
  92. package/lib-es/bridge/bridge.fixture.js +12 -82
  93. package/lib-es/bridge/bridge.fixture.js.map +1 -1
  94. package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
  95. package/lib-es/bridge/buildTransaction.js +4 -30
  96. package/lib-es/bridge/buildTransaction.js.map +1 -1
  97. package/lib-es/bridge/estimateMaxSpendable.js +1 -1
  98. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  99. package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
  100. package/lib-es/bridge/getFeesForTransaction.js +8 -13
  101. package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
  102. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  103. package/lib-es/bridge/getTransactionStatus.js +14 -28
  104. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  105. package/lib-es/bridge/logic.d.ts +8 -13
  106. package/lib-es/bridge/logic.d.ts.map +1 -1
  107. package/lib-es/bridge/logic.js +52 -146
  108. package/lib-es/bridge/logic.js.map +1 -1
  109. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  110. package/lib-es/bridge/prepareTransaction.js +2 -2
  111. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  112. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  113. package/lib-es/bridge/signOperation.js +3 -17
  114. package/lib-es/bridge/signOperation.js.map +1 -1
  115. package/lib-es/bridge/synchronisation.d.ts +0 -15
  116. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  117. package/lib-es/bridge/synchronisation.js +3 -123
  118. package/lib-es/bridge/synchronisation.js.map +1 -1
  119. package/lib-es/constants.d.ts +1 -5
  120. package/lib-es/constants.d.ts.map +1 -1
  121. package/lib-es/constants.js +1 -5
  122. package/lib-es/constants.js.map +1 -1
  123. package/lib-es/test/bot-specs.d.ts.map +1 -1
  124. package/lib-es/test/bot-specs.js +2 -41
  125. package/lib-es/test/bot-specs.js.map +1 -1
  126. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
  127. package/lib-es/test/bridgeDatasetTest.js +59 -43
  128. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  129. package/lib-es/test/speculos-deviceActions.d.ts +0 -1
  130. package/lib-es/test/speculos-deviceActions.d.ts.map +1 -1
  131. package/lib-es/test/speculos-deviceActions.js +4 -36
  132. package/lib-es/test/speculos-deviceActions.js.map +1 -1
  133. package/lib-es/types/index.d.ts +7 -18
  134. package/lib-es/types/index.d.ts.map +1 -1
  135. package/package.json +5 -6
  136. package/src/__tests__/api/index.test.ts +5 -75
  137. package/src/__tests__/bridge/buildTransaction.test.ts +3 -85
  138. package/src/__tests__/bridge/getFeesForTransaction.test.ts +9 -144
  139. package/src/__tests__/bridge/getTransactionStatus.test.ts +38 -217
  140. package/src/__tests__/bridge/logic.test.ts +118 -922
  141. package/src/__tests__/bridge/signOperation.test.ts +2 -141
  142. package/src/__tests__/bridge/synchronisation.test.ts +71 -1265
  143. package/src/api/graphql/queries.ts +6 -6
  144. package/src/api/graphql/types.ts +9 -9
  145. package/src/api/index.ts +5 -32
  146. package/src/bridge/bridge.fixture.ts +12 -91
  147. package/src/bridge/buildTransaction.ts +6 -39
  148. package/src/bridge/estimateMaxSpendable.ts +1 -1
  149. package/src/bridge/getFeesForTransaction.ts +9 -14
  150. package/src/bridge/getTransactionStatus.ts +13 -35
  151. package/src/bridge/logic.ts +63 -202
  152. package/src/bridge/prepareTransaction.ts +3 -4
  153. package/src/bridge/signOperation.ts +3 -19
  154. package/src/bridge/synchronisation.ts +3 -170
  155. package/src/constants.ts +1 -12
  156. package/src/test/bot-specs.ts +3 -63
  157. package/src/test/bridgeDatasetTest.ts +59 -45
  158. package/src/test/speculos-deviceActions.ts +4 -40
  159. package/src/types/index.ts +1 -15
@@ -4,37 +4,20 @@ import {
4
4
  InputEntryFunctionData,
5
5
  MoveResource,
6
6
  WriteSetChange,
7
- WriteSetChangeWriteResource,
8
7
  } from "@aptos-labs/ts-sdk";
9
8
  import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
10
- import type { Account, Operation, OperationType, TokenAccount } from "@ledgerhq/types-live";
11
- import {
12
- decodeTokenAccountId,
13
- encodeTokenAccountId,
14
- findSubAccountById,
15
- isTokenAccount,
16
- } from "@ledgerhq/coin-framework/account/index";
9
+ import type { Operation, OperationType } from "@ledgerhq/types-live";
17
10
  import BigNumber from "bignumber.js";
18
11
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
19
12
  import {
20
- APTOS_ASSET_ID,
21
- APTOS_FUNGIBLE_STORE,
13
+ APTOS_COIN_CHANGE,
22
14
  BATCH_TRANSFER_TYPES,
23
15
  DELEGATION_POOL_TYPES,
24
16
  DIRECTION,
25
- COIN_TRANSFER_TYPES,
26
- FA_TRANSFER_TYPES,
27
- APTOS_OBJECT_CORE,
17
+ TRANSFER_TYPES,
18
+ WRITE_RESOURCE,
28
19
  } from "../constants";
29
- import type {
30
- AptosFungibleoObjectCoreResourceData,
31
- AptosFungibleStoreResourceData,
32
- AptosMoveResource,
33
- AptosTransaction,
34
- Transaction,
35
- TransactionOptions,
36
- } from "../types";
37
- import { findTokenByAddressInCurrency } from "@ledgerhq/cryptoassets";
20
+ import type { AptosMoveResource, AptosTransaction, TransactionOptions } from "../types";
38
21
 
39
22
  export const DEFAULT_GAS = new BigNumber(200);
40
23
  export const DEFAULT_GAS_PRICE = new BigNumber(100);
@@ -47,21 +30,13 @@ export function isTestnet(currencyId: string): boolean {
47
30
  }
48
31
 
49
32
  export const getMaxSendBalance = (
33
+ amount: BigNumber,
50
34
  gas: BigNumber,
51
35
  gasPrice: BigNumber,
52
- account: Account,
53
- transaction?: Transaction,
54
36
  ): BigNumber => {
55
- const tokenAccount = findSubAccountById(account, transaction?.subAccountId ?? "");
56
- const fromTokenAccount = tokenAccount && isTokenAccount(tokenAccount);
57
-
58
37
  const totalGas = gas.multipliedBy(gasPrice);
59
38
 
60
- return fromTokenAccount
61
- ? tokenAccount.spendableBalance
62
- : account.spendableBalance.gt(totalGas)
63
- ? account.spendableBalance.minus(totalGas)
64
- : new BigNumber(0);
39
+ return amount.gt(totalGas) ? amount.minus(totalGas) : new BigNumber(0);
65
40
  };
66
41
 
67
42
  export function normalizeTransactionOptions(options: TransactionOptions): TransactionOptions {
@@ -113,10 +88,9 @@ export const txsToOps = (
113
88
  info: { address: string },
114
89
  id: string,
115
90
  txs: (AptosTransaction | null)[],
116
- ): [Operation[], Operation[]] => {
91
+ ): Operation[] => {
117
92
  const { address } = info;
118
93
  const ops: Operation[] = [];
119
- const opsTokens: Operation[] = [];
120
94
 
121
95
  txs.forEach(tx => {
122
96
  if (tx !== null) {
@@ -133,12 +107,10 @@ export const txsToOps = (
133
107
  return; // skip transaction without functions in payload
134
108
  }
135
109
 
136
- const { coin_id, amount_in, amount_out } = getCoinAndAmounts(tx, address);
137
- op.value = calculateAmount(tx.sender, address, amount_in, amount_out);
110
+ const { amount_in, amount_out } = getAptosAmounts(tx, address);
111
+ op.value = calculateAmount(tx.sender, address, op.fee, amount_in, amount_out);
138
112
  op.type = compareAddress(tx.sender, address) ? DIRECTION.OUT : DIRECTION.IN;
139
113
  op.senders.push(tx.sender);
140
- op.hasFailed = !tx.success;
141
- op.id = encodeOperationId(op.accountId, tx.hash, op.type);
142
114
 
143
115
  processRecipients(payload, address, op, function_address);
144
116
 
@@ -147,30 +119,13 @@ export const txsToOps = (
147
119
  op.type = DIRECTION.UNKNOWN;
148
120
  }
149
121
 
150
- if (op.type !== DIRECTION.UNKNOWN && coin_id !== null) {
151
- if (coin_id === APTOS_ASSET_ID) {
152
- ops.push(op);
153
- } else {
154
- const token = findTokenByAddressInCurrency(coin_id.toLowerCase(), "aptos");
155
- if (token !== undefined) {
156
- op.accountId = encodeTokenAccountId(id, token);
157
- opsTokens.push(op);
158
-
159
- if (op.type === DIRECTION.OUT) {
160
- ops.push({
161
- ...op,
162
- accountId: decodeTokenAccountId(op.accountId).accountId,
163
- value: op.fee,
164
- type: "FEES",
165
- });
166
- }
167
- }
168
- }
169
- }
122
+ op.hasFailed = !tx.success;
123
+ op.id = encodeOperationId(id, tx.hash, op.type);
124
+ if (op.type !== DIRECTION.UNKNOWN) ops.push(op);
170
125
  }
171
126
  });
172
127
 
173
- return [ops, opsTokens];
128
+ return ops;
174
129
  };
175
130
 
176
131
  export function compareAddress(addressA: string, addressB: string) {
@@ -196,7 +151,7 @@ export function processRecipients(
196
151
  ): void {
197
152
  // get recipients buy 3 groups
198
153
  if (
199
- (COIN_TRANSFER_TYPES.includes(payload.function) ||
154
+ (TRANSFER_TYPES.includes(payload.function) ||
200
155
  DELEGATION_POOL_TYPES.includes(payload.function)) &&
201
156
  payload.functionArguments &&
202
157
  payload.functionArguments.length > 0 &&
@@ -204,15 +159,6 @@ export function processRecipients(
204
159
  ) {
205
160
  // 1. Transfer like functions (includes some delegation pool functions)
206
161
  op.recipients.push(payload.functionArguments[0].toString());
207
- } else if (
208
- FA_TRANSFER_TYPES.includes(payload.function) &&
209
- payload.functionArguments &&
210
- payload.functionArguments.length > 1 &&
211
- typeof payload.functionArguments[0] === "object" &&
212
- typeof payload.functionArguments[1] === "string"
213
- ) {
214
- // 1. Transfer like functions (includes some delegation pool functions)
215
- op.recipients.push(payload.functionArguments[1].toString());
216
162
  } else if (
217
163
  BATCH_TRANSFER_TYPES.includes(payload.function) &&
218
164
  payload.functionArguments &&
@@ -233,172 +179,87 @@ export function processRecipients(
233
179
  }
234
180
  }
235
181
 
236
- export function getEventCoinAddress(
237
- change: WriteSetChangeWriteResource,
182
+ function checkWriteSets(tx: AptosTransaction, event: Event, event_name: string): boolean {
183
+ return tx.changes.some(change => {
184
+ return isChangeOfAptos(change, event, event_name);
185
+ });
186
+ }
187
+
188
+ export function isChangeOfAptos(
189
+ writeSetChange: WriteSetChange,
238
190
  event: Event,
239
191
  event_name: string,
240
- ): string | null {
241
- const change_data = change.data;
242
-
243
- const mr = change_data as MoveResource<AptosMoveResource>; // -> this is data that we want to parse
244
-
245
- if (!(event_name in mr.data)) {
246
- return null;
192
+ ): boolean {
193
+ // to validate the event is related to Aptos Tokens we need to find change of type "write_resource"
194
+ // with the same guid as event
195
+ if (writeSetChange.type !== WRITE_RESOURCE) {
196
+ return false;
247
197
  }
248
198
 
249
- const change_event_data = mr.data[event_name];
250
- if (
251
- change_event_data.guid.id.addr !== event.guid.account_address ||
252
- change_event_data.guid.id.creation_num !== event.guid.creation_number
253
- ) {
254
- return null;
199
+ if (!("data" in writeSetChange)) {
200
+ return false;
255
201
  }
256
202
 
257
- const address = extractAddress(mr.type);
258
-
259
- return address;
260
- }
203
+ const change_data = writeSetChange.data;
261
204
 
262
- export function getEventFAAddress(
263
- change: WriteSetChangeWriteResource,
264
- event: Event,
265
- _event_name: string,
266
- ): string | null {
267
- const change_data = change.data;
268
-
269
- if (change_data.type !== APTOS_FUNGIBLE_STORE) {
270
- return null;
205
+ if (!("type" in change_data)) {
206
+ return false;
271
207
  }
272
208
 
273
- const mr = change_data as MoveResource<AptosFungibleStoreResourceData>;
209
+ const mr = change_data as MoveResource<AptosMoveResource>;
274
210
 
275
- if (change.address !== event.data.store) {
276
- return null;
211
+ if (mr.type !== APTOS_COIN_CHANGE) {
212
+ return false;
277
213
  }
278
214
 
279
- return mr.data.metadata.inner;
280
- }
281
-
282
- export function getResourceAddress(
283
- tx: AptosTransaction,
284
- event: Event,
285
- event_name: string,
286
- getAddressProcessor: (
287
- change: WriteSetChangeWriteResource,
288
- event: Event,
289
- event_name: string,
290
- ) => string | null,
291
- ): string | null {
292
- for (const change of tx.changes) {
293
- if (isWriteSetChangeWriteResource(change)) {
294
- const address = getAddressProcessor(change, event, event_name);
295
- if (address !== null) {
296
- return address;
297
- }
298
- }
299
- }
300
- return null;
301
- }
302
-
303
- function isWriteSetChangeWriteResource(
304
- change: WriteSetChange,
305
- ): change is WriteSetChangeWriteResource {
306
- return (change as WriteSetChangeWriteResource).data !== undefined;
307
- }
215
+ const change_event_data = mr.data[event_name];
308
216
 
309
- export function checkFAOwner(tx: AptosTransaction, event: Event, user_address: string): boolean {
310
- for (const change of tx.changes) {
311
- if (isWriteSetChangeWriteResource(change)) {
312
- const storeData = change.data as MoveResource<AptosFungibleoObjectCoreResourceData>;
313
- if (
314
- change.address == event.data.store &&
315
- storeData.type == APTOS_OBJECT_CORE &&
316
- storeData.data.owner == user_address
317
- ) {
318
- return true;
319
- }
320
- }
321
- }
322
- return false;
217
+ return (
218
+ change_event_data.guid.id.addr === event.guid.account_address &&
219
+ change_event_data.guid.id.creation_num === event.guid.creation_number
220
+ );
323
221
  }
324
222
 
325
- export function getCoinAndAmounts(
223
+ export function getAptosAmounts(
326
224
  tx: AptosTransaction,
327
225
  address: string,
328
- ): { coin_id: string | null; amount_in: BigNumber; amount_out: BigNumber } {
329
- let coin_id: string | null = null;
330
- let amount_in = BigNumber(0);
331
- let amount_out = BigNumber(0);
332
-
226
+ ): { amount_in: BigNumber; amount_out: BigNumber } {
227
+ let amount_in = new BigNumber(0);
228
+ let amount_out = new BigNumber(0);
333
229
  // collect all events related to the address and calculate the overall amounts
334
230
  tx.events.forEach(event => {
335
- switch (event.type) {
336
- case "0x1::coin::WithdrawEvent":
337
- if (compareAddress(event.guid.account_address, address)) {
338
- coin_id = getResourceAddress(tx, event, "withdraw_events", getEventCoinAddress);
339
- amount_out = amount_out.plus(event.data.amount);
340
- }
341
- break;
342
- case "0x1::coin::DepositEvent":
343
- if (compareAddress(event.guid.account_address, address)) {
344
- coin_id = getResourceAddress(tx, event, "deposit_events", getEventCoinAddress);
345
- amount_in = amount_in.plus(event.data.amount);
346
- }
347
- break;
348
- case "0x1::fungible_asset::Withdraw":
349
- if (checkFAOwner(tx, event, address)) {
350
- coin_id = getResourceAddress(tx, event, "withdraw_events", getEventFAAddress);
351
- amount_out = amount_out.plus(event.data.amount);
352
- }
353
- break;
354
- case "0x1::fungible_asset::Deposit":
355
- if (checkFAOwner(tx, event, address)) {
356
- coin_id = getResourceAddress(tx, event, "deposit_events", getEventFAAddress);
357
- amount_in = amount_in.plus(event.data.amount);
358
- }
359
- break;
360
- case "0x1::transaction_fee::FeeStatement":
361
- if (tx.sender === address) {
362
- if (coin_id === null) coin_id = APTOS_ASSET_ID;
363
- if (coin_id === APTOS_ASSET_ID) {
364
- const fees = BigNumber(tx.gas_unit_price).times(BigNumber(tx.gas_used));
365
- amount_out = amount_out.plus(fees);
231
+ if (compareAddress(event.guid.account_address, address)) {
232
+ switch (event.type) {
233
+ case "0x1::coin::WithdrawEvent":
234
+ if (checkWriteSets(tx, event, "withdraw_events")) {
235
+ amount_out = amount_out.plus(event.data.amount);
366
236
  }
367
- }
368
- break;
237
+ break;
238
+ case "0x1::coin::DepositEvent":
239
+ if (checkWriteSets(tx, event, "deposit_events")) {
240
+ amount_in = amount_in.plus(event.data.amount);
241
+ }
242
+ break;
243
+ }
369
244
  }
370
245
  });
371
- return { coin_id, amount_in, amount_out }; // TODO: manage situation when there are several coinID from the events parsing
246
+ return { amount_in, amount_out };
372
247
  }
373
248
 
374
249
  export function calculateAmount(
375
250
  sender: string,
376
251
  address: string,
252
+ fee: BigNumber,
377
253
  amount_in: BigNumber,
378
254
  amount_out: BigNumber,
379
255
  ): BigNumber {
380
256
  const is_sender: boolean = compareAddress(sender, address);
257
+ // Include fees if our address is the sender
258
+ if (is_sender) {
259
+ amount_out = amount_out.plus(fee);
260
+ }
381
261
  // LL negates the amount for SEND transactions
382
262
  // to show positive amount on the send transaction (ex: in "cancel" tx, when amount will be returned to our account)
383
263
  // we need to make it negative
384
264
  return is_sender ? amount_out.minus(amount_in) : amount_in.minus(amount_out);
385
265
  }
386
-
387
- /**
388
- * Extracts the address from a string like "0x1::coin::CoinStore<address::module::type>"
389
- * @param {string} str - The input string containing the address.
390
- * @returns {string | null} - The extracted address or null if not found.
391
- */
392
- function extractAddress(str: string): string | null {
393
- const match = str.match(/<([^<>]+)>{1}$/);
394
- return match ? match[1] : null;
395
- }
396
-
397
- export function getTokenAccount(
398
- account: Account,
399
- transaction: Transaction,
400
- ): TokenAccount | undefined {
401
- const tokenAccount = findSubAccountById(account, transaction.subAccountId ?? "");
402
- const fromTokenAccount = tokenAccount && isTokenAccount(tokenAccount);
403
- return fromTokenAccount ? tokenAccount : undefined;
404
- }
@@ -1,5 +1,6 @@
1
1
  import type { Account } from "@ledgerhq/types-live";
2
2
  import BigNumber from "bignumber.js";
3
+
3
4
  import { AptosAPI } from "../api";
4
5
  import { getEstimatedGas } from "./getFeesForTransaction";
5
6
  import type { Transaction } from "../types";
@@ -27,10 +28,9 @@ const prepareTransaction = async (
27
28
  if (transaction.useAllAmount) {
28
29
  // we will use this amount in simulation, to estimate gas
29
30
  transaction.amount = getMaxSendBalance(
31
+ account.spendableBalance,
30
32
  new BigNumber(DEFAULT_GAS),
31
33
  new BigNumber(DEFAULT_GAS_PRICE),
32
- account,
33
- transaction,
34
34
  );
35
35
  }
36
36
 
@@ -39,10 +39,9 @@ const prepareTransaction = async (
39
39
  if (transaction.useAllAmount) {
40
40
  // correct the transaction amount according to estimated fees
41
41
  transaction.amount = getMaxSendBalance(
42
+ account.spendableBalance,
42
43
  BigNumber(estimate.maxGasAmount),
43
44
  BigNumber(estimate.gasUnitPrice),
44
- account,
45
- transaction,
46
45
  );
47
46
  }
48
47
 
@@ -9,7 +9,6 @@ import { AptosAPI } from "../api";
9
9
  import { SignerContext } from "@ledgerhq/coin-framework/signer";
10
10
  import { AptosSigner } from "../types";
11
11
  import { signTransaction } from "../network";
12
- import { findSubAccountById } from "@ledgerhq/coin-framework/account/helpers";
13
12
 
14
13
  export const getAddress = (a: Account) => ({
15
14
  address: a.freshAddress,
@@ -46,15 +45,14 @@ const buildSignOperation =
46
45
  recipients.push(transaction.recipient);
47
46
  }
48
47
 
49
- const subAccount =
50
- !!transaction.subAccountId && findSubAccountById(account, transaction.subAccountId);
51
-
52
48
  // build optimistic operation
53
49
  const operation: Operation = {
54
50
  id: encodeOperationId(accountId, hash, type),
55
51
  hash,
56
52
  type,
57
- value: subAccount ? fee : transaction.amount.plus(fee),
53
+ value: transaction.useAllAmount
54
+ ? account.balance.minus(fee)
55
+ : transaction.amount.plus(fee),
58
56
  fee,
59
57
  extra,
60
58
  blockHash: null,
@@ -64,20 +62,6 @@ const buildSignOperation =
64
62
  accountId,
65
63
  date: new Date(),
66
64
  transactionSequenceNumber: Number(rawTx.sequence_number),
67
- subOperations: subAccount
68
- ? [
69
- {
70
- id: encodeOperationId(subAccount.id, "", "OUT"),
71
- type: "OUT",
72
- accountId: transaction.subAccountId,
73
- senders: [account.freshAddress],
74
- recipients: [transaction.recipient],
75
- value: transaction.amount,
76
- fee,
77
- date: new Date(),
78
- } as Operation,
79
- ]
80
- : [],
81
65
  };
82
66
 
83
67
  o.next({
@@ -1,160 +1,9 @@
1
- import { inferSubOperations } from "@ledgerhq/coin-framework/serialization/index";
2
1
  import { decodeAccountId, encodeAccountId } from "@ledgerhq/coin-framework/account";
3
2
  import type { GetAccountShape } from "@ledgerhq/coin-framework/bridge/jsHelpers";
4
3
  import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
5
4
  import { AptosAPI } from "../api";
6
5
  import { txsToOps } from "./logic";
7
6
  import type { AptosAccount } from "../types";
8
- import { Account, Operation, TokenAccount } from "@ledgerhq/types-live";
9
- import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
10
- import {
11
- decodeTokenAccountId,
12
- emptyHistoryCache,
13
- encodeTokenAccountId,
14
- } from "@ledgerhq/coin-framework/account/index";
15
- import { AccountShapeInfo } from "@ledgerhq/coin-framework/bridge/jsHelpers";
16
-
17
- /**
18
- * List of properties of a sub account that can be updated when 2 "identical" accounts are found
19
- */
20
- const updatableSubAccountProperties: { name: string; isOps: boolean }[] = [
21
- { name: "balance", isOps: false },
22
- { name: "spendableBalance", isOps: false },
23
- { name: "balanceHistoryCache", isOps: false },
24
- { name: "operations", isOps: true },
25
- { name: "pendingOperations", isOps: true },
26
- ];
27
- /**
28
- * In charge of smartly merging sub accounts while maintaining references as much as possible
29
- */
30
- export const mergeSubAccounts = (
31
- initialAccount: Account | undefined,
32
- newSubAccounts: TokenAccount[],
33
- ): Array<TokenAccount> => {
34
- const oldSubAccounts: Array<TokenAccount> | undefined = initialAccount?.subAccounts;
35
- if (!oldSubAccounts) {
36
- return newSubAccounts;
37
- }
38
-
39
- // Creating a map of already existing sub accounts by id
40
- const oldSubAccountsById: { [key: string]: TokenAccount } = {};
41
- for (const oldSubAccount of oldSubAccounts) {
42
- oldSubAccountsById[oldSubAccount.id!] = oldSubAccount;
43
- }
44
-
45
- // Looping on new sub accounts to compare them with already existing ones
46
- // Already existing will be updated if necessary (see `updatableSubAccountProperties`)
47
- // Fresh new sub accounts will be added/pushed after already existing
48
- const newSubAccountsToAdd: TokenAccount[] = [];
49
- for (const newSubAccount of newSubAccounts) {
50
- const duplicatedAccount: TokenAccount | undefined = oldSubAccountsById[newSubAccount.id!];
51
-
52
- // If this sub account was not already in the initialAccount
53
- if (!duplicatedAccount) {
54
- // We'll add it later
55
- newSubAccountsToAdd.push(newSubAccount);
56
- continue;
57
- }
58
-
59
- const updates: Partial<TokenAccount> & { [key: string]: any } = {};
60
- for (const { name, isOps } of updatableSubAccountProperties) {
61
- if (!isOps) {
62
- if (
63
- newSubAccount[name as keyof TokenAccount] !==
64
- duplicatedAccount[name as keyof TokenAccount]
65
- ) {
66
- updates[name] = newSubAccount[name as keyof TokenAccount];
67
- }
68
- } else {
69
- updates[name] =
70
- mergeOps(
71
- duplicatedAccount[name as keyof TokenAccount] as Operation[],
72
- newSubAccount[name as keyof TokenAccount] as Operation[],
73
- ) || [];
74
- }
75
- }
76
-
77
- // Updating the operationsCount in case the mergeOps changed it
78
- updates.operationsCount =
79
- updates.operations?.length || duplicatedAccount?.operations?.length || 0;
80
-
81
- // Modifying the Map with the updated sub account with a new ref
82
- oldSubAccountsById[newSubAccount.id!] = {
83
- ...duplicatedAccount,
84
- ...updates,
85
- };
86
- }
87
- const updatedSubAccounts = Object.values(oldSubAccountsById);
88
- return [...updatedSubAccounts, ...newSubAccountsToAdd];
89
- };
90
-
91
- /**
92
- * Fetch the balance for a token and creates a TokenAccount based on this and the provided operations
93
- */
94
- export const getSubAccountShape = async (
95
- currency: CryptoCurrency,
96
- address: string,
97
- parentId: string,
98
- token: TokenCurrency,
99
- operations: Operation[],
100
- ): Promise<TokenAccount> => {
101
- const aptosClient = new AptosAPI(currency.id);
102
- const tokenAccountId = encodeTokenAccountId(parentId, token);
103
- const balance = await aptosClient.getBalance(address, token);
104
- const firstOperation = operations
105
- .sort((a, b) => b.date.getTime() - a.date.getTime())
106
- .at(operations.length - 1);
107
-
108
- return {
109
- type: "TokenAccount",
110
- id: tokenAccountId,
111
- parentId,
112
- token,
113
- balance,
114
- spendableBalance: balance,
115
- creationDate: firstOperation?.date || new Date(0),
116
- operations,
117
- operationsCount: operations.length,
118
- pendingOperations: [],
119
- balanceHistoryCache: emptyHistoryCache,
120
- swapHistory: [],
121
- };
122
- };
123
-
124
- /**
125
- * Getting all token related operations in order to provide TokenAccounts
126
- */
127
- export const getSubAccounts = async (
128
- infos: AccountShapeInfo<Account>,
129
- address: string,
130
- accountId: string,
131
- lastTokenOperations: Operation[],
132
- ): Promise<TokenAccount[]> => {
133
- const { currency } = infos;
134
-
135
- // Creating a Map of Operations by TokenCurrencies in order to know which TokenAccounts should be synced as well
136
- const operationsByToken = lastTokenOperations.reduce<Map<TokenCurrency, Operation[]>>(
137
- (acc, operation) => {
138
- const { token } = decodeTokenAccountId(operation.accountId);
139
- if (!token) return acc; // TODO: do we need to check blacklistedTokenIds
140
-
141
- if (!acc.has(token)) {
142
- acc.set(token, []);
143
- }
144
- acc.get(token)?.push(operation);
145
- return acc;
146
- },
147
- new Map<TokenCurrency, Operation[]>(),
148
- );
149
-
150
- // Fetching all TokenAccounts possible and providing already filtered operations
151
- const subAccountsPromises: Promise<TokenAccount>[] = [];
152
- for (const [token, ops] of operationsByToken.entries()) {
153
- subAccountsPromises.push(getSubAccountShape(currency, address, accountId, token, ops));
154
- }
155
-
156
- return Promise.all(subAccountsPromises);
157
- };
158
7
 
159
8
  export const getAccountShape: GetAccountShape = async info => {
160
9
  const { address, initialAccount, currency, derivationMode, rest } = info;
@@ -177,29 +26,14 @@ export const getAccountShape: GetAccountShape = async info => {
177
26
  const xpub = initialAccount?.xpub || publicKey || "";
178
27
 
179
28
  const oldOperations = initialAccount?.operations || [];
29
+ const startAt = (oldOperations[0]?.extra as any)?.version;
180
30
 
181
31
  const aptosClient = new AptosAPI(currency.id);
182
- const { balance, transactions, blockHeight } = await aptosClient.getAccountInfo(address);
32
+ const { balance, transactions, blockHeight } = await aptosClient.getAccountInfo(address, startAt);
183
33
 
184
- const [newOperations, tokenOperations]: [Operation[], Operation[]] = txsToOps(
185
- info,
186
- accountId,
187
- transactions,
188
- );
34
+ const newOperations = txsToOps(info, accountId, transactions);
189
35
  const operations = mergeOps(oldOperations, newOperations);
190
36
 
191
- const newSubAccounts = await getSubAccounts(info, address, accountId, tokenOperations);
192
- const shouldSyncFromScratch = initialAccount === undefined;
193
- const subAccounts = shouldSyncFromScratch
194
- ? newSubAccounts
195
- : mergeSubAccounts(initialAccount, newSubAccounts);
196
-
197
- operations.forEach(op => {
198
- const subOperations = inferSubOperations(op.hash, subAccounts);
199
- op.subOperations =
200
- subOperations.length === 1 ? subOperations : subOperations.filter(op => !!op.blockHash);
201
- });
202
-
203
37
  const shape: Partial<AptosAccount> = {
204
38
  type: "Account",
205
39
  id: accountId,
@@ -210,7 +44,6 @@ export const getAccountShape: GetAccountShape = async info => {
210
44
  operationsCount: operations.length,
211
45
  blockHeight,
212
46
  lastSyncDate: new Date(),
213
- subAccounts,
214
47
  };
215
48
 
216
49
  return shape;
package/src/constants.ts CHANGED
@@ -10,36 +10,25 @@ export enum TX_STATUS {
10
10
 
11
11
  export const WRITE_RESOURCE = "write_resource";
12
12
 
13
- export const COIN_TRANSFER_TYPES: MoveStructId[] = [
13
+ export const TRANSFER_TYPES: MoveStructId[] = [
14
14
  "0x1::aptos_account::transfer",
15
15
  "0x1::aptos_account::transfer_coins",
16
16
  "0x1::coin::transfer",
17
17
  ];
18
-
19
- export const FA_TRANSFER_TYPES: MoveStructId[] = ["0x1::primary_fungible_store::transfer"];
20
-
21
18
  export const BATCH_TRANSFER_TYPES: MoveStructId[] = [
22
19
  "0x1::aptos_account::batch_transfer",
23
20
  "0x1::aptos_account::batch_transfer_coins",
24
21
  ];
25
-
26
22
  export const DELEGATION_POOL_TYPES: MoveStructId[] = [
27
23
  "0x1::delegation_pool::add_stake",
28
24
  "0x1::delegation_pool::withdraw",
29
25
  ];
30
26
 
31
27
  export const APTOS_ASSET_ID: MoveStructId = "0x1::aptos_coin::AptosCoin";
32
-
33
28
  export const APTOS_COIN_CHANGE: MoveStructId = `0x1::coin::CoinStore<${APTOS_ASSET_ID}>`;
34
29
 
35
- export const APTOS_FUNGIBLE_STORE: MoveStructId = "0x1::fungible_asset::FungibleStore";
36
-
37
- export const APTOS_OBJECT_CORE: MoveStructId = "0x1::object::ObjectCore";
38
-
39
30
  export enum DIRECTION {
40
31
  IN = "IN",
41
32
  OUT = "OUT",
42
33
  UNKNOWN = "UNKNOWN",
43
34
  }
44
-
45
- export const SUPPORTED_TOKEN_TYPES = ["coin", "fungible_asset"];