@ledgerhq/coin-aptos 1.9.0-next.0 → 2.0.0-nightly.2

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 +28 -10
  3. package/lib/__tests__/api/index.test.js +61 -5
  4. package/lib/__tests__/api/index.test.js.map +1 -1
  5. package/lib/__tests__/bridge/buildTransaction.test.js +57 -2
  6. package/lib/__tests__/bridge/buildTransaction.test.js.map +1 -1
  7. package/lib/__tests__/bridge/getFeesForTransaction.test.js +109 -8
  8. package/lib/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  9. package/lib/__tests__/bridge/getTransactionStatus.test.js +175 -37
  10. package/lib/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  11. package/lib/__tests__/bridge/logic.test.js +889 -115
  12. package/lib/__tests__/bridge/logic.test.js.map +1 -1
  13. package/lib/__tests__/bridge/signOperation.test.js +128 -2
  14. package/lib/__tests__/bridge/signOperation.test.js.map +1 -1
  15. package/lib/__tests__/bridge/synchronisation.test.js +1214 -67
  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 +5 -2
  21. package/lib/api/index.d.ts.map +1 -1
  22. package/lib/api/index.js +30 -4
  23. package/lib/api/index.js.map +1 -1
  24. package/lib/bridge/bridge.fixture.d.ts +2 -0
  25. package/lib/bridge/bridge.fixture.d.ts.map +1 -1
  26. package/lib/bridge/bridge.fixture.js +85 -13
  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 +29 -3
  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 +12 -7
  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 +28 -14
  38. package/lib/bridge/getTransactionStatus.js.map +1 -1
  39. package/lib/bridge/logic.d.ts +13 -8
  40. package/lib/bridge/logic.d.ts.map +1 -1
  41. package/lib/bridge/logic.js +152 -54
  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 +17 -3
  48. package/lib/bridge/signOperation.js.map +1 -1
  49. package/lib/bridge/synchronisation.d.ts +15 -0
  50. package/lib/bridge/synchronisation.d.ts.map +1 -1
  51. package/lib/bridge/synchronisation.js +127 -4
  52. package/lib/bridge/synchronisation.js.map +1 -1
  53. package/lib/constants.d.ts +5 -1
  54. package/lib/constants.d.ts.map +1 -1
  55. package/lib/constants.js +6 -2
  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 +40 -1
  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 +43 -62
  62. package/lib/test/bridgeDatasetTest.js.map +1 -1
  63. package/lib/test/speculos-deviceActions.d.ts +1 -0
  64. package/lib/test/speculos-deviceActions.d.ts.map +1 -1
  65. package/lib/test/speculos-deviceActions.js +37 -5
  66. package/lib/test/speculos-deviceActions.js.map +1 -1
  67. package/lib/types/index.d.ts +18 -7
  68. package/lib/types/index.d.ts.map +1 -1
  69. package/lib-es/__tests__/api/index.test.js +61 -5
  70. package/lib-es/__tests__/api/index.test.js.map +1 -1
  71. package/lib-es/__tests__/bridge/buildTransaction.test.js +58 -3
  72. package/lib-es/__tests__/bridge/buildTransaction.test.js.map +1 -1
  73. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js +110 -9
  74. package/lib-es/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
  75. package/lib-es/__tests__/bridge/getTransactionStatus.test.js +177 -39
  76. package/lib-es/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
  77. package/lib-es/__tests__/bridge/logic.test.js +891 -117
  78. package/lib-es/__tests__/bridge/logic.test.js.map +1 -1
  79. package/lib-es/__tests__/bridge/signOperation.test.js +128 -2
  80. package/lib-es/__tests__/bridge/signOperation.test.js.map +1 -1
  81. package/lib-es/__tests__/bridge/synchronisation.test.js +1213 -69
  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 +5 -2
  87. package/lib-es/api/index.d.ts.map +1 -1
  88. package/lib-es/api/index.js +30 -4
  89. package/lib-es/api/index.js.map +1 -1
  90. package/lib-es/bridge/bridge.fixture.d.ts +2 -0
  91. package/lib-es/bridge/bridge.fixture.d.ts.map +1 -1
  92. package/lib-es/bridge/bridge.fixture.js +82 -12
  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 +30 -4
  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 +13 -8
  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 +28 -14
  104. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  105. package/lib-es/bridge/logic.d.ts +13 -8
  106. package/lib-es/bridge/logic.d.ts.map +1 -1
  107. package/lib-es/bridge/logic.js +146 -52
  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 +17 -3
  114. package/lib-es/bridge/signOperation.js.map +1 -1
  115. package/lib-es/bridge/synchronisation.d.ts +15 -0
  116. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  117. package/lib-es/bridge/synchronisation.js +123 -3
  118. package/lib-es/bridge/synchronisation.js.map +1 -1
  119. package/lib-es/constants.d.ts +5 -1
  120. package/lib-es/constants.d.ts.map +1 -1
  121. package/lib-es/constants.js +5 -1
  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 +41 -2
  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 +43 -59
  128. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  129. package/lib-es/test/speculos-deviceActions.d.ts +1 -0
  130. package/lib-es/test/speculos-deviceActions.d.ts.map +1 -1
  131. package/lib-es/test/speculos-deviceActions.js +36 -4
  132. package/lib-es/test/speculos-deviceActions.js.map +1 -1
  133. package/lib-es/types/index.d.ts +18 -7
  134. package/lib-es/types/index.d.ts.map +1 -1
  135. package/package.json +9 -8
  136. package/src/__tests__/api/index.test.ts +75 -5
  137. package/src/__tests__/bridge/buildTransaction.test.ts +85 -3
  138. package/src/__tests__/bridge/getFeesForTransaction.test.ts +144 -9
  139. package/src/__tests__/bridge/getTransactionStatus.test.ts +217 -38
  140. package/src/__tests__/bridge/logic.test.ts +922 -118
  141. package/src/__tests__/bridge/signOperation.test.ts +141 -2
  142. package/src/__tests__/bridge/synchronisation.test.ts +1265 -71
  143. package/src/api/graphql/queries.ts +6 -6
  144. package/src/api/graphql/types.ts +9 -9
  145. package/src/api/index.ts +32 -5
  146. package/src/bridge/bridge.fixture.ts +91 -12
  147. package/src/bridge/buildTransaction.ts +39 -6
  148. package/src/bridge/estimateMaxSpendable.ts +1 -1
  149. package/src/bridge/getFeesForTransaction.ts +14 -9
  150. package/src/bridge/getTransactionStatus.ts +35 -13
  151. package/src/bridge/logic.ts +202 -63
  152. package/src/bridge/prepareTransaction.ts +4 -3
  153. package/src/bridge/signOperation.ts +19 -3
  154. package/src/bridge/synchronisation.ts +170 -3
  155. package/src/constants.ts +12 -1
  156. package/src/test/bot-specs.ts +63 -3
  157. package/src/test/bridgeDatasetTest.ts +45 -59
  158. package/src/test/speculos-deviceActions.ts +40 -4
  159. package/src/types/index.ts +15 -1
