@ledgerhq/coin-multiversx 0.7.0 → 0.8.0-nightly.20251108023448
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/CHANGELOG.md +15 -0
- package/lib/api/sdk.d.ts.map +1 -1
- package/lib/api/sdk.js +3 -1
- package/lib/api/sdk.js.map +1 -1
- package/lib/buildOptimisticOperation.js +1 -1
- package/lib/buildOptimisticOperation.js.map +1 -1
- package/lib/buildSubAccounts.d.ts.map +1 -1
- package/lib/buildSubAccounts.js +72 -53
- package/lib/buildSubAccounts.js.map +1 -1
- package/lib/deviceTransactionConfig.js +1 -1
- package/lib/deviceTransactionConfig.js.map +1 -1
- package/lib/encode.d.ts +1 -1
- package/lib/encode.d.ts.map +1 -1
- package/lib/encode.js +2 -2
- package/lib/encode.js.map +1 -1
- package/lib/prepareTransaction.js +1 -1
- package/lib/prepareTransaction.js.map +1 -1
- package/lib/signOperation.js +1 -1
- package/lib/signOperation.js.map +1 -1
- package/lib/speculos-deviceActions.d.ts.map +1 -1
- package/lib/speculos-deviceActions.js +4 -4
- package/lib/speculos-deviceActions.js.map +1 -1
- package/lib-es/api/sdk.d.ts.map +1 -1
- package/lib-es/api/sdk.js +3 -1
- package/lib-es/api/sdk.js.map +1 -1
- package/lib-es/buildOptimisticOperation.js +1 -1
- package/lib-es/buildOptimisticOperation.js.map +1 -1
- package/lib-es/buildSubAccounts.d.ts.map +1 -1
- package/lib-es/buildSubAccounts.js +69 -50
- package/lib-es/buildSubAccounts.js.map +1 -1
- package/lib-es/deviceTransactionConfig.js +1 -1
- package/lib-es/deviceTransactionConfig.js.map +1 -1
- package/lib-es/encode.d.ts +1 -1
- package/lib-es/encode.d.ts.map +1 -1
- package/lib-es/encode.js +2 -2
- package/lib-es/encode.js.map +1 -1
- package/lib-es/prepareTransaction.js +1 -1
- package/lib-es/prepareTransaction.js.map +1 -1
- package/lib-es/signOperation.js +1 -1
- package/lib-es/signOperation.js.map +1 -1
- package/lib-es/speculos-deviceActions.d.ts.map +1 -1
- package/lib-es/speculos-deviceActions.js +4 -4
- package/lib-es/speculos-deviceActions.js.map +1 -1
- package/package.json +4 -4
- package/src/api/sdk.ts +4 -1
- package/src/buildOptimisticOperation.ts +1 -1
- package/src/buildSubAccounts.ts +110 -54
- package/src/deviceTransactionConfig.ts +1 -1
- package/src/encode.ts +2 -2
- package/src/prepareTransaction.ts +1 -1
- package/src/signOperation.ts +1 -1
- package/src/speculos-deviceActions.ts +4 -5
package/src/buildSubAccounts.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/index";
|
|
2
2
|
import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
3
3
|
import { Account, SyncConfig, TokenAccount } from "@ledgerhq/types-live";
|
|
4
4
|
import BigNumber from "bignumber.js";
|
|
@@ -6,6 +6,7 @@ import { emptyHistoryCache, encodeTokenAccountId } from "@ledgerhq/coin-framewor
|
|
|
6
6
|
import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
7
7
|
import { getESDTOperations, getAccountESDTTokens } from "./api";
|
|
8
8
|
import { addPrefixToken, extractTokenId } from "./logic";
|
|
9
|
+
import { ESDTToken } from "./types";
|
|
9
10
|
|
|
10
11
|
async function buildMultiversXESDTTokenAccount({
|
|
11
12
|
parentAccountId,
|
|
@@ -41,27 +42,114 @@ async function buildMultiversXESDTTokenAccount({
|
|
|
41
42
|
return tokenAccount;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function buildExistingAccountMaps(
|
|
46
|
+
existingAccount: Account | null | undefined,
|
|
47
|
+
blacklistedTokenIds: string[],
|
|
48
|
+
): { existingAccountByTicker: Record<string, TokenAccount>; existingAccountTickers: string[] } {
|
|
49
|
+
const existingAccountByTicker: Record<string, TokenAccount> = {};
|
|
50
|
+
const existingAccountTickers: string[] = [];
|
|
51
|
+
|
|
52
|
+
if (!existingAccount?.subAccounts) {
|
|
53
|
+
return { existingAccountByTicker, existingAccountTickers };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
for (const existingSubAccount of existingAccount.subAccounts) {
|
|
57
|
+
if (existingSubAccount.type !== "TokenAccount") continue;
|
|
58
|
+
|
|
59
|
+
const { ticker, id } = existingSubAccount.token;
|
|
60
|
+
|
|
61
|
+
if (!blacklistedTokenIds.includes(id)) {
|
|
62
|
+
existingAccountTickers.push(ticker);
|
|
63
|
+
existingAccountByTicker[ticker] = existingSubAccount;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return { existingAccountByTicker, existingAccountTickers };
|
|
68
|
+
}
|
|
69
|
+
|
|
44
70
|
async function syncESDTTokenAccountOperations(
|
|
45
71
|
tokenAccount: TokenAccount,
|
|
46
72
|
address: string,
|
|
47
73
|
): Promise<TokenAccount> {
|
|
48
74
|
const oldOperations = tokenAccount?.operations || [];
|
|
49
|
-
// Needed for incremental synchronisation
|
|
50
75
|
const startAt = oldOperations.length ? Math.floor(oldOperations[0].date.valueOf() / 1000) : 0;
|
|
51
76
|
|
|
52
77
|
const tokenIdentifierHex = extractTokenId(tokenAccount.token.id);
|
|
53
78
|
const tokenIdentifier = Buffer.from(tokenIdentifierHex, "hex").toString();
|
|
54
79
|
|
|
55
|
-
// Merge new operations with the previously synced ones
|
|
56
80
|
const newOperations = await getESDTOperations(tokenAccount.id, address, tokenIdentifier, startAt);
|
|
57
81
|
const operations = mergeOps(oldOperations, newOperations);
|
|
58
82
|
|
|
59
83
|
if (operations === oldOperations) return tokenAccount;
|
|
60
84
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
return {
|
|
86
|
+
...tokenAccount,
|
|
87
|
+
operations,
|
|
88
|
+
operationsCount: operations.length,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function updateTokenAccountBalance(
|
|
93
|
+
tokenAccount: TokenAccount,
|
|
94
|
+
newBalance: BigNumber,
|
|
95
|
+
): Promise<TokenAccount> {
|
|
96
|
+
if (newBalance.eq(tokenAccount.balance)) {
|
|
97
|
+
return tokenAccount;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
...tokenAccount,
|
|
102
|
+
balance: newBalance,
|
|
103
|
+
spendableBalance: newBalance,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function processESDT({
|
|
108
|
+
esdt,
|
|
109
|
+
accountId,
|
|
110
|
+
accountAddress,
|
|
111
|
+
existingAccountByTicker,
|
|
112
|
+
existingAccountTickers,
|
|
113
|
+
blacklistedTokenIds,
|
|
114
|
+
}: {
|
|
115
|
+
esdt: ESDTToken;
|
|
116
|
+
accountId: string;
|
|
117
|
+
accountAddress: string;
|
|
118
|
+
existingAccountByTicker: Record<string, TokenAccount>;
|
|
119
|
+
existingAccountTickers: string[];
|
|
120
|
+
blacklistedTokenIds: string[];
|
|
121
|
+
}): Promise<TokenAccount | null> {
|
|
122
|
+
const esdtIdentifierHex = Buffer.from(esdt.identifier).toString("hex");
|
|
123
|
+
const token = await getCryptoAssetsStore().findTokenById(addPrefixToken(esdtIdentifierHex));
|
|
124
|
+
|
|
125
|
+
if (!token || blacklistedTokenIds.includes(token.id)) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const existingTokenAccount = existingAccountByTicker[token.ticker];
|
|
130
|
+
const balance = new BigNumber(esdt.balance);
|
|
131
|
+
|
|
132
|
+
let tokenAccount: TokenAccount;
|
|
133
|
+
|
|
134
|
+
if (existingTokenAccount) {
|
|
135
|
+
const syncedTokenAccount = await syncESDTTokenAccountOperations(
|
|
136
|
+
existingTokenAccount,
|
|
137
|
+
accountAddress,
|
|
138
|
+
);
|
|
139
|
+
tokenAccount = await updateTokenAccountBalance(syncedTokenAccount, balance);
|
|
140
|
+
} else {
|
|
141
|
+
tokenAccount = await buildMultiversXESDTTokenAccount({
|
|
142
|
+
parentAccountId: accountId,
|
|
143
|
+
accountAddress,
|
|
144
|
+
token,
|
|
145
|
+
balance,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
existingAccountTickers.push(token.ticker);
|
|
150
|
+
existingAccountByTicker[token.ticker] = tokenAccount;
|
|
151
|
+
|
|
152
|
+
return tokenAccount;
|
|
65
153
|
}
|
|
66
154
|
|
|
67
155
|
async function MultiversXBuildESDTTokenAccounts({
|
|
@@ -79,56 +167,24 @@ async function MultiversXBuildESDTTokenAccounts({
|
|
|
79
167
|
const { blacklistedTokenIds = [] } = syncConfig;
|
|
80
168
|
const tokenAccounts: TokenAccount[] = [];
|
|
81
169
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (existingAccount && existingAccount.subAccounts) {
|
|
87
|
-
for (const existingSubAccount of existingAccount.subAccounts) {
|
|
88
|
-
if (existingSubAccount.type === "TokenAccount") {
|
|
89
|
-
const { ticker, id } = existingSubAccount.token;
|
|
90
|
-
|
|
91
|
-
if (!blacklistedTokenIds.includes(id)) {
|
|
92
|
-
existingAccountTickers.push(ticker);
|
|
93
|
-
existingAccountByTicker[ticker] = existingSubAccount;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
170
|
+
const { existingAccountByTicker, existingAccountTickers } = buildExistingAccountMaps(
|
|
171
|
+
existingAccount,
|
|
172
|
+
blacklistedTokenIds,
|
|
173
|
+
);
|
|
98
174
|
|
|
99
175
|
const accountESDTs = await getAccountESDTTokens(accountAddress);
|
|
100
176
|
for (const esdt of accountESDTs) {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
} else {
|
|
114
|
-
const inputTokenAccount = tokenAccount;
|
|
115
|
-
tokenAccount = await syncESDTTokenAccountOperations(inputTokenAccount, accountAddress);
|
|
116
|
-
const balance = new BigNumber(esdt.balance);
|
|
117
|
-
if (!balance.eq(tokenAccount.balance)) {
|
|
118
|
-
// only recreate the object if balance changed
|
|
119
|
-
if (inputTokenAccount === tokenAccount) {
|
|
120
|
-
tokenAccount = { ...tokenAccount };
|
|
121
|
-
}
|
|
122
|
-
tokenAccount.balance = balance;
|
|
123
|
-
tokenAccount.spendableBalance = balance;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (tokenAccount) {
|
|
128
|
-
tokenAccounts.push(tokenAccount);
|
|
129
|
-
existingAccountTickers.push(token.ticker);
|
|
130
|
-
existingAccountByTicker[token.ticker] = tokenAccount;
|
|
131
|
-
}
|
|
177
|
+
const tokenAccount = await processESDT({
|
|
178
|
+
esdt,
|
|
179
|
+
accountId,
|
|
180
|
+
accountAddress,
|
|
181
|
+
existingAccountByTicker,
|
|
182
|
+
existingAccountTickers,
|
|
183
|
+
blacklistedTokenIds,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (tokenAccount) {
|
|
187
|
+
tokenAccounts.push(tokenAccount);
|
|
132
188
|
}
|
|
133
189
|
}
|
|
134
190
|
|
|
@@ -21,7 +21,7 @@ async function getDeviceTransactionConfig({
|
|
|
21
21
|
const isEsdtTransfer = subAccountId !== undefined && subAccountId !== null;
|
|
22
22
|
|
|
23
23
|
if (isEsdtTransfer) {
|
|
24
|
-
const { token } = decodeTokenAccountId(subAccountId);
|
|
24
|
+
const { token } = await decodeTokenAccountId(subAccountId);
|
|
25
25
|
|
|
26
26
|
if (token) {
|
|
27
27
|
fields.push({
|
package/src/encode.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { Transaction } from "./types";
|
|
|
4
4
|
import { extractTokenId } from "./logic";
|
|
5
5
|
|
|
6
6
|
export class MultiversXEncodeTransaction {
|
|
7
|
-
static ESDTTransfer(t: Transaction, ta: TokenAccount): string {
|
|
8
|
-
const { token } = decodeTokenAccountId(ta.id);
|
|
7
|
+
static async ESDTTransfer(t: Transaction, ta: TokenAccount): Promise<string> {
|
|
8
|
+
const { token } = await decodeTokenAccountId(ta.id);
|
|
9
9
|
const tokenIdentifierHex = token && extractTokenId(token.id);
|
|
10
10
|
let amountHex = t.useAllAmount ? ta.balance.toString(16) : t.amount.toString(16);
|
|
11
11
|
|
|
@@ -26,7 +26,7 @@ export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"
|
|
|
26
26
|
null;
|
|
27
27
|
|
|
28
28
|
if (tokenAccount) {
|
|
29
|
-
preparedTx.data = MultiversXEncodeTransaction.ESDTTransfer(transaction, tokenAccount);
|
|
29
|
+
preparedTx.data = await MultiversXEncodeTransaction.ESDTTransfer(transaction, tokenAccount);
|
|
30
30
|
preparedTx.gasLimit = GAS.ESDT_TRANSFER;
|
|
31
31
|
} else {
|
|
32
32
|
switch (transaction.mode) {
|
package/src/signOperation.ts
CHANGED
|
@@ -36,7 +36,7 @@ export const buildSignOperation =
|
|
|
36
36
|
await signerContext(deviceId, signer => signer.setAddress(account.freshAddressPath));
|
|
37
37
|
|
|
38
38
|
if (tokenAccount) {
|
|
39
|
-
const { token } = decodeTokenAccountId(tokenAccount.id);
|
|
39
|
+
const { token } = await decodeTokenAccountId(tokenAccount.id);
|
|
40
40
|
if (!token) {
|
|
41
41
|
throw new Error("Invalid token");
|
|
42
42
|
}
|
|
@@ -190,7 +190,7 @@ export const acceptEsdtTransferTransaction: DeviceAction<Transaction, any> = dev
|
|
|
190
190
|
{
|
|
191
191
|
title: "Token",
|
|
192
192
|
button: SpeculosButton.RIGHT,
|
|
193
|
-
expectedValue: ({ account, transaction }) => {
|
|
193
|
+
expectedValue: async ({ account, transaction }) => {
|
|
194
194
|
const { subAccounts } = account;
|
|
195
195
|
const { subAccountId } = transaction;
|
|
196
196
|
const tokenAccount = !subAccountId
|
|
@@ -201,15 +201,14 @@ export const acceptEsdtTransferTransaction: DeviceAction<Transaction, any> = dev
|
|
|
201
201
|
throw new Error();
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
const { token } = decodeTokenAccountId(tokenAccount.id);
|
|
205
|
-
|
|
204
|
+
const { token } = await decodeTokenAccountId(tokenAccount.id);
|
|
206
205
|
return token?.name ?? "";
|
|
207
206
|
},
|
|
208
207
|
},
|
|
209
208
|
{
|
|
210
209
|
title: "Value",
|
|
211
210
|
button: SpeculosButton.RIGHT,
|
|
212
|
-
expectedValue: ({ account, transaction }) => {
|
|
211
|
+
expectedValue: async ({ account, transaction }) => {
|
|
213
212
|
const { subAccounts } = account;
|
|
214
213
|
const { subAccountId } = transaction;
|
|
215
214
|
const tokenAccount = !subAccountId
|
|
@@ -220,7 +219,7 @@ export const acceptEsdtTransferTransaction: DeviceAction<Transaction, any> = dev
|
|
|
220
219
|
throw new Error();
|
|
221
220
|
}
|
|
222
221
|
|
|
223
|
-
const { token } = decodeTokenAccountId(tokenAccount.id);
|
|
222
|
+
const { token } = await decodeTokenAccountId(tokenAccount.id);
|
|
224
223
|
if (!token) {
|
|
225
224
|
throw new Error();
|
|
226
225
|
}
|