@ledgerhq/coin-aptos 2.0.0-nightly.3 → 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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -0
- package/lib/__tests__/api/index.test.js +5 -61
- package/lib/__tests__/api/index.test.js.map +1 -1
- package/lib/__tests__/bridge/buildTransaction.test.js +2 -57
- package/lib/__tests__/bridge/buildTransaction.test.js.map +1 -1
- package/lib/__tests__/bridge/getFeesForTransaction.test.js +8 -109
- package/lib/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
- package/lib/__tests__/bridge/getTransactionStatus.test.js +37 -175
- package/lib/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
- package/lib/__tests__/bridge/logic.test.js +115 -889
- package/lib/__tests__/bridge/logic.test.js.map +1 -1
- package/lib/__tests__/bridge/signOperation.test.js +2 -128
- package/lib/__tests__/bridge/signOperation.test.js.map +1 -1
- package/lib/__tests__/bridge/synchronisation.test.js +67 -1214
- package/lib/__tests__/bridge/synchronisation.test.js.map +1 -1
- package/lib/api/graphql/queries.js +6 -6
- package/lib/api/graphql/types.d.ts +9 -9
- package/lib/api/graphql/types.d.ts.map +1 -1
- package/lib/api/index.d.ts +2 -5
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +4 -30
- package/lib/api/index.js.map +1 -1
- package/lib/bridge/bridge.fixture.d.ts +0 -2
- package/lib/bridge/bridge.fixture.d.ts.map +1 -1
- package/lib/bridge/bridge.fixture.js +13 -85
- package/lib/bridge/bridge.fixture.js.map +1 -1
- package/lib/bridge/buildTransaction.d.ts.map +1 -1
- package/lib/bridge/buildTransaction.js +3 -29
- package/lib/bridge/buildTransaction.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +1 -1
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib/bridge/getFeesForTransaction.js +7 -12
- package/lib/bridge/getFeesForTransaction.js.map +1 -1
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +14 -28
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/logic.d.ts +8 -13
- package/lib/bridge/logic.d.ts.map +1 -1
- package/lib/bridge/logic.js +54 -152
- package/lib/bridge/logic.js.map +1 -1
- package/lib/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib/bridge/prepareTransaction.js +2 -2
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +3 -17
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/synchronisation.d.ts +0 -15
- package/lib/bridge/synchronisation.d.ts.map +1 -1
- package/lib/bridge/synchronisation.js +4 -127
- package/lib/bridge/synchronisation.js.map +1 -1
- package/lib/constants.d.ts +1 -5
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +2 -6
- package/lib/constants.js.map +1 -1
- package/lib/test/bot-specs.d.ts.map +1 -1
- package/lib/test/bot-specs.js +1 -40
- package/lib/test/bot-specs.js.map +1 -1
- package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
- package/lib/test/bridgeDatasetTest.js +62 -43
- package/lib/test/bridgeDatasetTest.js.map +1 -1
- package/lib/test/speculos-deviceActions.d.ts +0 -1
- package/lib/test/speculos-deviceActions.d.ts.map +1 -1
- package/lib/test/speculos-deviceActions.js +5 -37
- package/lib/test/speculos-deviceActions.js.map +1 -1
- package/lib/types/index.d.ts +7 -18
- package/lib/types/index.d.ts.map +1 -1
- package/lib-es/__tests__/api/index.test.js +5 -61
- package/lib-es/__tests__/api/index.test.js.map +1 -1
- package/lib-es/__tests__/bridge/buildTransaction.test.js +3 -58
- package/lib-es/__tests__/bridge/buildTransaction.test.js.map +1 -1
- package/lib-es/__tests__/bridge/getFeesForTransaction.test.js +9 -110
- package/lib-es/__tests__/bridge/getFeesForTransaction.test.js.map +1 -1
- package/lib-es/__tests__/bridge/getTransactionStatus.test.js +39 -177
- package/lib-es/__tests__/bridge/getTransactionStatus.test.js.map +1 -1
- package/lib-es/__tests__/bridge/logic.test.js +117 -891
- package/lib-es/__tests__/bridge/logic.test.js.map +1 -1
- package/lib-es/__tests__/bridge/signOperation.test.js +2 -128
- package/lib-es/__tests__/bridge/signOperation.test.js.map +1 -1
- package/lib-es/__tests__/bridge/synchronisation.test.js +69 -1213
- package/lib-es/__tests__/bridge/synchronisation.test.js.map +1 -1
- package/lib-es/api/graphql/queries.js +6 -6
- package/lib-es/api/graphql/types.d.ts +9 -9
- package/lib-es/api/graphql/types.d.ts.map +1 -1
- package/lib-es/api/index.d.ts +2 -5
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +4 -30
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/bridge/bridge.fixture.d.ts +0 -2
- package/lib-es/bridge/bridge.fixture.d.ts.map +1 -1
- package/lib-es/bridge/bridge.fixture.js +12 -82
- package/lib-es/bridge/bridge.fixture.js.map +1 -1
- package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
- package/lib-es/bridge/buildTransaction.js +4 -30
- package/lib-es/bridge/buildTransaction.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.js +8 -13
- package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +14 -28
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/logic.d.ts +8 -13
- package/lib-es/bridge/logic.d.ts.map +1 -1
- package/lib-es/bridge/logic.js +52 -146
- package/lib-es/bridge/logic.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +2 -2
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/signOperation.js +3 -17
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/synchronisation.d.ts +0 -15
- package/lib-es/bridge/synchronisation.d.ts.map +1 -1
- package/lib-es/bridge/synchronisation.js +3 -123
- package/lib-es/bridge/synchronisation.js.map +1 -1
- package/lib-es/constants.d.ts +1 -5
- package/lib-es/constants.d.ts.map +1 -1
- package/lib-es/constants.js +1 -5
- package/lib-es/constants.js.map +1 -1
- package/lib-es/test/bot-specs.d.ts.map +1 -1
- package/lib-es/test/bot-specs.js +2 -41
- package/lib-es/test/bot-specs.js.map +1 -1
- package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
- package/lib-es/test/bridgeDatasetTest.js +59 -43
- package/lib-es/test/bridgeDatasetTest.js.map +1 -1
- package/lib-es/test/speculos-deviceActions.d.ts +0 -1
- package/lib-es/test/speculos-deviceActions.d.ts.map +1 -1
- package/lib-es/test/speculos-deviceActions.js +4 -36
- package/lib-es/test/speculos-deviceActions.js.map +1 -1
- package/lib-es/types/index.d.ts +7 -18
- package/lib-es/types/index.d.ts.map +1 -1
- package/package.json +5 -6
- package/src/__tests__/api/index.test.ts +5 -75
- package/src/__tests__/bridge/buildTransaction.test.ts +3 -85
- package/src/__tests__/bridge/getFeesForTransaction.test.ts +9 -144
- package/src/__tests__/bridge/getTransactionStatus.test.ts +38 -217
- package/src/__tests__/bridge/logic.test.ts +118 -922
- package/src/__tests__/bridge/signOperation.test.ts +2 -141
- package/src/__tests__/bridge/synchronisation.test.ts +71 -1265
- package/src/api/graphql/queries.ts +6 -6
- package/src/api/graphql/types.ts +9 -9
- package/src/api/index.ts +5 -32
- package/src/bridge/bridge.fixture.ts +12 -91
- package/src/bridge/buildTransaction.ts +6 -39
- package/src/bridge/estimateMaxSpendable.ts +1 -1
- package/src/bridge/getFeesForTransaction.ts +9 -14
- package/src/bridge/getTransactionStatus.ts +13 -35
- package/src/bridge/logic.ts +63 -202
- package/src/bridge/prepareTransaction.ts +3 -4
- package/src/bridge/signOperation.ts +3 -19
- package/src/bridge/synchronisation.ts +3 -170
- package/src/constants.ts +1 -12
- package/src/test/bot-specs.ts +3 -63
- package/src/test/bridgeDatasetTest.ts +59 -45
- package/src/test/speculos-deviceActions.ts +4 -40
- package/src/types/index.ts +1 -15
package/src/bridge/logic.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
21
|
-
APTOS_FUNGIBLE_STORE,
|
|
13
|
+
APTOS_COIN_CHANGE,
|
|
22
14
|
BATCH_TRANSFER_TYPES,
|
|
23
15
|
DELEGATION_POOL_TYPES,
|
|
24
16
|
DIRECTION,
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
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
|
-
):
|
|
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 {
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
|
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
|
-
(
|
|
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
|
-
|
|
237
|
-
change
|
|
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
|
-
):
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
250
|
-
|
|
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
|
|
258
|
-
|
|
259
|
-
return address;
|
|
260
|
-
}
|
|
203
|
+
const change_data = writeSetChange.data;
|
|
261
204
|
|
|
262
|
-
|
|
263
|
-
|
|
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<
|
|
209
|
+
const mr = change_data as MoveResource<AptosMoveResource>;
|
|
274
210
|
|
|
275
|
-
if (
|
|
276
|
-
return
|
|
211
|
+
if (mr.type !== APTOS_COIN_CHANGE) {
|
|
212
|
+
return false;
|
|
277
213
|
}
|
|
278
214
|
|
|
279
|
-
|
|
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
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
|
223
|
+
export function getAptosAmounts(
|
|
326
224
|
tx: AptosTransaction,
|
|
327
225
|
address: string,
|
|
328
|
-
): {
|
|
329
|
-
let
|
|
330
|
-
let
|
|
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
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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 {
|
|
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:
|
|
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
|
|
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
|
|
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"];
|