@@ -18,8 +18,8 @@ export const GetDelegatedStakingActivities = gql`
18
18
  `;
19
19
  export const GetAccountTransactionsData = gql`
20
20
  query GetAccountTransactionsData($address: String, $limit: Int) {
21
- address_version_from_move_resources(
22
- where: { address: { _eq: $address } }
21
+ account_transactions(
22
+ where: { account_address: { _eq: $address } }
23
23
  order_by: { transaction_version: desc }
24
24
  limit: $limit
25
25
  ) {
@@ -30,8 +30,8 @@ export const GetAccountTransactionsData = gql`
30
30
  `;
31
31
  export const GetAccountTransactionsDataGt = gql`
32
32
  query GetAccountTransactionsDataGt($address: String, $limit: Int, $gt: bigint) {
33
- address_version_from_move_resources(
34
- where: { address: { _eq: $address }, transaction_version: { _gt: $gt } }
33
+ account_transactions(
34
+ where: { account_address: { _eq: $address }, transaction_version: { _gt: $gt } }
35
35
  order_by: { transaction_version: desc }
36
36
  limit: $limit
37
37
  ) {
@@ -42,8 +42,8 @@ export const GetAccountTransactionsDataGt = gql`
42
42
  `;
43
43
  export const GetAccountTransactionsDataLt = gql`
44
44
  query GetAccountTransactionsDataLt($address: String, $limit: Int, $lt: bigint) {
45
- address_version_from_move_resources(
46
- where: { address: { _eq: $address }, transaction_version: { _lt: $lt } }
45
+ account_transactions(
46
+ where: { account_address: { _eq: $address }, transaction_version: { _lt: $lt } }
47
47
  order_by: { transaction_version: desc }
48
48
  limit: $limit
49
49
  ) {
@@ -22,9 +22,9 @@ export type GetAccountTransactionsDataQueryVariables = Exact<{
22
22
 
23
23
  export type GetAccountTransactionsDataQuery = {
24
24
  __typename?: "query_root";
25
- address_version_from_move_resources: Array<{
26
- __typename: "address_version_from_move_resources";
27
- transaction_version?: any | null;
25
+ account_transactions: Array<{
26
+ __typename?: "account_transactions";
27
+ transaction_version: number;
28
28
  }>;
29
29
  };
30
30
 
@@ -36,9 +36,9 @@ export type GetAccountTransactionsDataGtQueryVariables = Exact<{
36
36
 
37
37
  export type GetAccountTransactionsDataGtQuery = {
38
38
  __typename?: "query_root";
39
- address_version_from_move_resources: Array<{
40
- __typename: "address_version_from_move_resources";
41
- transaction_version?: any | null;
39
+ account_transactions: Array<{
40
+ __typename?: "account_transactions";
41
+ transaction_version: number;
42
42
  }>;
43
43
  };
44
44
 
@@ -50,9 +50,9 @@ export type GetAccountTransactionsDataLtQueryVariables = Exact<{
50
50
 
51
51
  export type GetAccountTransactionsDataLtQuery = {
52
52
  __typename?: "query_root";
53
- address_version_from_move_resources: Array<{
54
- __typename: "address_version_from_move_resources";
55
- transaction_version?: any | null;
53
+ account_transactions: Array<{
54
+ __typename?: "account_transactions";
55
+ transaction_version: number;
56
56
  }>;
57
57
  };
58
58
 
package/src/api/index.ts CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  GetAccountTransactionsDataQuery,
31
31
  GetAccountTransactionsDataGtQueryVariables,
32
32
  } from "./graphql/types";
33
+ import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
33
34
 
34
35
  const getApiEndpoint = (currencyId: string) =>
35
36
  isTestnet(currencyId) ? getEnv("APTOS_TESTNET_API_ENDPOINT") : getEnv("APTOS_API_ENDPOINT");
@@ -66,9 +67,9 @@ export class AptosAPI {
66
67
  return this.aptosClient.getAccountInfo({ accountAddress: address });
67
68
  }
68
69
 
69
- async getAccountInfo(address: string, startAt: string) {
70
+ async getAccountInfo(address: string, startAt?: string) {
70
71
  const [balance, transactions, blockHeight] = await Promise.all([
71
- this.getBalance(address),
72
+ this.getCoinBalance(address, APTOS_ASSET_ID),
72
73
  this.fetchTransactions(address, startAt),
73
74
  this.getHeight(),
74
75
  ]);
@@ -146,12 +147,22 @@ export class AptosAPI {
146
147
  return pendingTx.data.hash;
147
148
  }
148
149
 
149
- private async getBalance(address: string): Promise<BigNumber> {
150
+ async getBalance(address: string, token: TokenCurrency): Promise<BigNumber> {
151
+ let balance = new BigNumber(0);
152
+ if (token.tokenType === "coin") {
153
+ balance = await this.getCoinBalance(address, token.contractAddress);
154
+ } else {
155
+ balance = await this.getFABalance(address, token.contractAddress);
156
+ }
157
+ return balance;
158
+ }
159
+
160
+ async getCoinBalance(address: string, contract_address: string): Promise<BigNumber> {
150
161
  try {
151
162
  const [balanceStr] = await this.aptosClient.view<[string]>({
152
163
  payload: {
153
164
  function: "0x1::coin::balance",
154
- typeArguments: [APTOS_ASSET_ID],
165
+ typeArguments: [contract_address],
155
166
  functionArguments: [address],
156
167
  },
157
168
  });
@@ -162,6 +173,22 @@ export class AptosAPI {
162
173
  }
163
174
  }
164
175
 
176
+ async getFABalance(address: string, contract_address: string): Promise<BigNumber> {
177
+ try {
178
+ const [balanceStr] = await this.aptosClient.view<[string]>({
179
+ payload: {
180
+ function: "0x1::primary_fungible_store::balance",
181
+ typeArguments: ["0x1::object::ObjectCore"],
182
+ functionArguments: [address, contract_address],
183
+ },
184
+ });
185
+ const balance = parseInt(balanceStr, 10);
186
+ return new BigNumber(balance);
187
+ } catch (_) {
188
+ return new BigNumber(0);
189
+ }
190
+ }
191
+
165
192
  private async fetchTransactions(address: string, gt?: string) {
166
193
  if (!address) {
167
194
  return [];
@@ -186,7 +213,7 @@ export class AptosAPI {
186
213
  });
187
214
 
188
215
  return Promise.all(
189
- queryResponse.data.address_version_from_move_resources.map(({ transaction_version }) => {
216
+ queryResponse.data.account_transactions.map(({ transaction_version }) => {
190
217
  return this.richItemByVersion(transaction_version);
191
218
  }),
192
219
  );
@@ -3,6 +3,7 @@ import { faker } from "@faker-js/faker";
3
3
  import type { AptosAccount, Transaction } from "../types/index";
4
4
  import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
5
5
  import { emptyHistoryCache } from "@ledgerhq/coin-framework/account/index";
6
+ import { TokenCurrency } from "@ledgerhq/types-cryptoassets";
6
7
 
7
8
  const currency = getCryptoCurrencyById("aptos");
8
9
 
@@ -18,35 +19,113 @@ export function createFixtureAccount(account?: Partial<AptosAccount>): AptosAcco
18
19
  seedIdentifier: faker.string.uuid(),
19
20
  derivationMode: "",
20
21
  index: faker.number.int(),
21
- freshAddress: account?.freshAddress || freshAddress.address,
22
- freshAddressPath: account?.freshAddressPath || freshAddress.derivationPath,
22
+ freshAddress: freshAddress.address,
23
+ freshAddressPath: freshAddress.derivationPath,
23
24
  used: true,
24
- balance: account?.balance || new BigNumber(0),
25
- spendableBalance: account?.spendableBalance || new BigNumber(0),
25
+ balance: new BigNumber(0),
26
+ spendableBalance: new BigNumber(0),
26
27
  creationDate: faker.date.past(),
27
28
  blockHeight: faker.number.int({ min: 100_000, max: 200_000 }),
28
29
  currency,
29
- operationsCount: account?.operationsCount || 0,
30
- operations: account?.operations || [],
31
- pendingOperations: account?.pendingOperations || [],
30
+ operationsCount: 0,
31
+ operations: [],
32
+ pendingOperations: [],
32
33
  lastSyncDate: new Date(),
33
34
  balanceHistoryCache: emptyHistoryCache,
34
35
  swapHistory: [],
36
+ ...account,
37
+ };
38
+ }
39
+
40
+ export function createFixtureAccountWithSubAccount(
41
+ tokenType: string,
42
+ account?: Partial<AptosAccount>,
43
+ ): AptosAccount {
44
+ const freshAddress = {
45
+ address: "address",
46
+ derivationPath: "derivation_path",
47
+ };
48
+
49
+ const id = faker.string.uuid();
50
+
51
+ return {
52
+ type: "Account",
53
+ id,
54
+ seedIdentifier: faker.string.uuid(),
55
+ derivationMode: "",
56
+ index: faker.number.int(),
57
+ freshAddress: freshAddress.address,
58
+ freshAddressPath: freshAddress.derivationPath,
59
+ used: true,
60
+ balance: new BigNumber(0),
61
+ spendableBalance: new BigNumber(0),
62
+ creationDate: faker.date.past(),
63
+ blockHeight: faker.number.int({ min: 100_000, max: 200_000 }),
64
+ currency,
65
+ operationsCount: 0,
66
+ operations: [],
67
+ pendingOperations: [],
68
+ lastSyncDate: new Date(),
69
+ balanceHistoryCache: emptyHistoryCache,
70
+ swapHistory: [],
71
+ subAccounts: [
72
+ {
73
+ id: "1",
74
+ parentId: id,
75
+ type: "TokenAccount",
76
+ token: {
77
+ type: "TokenCurrency",
78
+ id: "aptToken",
79
+ contractAddress: "contract_address",
80
+ parentCurrency: currency,
81
+ tokenType,
82
+ } as TokenCurrency,
83
+ balance: BigNumber(1000),
84
+ spendableBalance: BigNumber(1000),
85
+ creationDate: new Date(),
86
+ operationsCount: 0,
87
+ operations: [],
88
+ pendingOperations: [],
89
+ balanceHistoryCache: emptyHistoryCache,
90
+ swapHistory: [],
91
+ },
92
+ ],
93
+ ...account,
35
94
  };
36
95
  }
37
96
 
38
97
  export function createFixtureTransaction(tx?: Partial<Transaction>): Transaction {
39
98
  const transaction: Transaction = {
40
- amount: tx?.amount || new BigNumber(0),
41
- recipient: tx?.recipient || "",
42
- useAllAmount: tx?.useAllAmount || false,
99
+ amount: new BigNumber(0),
100
+ recipient: "recipient",
101
+ useAllAmount: false,
102
+ family: "aptos",
103
+ mode: "send",
104
+ fees: null,
105
+ options: {
106
+ maxGasAmount: BigNumber(0).toString(),
107
+ gasUnitPrice: BigNumber(0).toString(),
108
+ },
109
+ ...tx,
110
+ };
111
+
112
+ return transaction;
113
+ }
114
+
115
+ export function createFixtureTransactionWithSubAccount(tx?: Partial<Transaction>): Transaction {
116
+ const transaction: Transaction = {
117
+ amount: new BigNumber(0),
118
+ recipient: "recipient",
119
+ useAllAmount: false,
43
120
  family: "aptos",
44
- mode: tx?.mode || "send",
45
- fees: tx?.fees || null,
121
+ mode: "send",
122
+ fees: null,
46
123
  options: {
47
124
  maxGasAmount: BigNumber(0).toString(),
48
125
  gasUnitPrice: BigNumber(0).toString(),
49
126
  },
127
+ subAccountId: "1",
128
+ ...tx,
50
129
  };
51
130
 
52
131
  return transaction;
@@ -1,8 +1,8 @@
1
1
  import { InputEntryFunctionData, RawTransaction } from "@aptos-labs/ts-sdk";
2
- import type { Account } from "@ledgerhq/types-live";
3
- import BigNumber from "bignumber.js";
2
+ import type { Account, TokenAccount } from "@ledgerhq/types-live";
3
+ import { findSubAccountById, isTokenAccount } from "@ledgerhq/coin-framework/account/index";
4
4
  import { AptosAPI } from "../api";
5
- import { APTOS_ASSET_ID } from "../constants";
5
+ import { APTOS_ASSET_ID, SUPPORTED_TOKEN_TYPES } from "../constants";
6
6
  import { normalizeTransactionOptions } from "./logic";
7
7
  import type { Transaction } from "../types";
8
8
 
@@ -11,18 +11,51 @@ const buildTransaction = async (
11
11
  transaction: Transaction,
12
12
  aptosClient: AptosAPI,
13
13
  ): Promise<RawTransaction> => {
14
- const txPayload = getPayload(transaction.recipient, transaction.amount);
14
+ const subAccount = findSubAccountById(account, transaction.subAccountId ?? "");
15
+
16
+ const txPayload = getPayload(subAccount, transaction);
15
17
  const txOptions = normalizeTransactionOptions(transaction.options);
16
18
  const tx = await aptosClient.generateTransaction(account.freshAddress, txPayload, txOptions);
17
19
 
18
20
  return tx;
19
21
  };
20
22
 
21
- const getPayload = (sendTo: string, amount: BigNumber): InputEntryFunctionData => {
23
+ const getPayload = (
24
+ tokenAccount: TokenAccount | undefined,
25
+ transaction: Transaction,
26
+ ): InputEntryFunctionData => {
27
+ if (tokenAccount && isTokenAccount(tokenAccount)) {
28
+ const { tokenType } = tokenAccount.token;
29
+
30
+ if (!SUPPORTED_TOKEN_TYPES.includes(tokenType)) {
31
+ throw new Error(`Token type ${tokenType} not supported`);
32
+ }
33
+
34
+ if (tokenType === "fungible_asset") {
35
+ return {
36
+ function: `0x1::primary_fungible_store::transfer`,
37
+ typeArguments: ["0x1::fungible_asset::Metadata"],
38
+ functionArguments: [
39
+ tokenAccount.token.contractAddress,
40
+ transaction.recipient,
41
+ transaction.amount.toString(),
42
+ ],
43
+ };
44
+ }
45
+
46
+ if (tokenType === "coin") {
47
+ return {
48
+ function: `0x1::aptos_account::transfer_coins`,
49
+ typeArguments: [tokenAccount.token.contractAddress],
50
+ functionArguments: [transaction.recipient, transaction.amount.toString()],
51
+ };
52
+ }
53
+ }
54
+
22
55
  return {
23
56
  function: "0x1::aptos_account::transfer_coins",
24
57
  typeArguments: [APTOS_ASSET_ID],
25
- functionArguments: [sendTo, amount.toString()],
58
+ functionArguments: [transaction.recipient, transaction.amount.toString()],
26
59
  };
27
60
  };
28
61
 
@@ -29,7 +29,7 @@ const estimateMaxSpendable = async ({
29
29
  gasUnitPrice = BigNumber(estimate.gasUnitPrice);
30
30
  }
31
31
 
32
- return getMaxSendBalance(mainAccount.spendableBalance, maxGasAmount, gasUnitPrice);
32
+ return getMaxSendBalance(maxGasAmount, gasUnitPrice, mainAccount, transaction);
33
33
  };
34
34
 
35
35
  export default estimateMaxSpendable;
@@ -5,7 +5,7 @@ import BigNumber from "bignumber.js";
5
5
  import { makeLRUCache, seconds } from "@ledgerhq/live-network/cache";
6
6
  import { AptosAPI } from "../api";
7
7
  import buildTransaction from "./buildTransaction";
8
- import { DEFAULT_GAS, DEFAULT_GAS_PRICE, ESTIMATE_GAS_MUL } from "./logic";
8
+ import { DEFAULT_GAS, DEFAULT_GAS_PRICE, ESTIMATE_GAS_MUL, getTokenAccount } from "./logic";
9
9
  import type { Transaction, TransactionErrors } from "../types";
10
10
 
11
11
  type IGetEstimatedGasReturnType = {
@@ -49,16 +49,18 @@ export const getFee = async (
49
49
 
50
50
  const expectedGas = gasPrice.multipliedBy(gasLimit);
51
51
 
52
- const isUnderMaxSpendable = transaction.amount
53
- .plus(expectedGas)
54
- .isLessThan(account.spendableBalance);
55
-
56
- if (isUnderMaxSpendable && !completedTx.success) {
57
- // we want to skip INSUFFICIENT_BALANCE error because it will be processed by getTransactionStatus
58
- if (!completedTx.vm_status.includes("INSUFFICIENT_BALANCE")) {
52
+ if (!completedTx.success) {
53
+ if (completedTx.vm_status.includes("MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS")) {
54
+ res.errors.maxGasAmount = "GasInsufficientBalance";
55
+ } else if (
56
+ !completedTx.vm_status.includes("INSUFFICIENT_BALANCE") &&
57
+ !completedTx.vm_status.includes("0x203ed") // 0x203ed -> PROLOGUE_ECANT_PAY_GAS_DEPOSIT equivalent to INSUFFICIENT_BALANCE_FOR_TRANSACTION_FEE
58
+ ) {
59
+ // INSUFFICIENT_BALANCE will be processed by getTransactionStatus
59
60
  throw Error(`Simulation failed with following error: ${completedTx.vm_status}`);
60
61
  }
61
62
  }
63
+
62
64
  res.fees = expectedGas;
63
65
  res.estimate.maxGasAmount = gasLimit.toString();
64
66
  res.estimate.gasUnitPrice = completedTx.gas_unit_price;
@@ -72,7 +74,10 @@ export const getFee = async (
72
74
 
73
75
  const CACHE = makeLRUCache(
74
76
  getFee,
75
- (account: Account, transaction: Transaction) => `${account.id}-${transaction.amount.toString()}}`,
77
+ (account: Account, transaction: Transaction) => {
78
+ const tokenAccount = getTokenAccount(account, transaction);
79
+ return `${tokenAccount ? tokenAccount.id : account.id}-${transaction.amount.toString()}}`;
80
+ },
76
81
  seconds(30),
77
82
  );
78
83
 
@@ -1,4 +1,3 @@
1
- import { BigNumber } from "bignumber.js";
2
1
  import {
3
2
  NotEnoughBalance,
4
3
  RecipientRequired,
@@ -6,40 +5,63 @@ import {
6
5
  FeeNotLoaded,
7
6
  InvalidAddressBecauseDestinationIsAlsoSource,
8
7
  AmountRequired,
8
+ NotEnoughBalanceFees,
9
9
  } from "@ledgerhq/errors";
10
10
  import type { Account } from "@ledgerhq/types-live";
11
+ import { BigNumber } from "bignumber.js";
11
12
  import type { Transaction, TransactionStatus } from "../types";
12
13
 
13
14
  import { AccountAddress } from "@aptos-labs/ts-sdk";
15
+ import { getTokenAccount } from "./logic";
14
16
 
15
17
  const getTransactionStatus = async (a: Account, t: Transaction): Promise<TransactionStatus> => {
16
18
  const errors: Record<string, Error> = {};
17
19
  const warnings = {};
18
20
 
21
+ if (!t.recipient) {
22
+ errors.recipient = new RecipientRequired();
23
+ }
24
+
25
+ if (!AccountAddress.isValid({ input: t.recipient }).valid && !errors.recipient) {
26
+ errors.recipient = new InvalidAddress("", { currencyName: a.currency.name });
27
+ }
28
+
29
+ if (t.recipient === a.freshAddress && !errors.recipient) {
30
+ errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource();
31
+ }
32
+
19
33
  if (!t.fees) {
20
34
  errors.fees = new FeeNotLoaded();
21
35
  }
22
36
 
23
37
  const estimatedFees = t.fees || BigNumber(0);
24
38
 
25
- if (t.amount.eq(0)) {
39
+ if (t.amount.lte(0)) {
26
40
  errors.amount = new AmountRequired();
27
41
  }
28
42
 
29
- const amount = t.amount;
43
+ const tokenAccount = getTokenAccount(a, t);
30
44
 
31
- const totalSpent = BigNumber(t.amount).plus(estimatedFees);
45
+ const amount = t.useAllAmount
46
+ ? tokenAccount
47
+ ? tokenAccount.spendableBalance
48
+ : a.spendableBalance.minus(estimatedFees).isLessThan(0)
49
+ ? BigNumber(0)
50
+ : a.spendableBalance.minus(estimatedFees)
51
+ : t.amount;
32
52
 
33
- if (totalSpent.gt(a.balance) && !errors.amount) {
34
- errors.amount = new NotEnoughBalance();
35
- }
53
+ const totalSpent = tokenAccount ? amount : amount.plus(estimatedFees);
36
54
 
37
- if (!t.recipient) {
38
- errors.recipient = new RecipientRequired();
39
- } else if (AccountAddress.isValid({ input: t.recipient }).valid === false && !errors.recipient) {
40
- errors.recipient = new InvalidAddress("", { currencyName: a.currency.name });
41
- } else if (t.recipient === a.freshAddress && !errors.recipient) {
42
- errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource();
55
+ if (tokenAccount && t.errors?.maxGasAmount == "GasInsufficientBalance" && !errors.amount) {
56
+ errors.amount = new NotEnoughBalanceFees();
57
+ }
58
+ if (
59
+ tokenAccount
60
+ ? tokenAccount.spendableBalance.isLessThan(totalSpent) ||
61
+ a.spendableBalance.isLessThan(estimatedFees)
62
+ : a.spendableBalance.isLessThan(totalSpent) && !errors.amount
63
+ ) {
64
+ errors.amount = new NotEnoughBalance();
43
65
  }
44
66
 
45
67
  return Promise.resolve({