@ledgerhq/live-common 21.18.0 → 21.19.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.
- package/lib/__tests__/test-helpers/setup.js +1 -0
- package/lib/__tests__/test-helpers/setup.js.map +1 -1
- package/lib/account/addAccounts.d.ts.map +1 -1
- package/lib/account/addAccounts.js +3 -2
- package/lib/account/addAccounts.js.map +1 -1
- package/lib/account/helpers.d.ts.map +1 -1
- package/lib/account/helpers.js +1 -0
- package/lib/account/helpers.js.map +1 -1
- package/lib/api/Ethereum.d.ts.map +1 -1
- package/lib/api/Ethereum.js +2 -1
- package/lib/api/Ethereum.js.map +1 -1
- package/lib/api/explorerConfig/index.d.ts.map +1 -1
- package/lib/api/explorerConfig/index.js +0 -4
- package/lib/api/explorerConfig/index.js.map +1 -1
- package/lib/bridge/jsHelpers.d.ts.map +1 -1
- package/lib/bridge/jsHelpers.js +9 -8
- package/lib/bridge/jsHelpers.js.map +1 -1
- package/lib/env.d.ts +10 -5
- package/lib/env.d.ts.map +1 -1
- package/lib/env.js +5 -0
- package/lib/env.js.map +1 -1
- package/lib/env.react.d.ts +1 -1
- package/lib/env.react.d.ts.map +1 -1
- package/lib/families/bitcoin/getAccountNetworkInfo.d.ts.map +1 -1
- package/lib/families/bitcoin/getAccountNetworkInfo.js +12 -2
- package/lib/families/bitcoin/getAccountNetworkInfo.js.map +1 -1
- package/lib/families/bitcoin/test-dataset.js +2 -2
- package/lib/families/bitcoin/test-dataset.js.map +1 -1
- package/lib/families/bitcoin/types.d.ts +1 -0
- package/lib/families/bitcoin/types.d.ts.map +1 -1
- package/lib/families/bitcoin/types.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/explorer/index.d.ts +1 -0
- package/lib/families/bitcoin/wallet-btc/explorer/index.d.ts.map +1 -1
- package/lib/families/bitcoin/wallet-btc/explorer/index.js +19 -0
- package/lib/families/bitcoin/wallet-btc/explorer/index.js.map +1 -1
- package/lib/families/bitcoin/wallet-btc/explorer/types.d.ts +1 -0
- package/lib/families/bitcoin/wallet-btc/explorer/types.d.ts.map +1 -1
- package/lib/families/ethereum/bridge/js.d.ts.map +1 -1
- package/lib/families/ethereum/bridge/js.js +3 -0
- package/lib/families/ethereum/bridge/js.js.map +1 -1
- package/lib/families/ethereum/modules/erc1155.d.ts.map +1 -1
- package/lib/families/ethereum/modules/erc1155.js +21 -9
- package/lib/families/ethereum/modules/erc1155.js.map +1 -1
- package/lib/families/ethereum/modules/erc721.d.ts +3 -1
- package/lib/families/ethereum/modules/erc721.d.ts.map +1 -1
- package/lib/families/ethereum/modules/erc721.js +101 -7
- package/lib/families/ethereum/modules/erc721.js.map +1 -1
- package/lib/families/ethereum/modules/index.d.ts +5 -0
- package/lib/families/ethereum/modules/index.d.ts.map +1 -1
- package/lib/families/ethereum/modules/index.js +9 -1
- package/lib/families/ethereum/modules/index.js.map +1 -1
- package/lib/families/ethereum/nft.test.d.ts +2 -0
- package/lib/families/ethereum/nft.test.d.ts.map +1 -0
- package/lib/families/ethereum/nft.test.js +360 -0
- package/lib/families/ethereum/nft.test.js.map +1 -0
- package/lib/families/ethereum/signOperation.d.ts.map +1 -1
- package/lib/families/ethereum/signOperation.js +3 -12
- package/lib/families/ethereum/signOperation.js.map +1 -1
- package/lib/families/ethereum/synchronisation.d.ts.map +1 -1
- package/lib/families/ethereum/synchronisation.js +21 -38
- package/lib/families/ethereum/synchronisation.js.map +1 -1
- package/lib/families/ethereum/synchronisation.test.js.map +1 -1
- package/lib/families/ethereum/transaction.d.ts.map +1 -1
- package/lib/families/ethereum/transaction.js +4 -4
- package/lib/families/ethereum/transaction.js.map +1 -1
- package/lib/families/ethereum/types.d.ts +2 -0
- package/lib/families/ethereum/types.d.ts.map +1 -1
- package/lib/families/ethereum/types.js.map +1 -1
- package/lib/hw/uninstallApp.d.ts.map +1 -1
- package/lib/hw/uninstallApp.js +1 -1
- package/lib/hw/uninstallApp.js.map +1 -1
- package/lib/nft/helpers.js +2 -3
- package/lib/nft/helpers.js.map +1 -1
- package/lib/nft/index.d.ts +1 -0
- package/lib/nft/index.d.ts.map +1 -1
- package/lib/nft/index.js +1 -0
- package/lib/nft/index.js.map +1 -1
- package/lib/nft/support.d.ts +4 -0
- package/lib/nft/support.d.ts.map +1 -0
- package/lib/nft/support.js +16 -0
- package/lib/nft/support.js.map +1 -0
- package/lib/reconciliation.d.ts.map +1 -1
- package/lib/reconciliation.js +5 -1
- package/lib/reconciliation.js.map +1 -1
- package/package.json +4 -4
- package/src/.DS_Store +0 -0
- package/src/__tests__/.DS_Store +0 -0
- package/src/__tests__/__snapshots__/all.libcore.ts.snap +10 -49
- package/src/__tests__/test-helpers/setup.ts +1 -0
- package/src/account/addAccounts.ts +3 -2
- package/src/account/helpers.ts +1 -0
- package/src/api/Ethereum.ts +4 -4
- package/src/api/explorerConfig/index.ts +0 -4
- package/src/bridge/jsHelpers.ts +9 -8
- package/src/currencies/{.DS_Store → __snapshots__/.DS_Store} +0 -0
- package/src/env.ts +5 -0
- package/src/families/bitcoin/getAccountNetworkInfo.ts +8 -1
- package/src/families/bitcoin/test-dataset.ts +2 -2
- package/src/families/bitcoin/types.ts +1 -0
- package/src/families/bitcoin/wallet-btc/explorer/index.ts +7 -0
- package/src/families/bitcoin/wallet-btc/explorer/types.ts +1 -0
- package/src/families/ethereum/bridge/js.ts +8 -1
- package/src/families/ethereum/modules/erc1155.ts +22 -7
- package/src/families/ethereum/modules/erc721.ts +42 -4
- package/src/families/ethereum/modules/index.ts +20 -0
- package/src/families/ethereum/nft.test.ts +263 -0
- package/src/families/ethereum/signOperation.ts +3 -16
- package/src/families/ethereum/synchronisation.test.ts +1 -0
- package/src/families/ethereum/synchronisation.ts +104 -113
- package/src/families/ethereum/transaction.ts +8 -4
- package/src/families/ethereum/types.ts +2 -0
- package/src/hw/uninstallApp.ts +13 -8
- package/src/nft/helpers.ts +2 -2
- package/src/nft/index.ts +1 -0
- package/src/nft/support.ts +16 -0
- package/src/reconciliation.ts +4 -1
- package/src/types/account.ts +1 -1
- package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +0 -6152
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import "../../__tests__/test-helpers/setup";
|
|
2
|
+
import BigNumber from "bignumber.js";
|
|
3
|
+
import { reduce } from "rxjs/operators";
|
|
4
|
+
import { fromAccountRaw, toAccountRaw, toNFTRaw } from "../../account";
|
|
5
|
+
import type { Account, AccountRaw, NFT } from "../../types";
|
|
6
|
+
import { getAccountBridge } from "../../bridge";
|
|
7
|
+
import { makeBridgeCacheSystem } from "../../bridge/cache";
|
|
8
|
+
import { patchAccount } from "../../reconciliation";
|
|
9
|
+
import { setEnv } from "../../env";
|
|
10
|
+
import { mergeNfts } from "../../bridge/jsHelpers";
|
|
11
|
+
import { encodeNftId } from "../../nft";
|
|
12
|
+
|
|
13
|
+
jest.setTimeout(120000);
|
|
14
|
+
|
|
15
|
+
const gaspardAccount: AccountRaw = {
|
|
16
|
+
id: "js:1:ethereum:0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a:",
|
|
17
|
+
seedIdentifier: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
18
|
+
name: "G4sp4rd",
|
|
19
|
+
derivationMode: "",
|
|
20
|
+
index: 0,
|
|
21
|
+
freshAddress: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
22
|
+
freshAddressPath: "44'/60'/0'/0/0",
|
|
23
|
+
freshAddresses: [],
|
|
24
|
+
pendingOperations: [],
|
|
25
|
+
operations: [],
|
|
26
|
+
currencyId: "ethereum",
|
|
27
|
+
unitMagnitude: 18,
|
|
28
|
+
balance: "",
|
|
29
|
+
blockHeight: 0,
|
|
30
|
+
lastSyncDate: "",
|
|
31
|
+
xpub: "",
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
const gaspardPolygonAccount: AccountRaw = {
|
|
36
|
+
id: "js:1:polygon:0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a:",
|
|
37
|
+
seedIdentifier: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
38
|
+
name: "G4sp4rd",
|
|
39
|
+
derivationMode: "",
|
|
40
|
+
index: 0,
|
|
41
|
+
freshAddress: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
42
|
+
freshAddressPath: "44'/60'/0'/0/0",
|
|
43
|
+
freshAddresses: [],
|
|
44
|
+
pendingOperations: [],
|
|
45
|
+
operations: [],
|
|
46
|
+
currencyId: "polygon",
|
|
47
|
+
unitMagnitude: 18,
|
|
48
|
+
balance: "",
|
|
49
|
+
blockHeight: 0,
|
|
50
|
+
lastSyncDate: "",
|
|
51
|
+
xpub: "",
|
|
52
|
+
};
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
const gaspardBscAccount: AccountRaw = {
|
|
56
|
+
id: "js:1:bsc:0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a:",
|
|
57
|
+
seedIdentifier: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
58
|
+
name: "G4sp4rd",
|
|
59
|
+
derivationMode: "",
|
|
60
|
+
index: 0,
|
|
61
|
+
freshAddress: "0xb98d10d9f6d07ba283bfd21b2dfec050f9ae282a",
|
|
62
|
+
freshAddressPath: "44'/60'/0'/0/0",
|
|
63
|
+
freshAddresses: [],
|
|
64
|
+
pendingOperations: [],
|
|
65
|
+
operations: [],
|
|
66
|
+
currencyId: "bsc",
|
|
67
|
+
unitMagnitude: 18,
|
|
68
|
+
balance: "",
|
|
69
|
+
blockHeight: 0,
|
|
70
|
+
lastSyncDate: "",
|
|
71
|
+
xpub: "",
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
async function sync(account, withNFT = true) {
|
|
75
|
+
const bridge = getAccountBridge(account);
|
|
76
|
+
const blacklistedTokenIds = [];
|
|
77
|
+
setEnv("NFT", withNFT);
|
|
78
|
+
const r = await bridge
|
|
79
|
+
.sync(account, {
|
|
80
|
+
paginationConfig: {},
|
|
81
|
+
blacklistedTokenIds,
|
|
82
|
+
})
|
|
83
|
+
.pipe(reduce((a, f: (arg0: Account) => Account) => f(a), account))
|
|
84
|
+
.toPromise();
|
|
85
|
+
setEnv("NFT", false);
|
|
86
|
+
return r;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const localCache = {};
|
|
90
|
+
const cache = makeBridgeCacheSystem({
|
|
91
|
+
saveData(c, d) {
|
|
92
|
+
localCache[c.id] = d;
|
|
93
|
+
return Promise.resolve();
|
|
94
|
+
},
|
|
95
|
+
getData(c) {
|
|
96
|
+
return Promise.resolve(localCache[c.id]);
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("nft merging", () => {
|
|
101
|
+
const makeNFT = (tokenId: string, contract: string, amount: number): NFT => ({
|
|
102
|
+
id: encodeNftId("test", contract, tokenId),
|
|
103
|
+
tokenId,
|
|
104
|
+
amount: new BigNumber(amount),
|
|
105
|
+
collection: {
|
|
106
|
+
contract,
|
|
107
|
+
standard: "erc721",
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
const oldNfts = [
|
|
111
|
+
makeNFT("1", "contract1", 10),
|
|
112
|
+
makeNFT("2", "contract1", 1),
|
|
113
|
+
makeNFT("3", "contract2", 6),
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
test("should remove first NFT and return new array with same refs", () => {
|
|
117
|
+
const nfts = [makeNFT("2", "contract1", 1), makeNFT("3", "contract2", 6)];
|
|
118
|
+
const newNfts = mergeNfts(oldNfts, nfts);
|
|
119
|
+
|
|
120
|
+
expect(newNfts.map(toNFTRaw)).toEqual(nfts.map(toNFTRaw));
|
|
121
|
+
expect(oldNfts[1]).toBe(newNfts[0]);
|
|
122
|
+
expect(oldNfts[2]).toBe(newNfts[1]);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("should remove any NFT and return new array with same refs", () => {
|
|
126
|
+
const nfts = [makeNFT("1", "contract1", 10), makeNFT("3", "contract2", 6)];
|
|
127
|
+
const newNfts = mergeNfts(oldNfts, nfts);
|
|
128
|
+
|
|
129
|
+
expect(newNfts.map(toNFTRaw)).toEqual(nfts.map(toNFTRaw));
|
|
130
|
+
expect(oldNfts[0]).toBe(newNfts[0]);
|
|
131
|
+
expect(oldNfts[2]).toBe(newNfts[1]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("should change NFT amount and return new array with new ref", () => {
|
|
135
|
+
const nfts = [
|
|
136
|
+
makeNFT("1", "contract1", 10),
|
|
137
|
+
makeNFT("2", "contract1", 5),
|
|
138
|
+
makeNFT("3", "contract2", 6),
|
|
139
|
+
];
|
|
140
|
+
const addToNft1 = mergeNfts(oldNfts, nfts);
|
|
141
|
+
|
|
142
|
+
expect(addToNft1.map(toNFTRaw)).toEqual(nfts.map(toNFTRaw));
|
|
143
|
+
expect(oldNfts[0]).toBe(addToNft1[0]);
|
|
144
|
+
expect(oldNfts[1]).not.toBe(addToNft1[1]);
|
|
145
|
+
expect(oldNfts[2]).toBe(addToNft1[2]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("should add NFT and return new array with new ref", () => {
|
|
149
|
+
const nfts = [
|
|
150
|
+
makeNFT("1", "contract1", 10),
|
|
151
|
+
makeNFT("2", "contract1", 1),
|
|
152
|
+
makeNFT("3", "contract2", 6),
|
|
153
|
+
makeNFT("4", "contract2", 4),
|
|
154
|
+
];
|
|
155
|
+
const addToNft1 = mergeNfts(oldNfts, nfts);
|
|
156
|
+
|
|
157
|
+
expect(addToNft1.map(toNFTRaw)).toEqual(
|
|
158
|
+
[
|
|
159
|
+
makeNFT("4", "contract2", 4),
|
|
160
|
+
makeNFT("1", "contract1", 10),
|
|
161
|
+
makeNFT("2", "contract1", 1),
|
|
162
|
+
makeNFT("3", "contract2", 6),
|
|
163
|
+
].map(toNFTRaw)
|
|
164
|
+
);
|
|
165
|
+
expect(oldNfts[0]).toBe(addToNft1[1]);
|
|
166
|
+
expect(oldNfts[1]).toBe(addToNft1[2]);
|
|
167
|
+
expect(oldNfts[2]).toBe(addToNft1[3]);
|
|
168
|
+
expect(addToNft1[0]).toBe(nfts[3]);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe("gaspard NFT on ethereum", () => {
|
|
173
|
+
let account = fromAccountRaw(gaspardAccount);
|
|
174
|
+
|
|
175
|
+
test("first sync & have nfts", async () => {
|
|
176
|
+
await cache.prepareCurrency(account.currency);
|
|
177
|
+
account = await sync(account);
|
|
178
|
+
expect(account.nfts?.length || 0).not.toBe(0);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("remove half NFTs will restore them with operations still here", async () => {
|
|
182
|
+
const copy = {
|
|
183
|
+
...account,
|
|
184
|
+
nfts: account.nfts?.slice(Math.ceil((account.nfts?.length || 0) / 2)),
|
|
185
|
+
};
|
|
186
|
+
const resync = await sync(copy);
|
|
187
|
+
expect(resync.nfts).toEqual(account.nfts);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("remove half NFTs will restore them with missing operations too", async () => {
|
|
191
|
+
const copy = {
|
|
192
|
+
...account,
|
|
193
|
+
operations: [],
|
|
194
|
+
nfts: account.nfts?.slice(Math.ceil((account.nfts?.length || 0) / 2)),
|
|
195
|
+
};
|
|
196
|
+
const resync = await sync(copy);
|
|
197
|
+
expect(resync.nfts).toEqual(account.nfts);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("remove half NFTs will restore them with half operations", async () => {
|
|
201
|
+
const halfOps = Math.ceil(account.operations.length / 2);
|
|
202
|
+
const copy = {
|
|
203
|
+
...account,
|
|
204
|
+
operations: account.operations.slice(halfOps),
|
|
205
|
+
nfts: account.nfts?.slice(Math.ceil((account.nfts?.length || 0) / 2)),
|
|
206
|
+
};
|
|
207
|
+
const resync = await sync(copy);
|
|
208
|
+
expect(resync.nfts).toEqual(account.nfts);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("patchAccount restore new NFTs correctly", async () => {
|
|
212
|
+
const copy = {
|
|
213
|
+
...account,
|
|
214
|
+
operations: [],
|
|
215
|
+
nfts: account.nfts?.slice(Math.ceil((account.nfts?.length || 0) / 2)),
|
|
216
|
+
};
|
|
217
|
+
const newAccount = patchAccount(copy, toAccountRaw(account));
|
|
218
|
+
expect(newAccount.nfts).toEqual(account.nfts);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("start account with .nfts and disable the NFT flag should make it disappear", async () => {
|
|
222
|
+
expect(account.nfts).not.toBeFalsy();
|
|
223
|
+
const resync = await sync(account, false);
|
|
224
|
+
expect(resync.nfts).toBeFalsy();
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("start account without .nfts and enable the NFT flag should make it appear", async () => {
|
|
228
|
+
const first = await sync(account, false);
|
|
229
|
+
expect(first.nfts).toBeFalsy();
|
|
230
|
+
const second = await sync(first, true);
|
|
231
|
+
expect(second.nfts).not.toBeFalsy();
|
|
232
|
+
expect(second.nfts).toEqual(account.nfts);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("no nft should be on quantity 0 or negative", async () => {
|
|
236
|
+
expect(account.nfts?.find((n) => !n.amount.gt(0))).toEqual(undefined);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
/*
|
|
241
|
+
// this is never ending here... have to disable this test... (backend issue)
|
|
242
|
+
describe("gaspard NFT on polygon", () => {
|
|
243
|
+
let account = fromAccountRaw(gaspardPolygonAccount);
|
|
244
|
+
test("first sync", async () => {
|
|
245
|
+
await cache.prepareCurrency(account.currency);
|
|
246
|
+
account = await sync(account);
|
|
247
|
+
});
|
|
248
|
+
test(".nfts shouldn't be visible", () => {
|
|
249
|
+
expect(account.nfts).toBeFalsy();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
describe("gaspard NFT on bsc", () => {
|
|
255
|
+
let account = fromAccountRaw(gaspardBscAccount);
|
|
256
|
+
test("first sync", async () => {
|
|
257
|
+
await cache.prepareCurrency(account.currency);
|
|
258
|
+
account = await sync(account);
|
|
259
|
+
});
|
|
260
|
+
test(".nfts shouldn't be visible", () => {
|
|
261
|
+
expect(account.nfts).toBeFalsy();
|
|
262
|
+
});
|
|
263
|
+
});
|
|
@@ -13,7 +13,7 @@ import { getGasLimit, buildEthereumTx } from "./transaction";
|
|
|
13
13
|
import { apiForCurrency } from "../../api/Ethereum";
|
|
14
14
|
import { withDevice } from "../../hw/deviceAccess";
|
|
15
15
|
import { modes } from "./modules";
|
|
16
|
-
import {
|
|
16
|
+
import { isNFTActive } from "../../nft";
|
|
17
17
|
export const signOperation = ({
|
|
18
18
|
account,
|
|
19
19
|
deviceId,
|
|
@@ -57,12 +57,11 @@ export const signOperation = ({
|
|
|
57
57
|
nonce
|
|
58
58
|
);
|
|
59
59
|
const to = eip55.encode("0x" + tx.to.toString("hex"));
|
|
60
|
-
const chainId = tx.getChainId();
|
|
61
60
|
const value = new BigNumber(
|
|
62
61
|
"0x" + (tx.value.toString("hex") || "0")
|
|
63
62
|
);
|
|
64
63
|
const eth = new Eth(transport);
|
|
65
|
-
if (
|
|
64
|
+
if (isNFTActive(account.currency)) {
|
|
66
65
|
eth.setLoadConfig({
|
|
67
66
|
// FIXME drop this after LL-8001
|
|
68
67
|
nftExplorerBaseURL:
|
|
@@ -99,19 +98,7 @@ export const signOperation = ({
|
|
|
99
98
|
type: "device-signature-granted",
|
|
100
99
|
});
|
|
101
100
|
// Second, we re-set some tx fields from the device signature
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (chainId > 0) {
|
|
105
|
-
// EIP155 support. check/recalc signature v value.
|
|
106
|
-
const rv = parseInt(v, 16);
|
|
107
|
-
let cv = chainId * 2 + 35;
|
|
108
|
-
|
|
109
|
-
if (rv !== cv && (rv & cv) !== rv) {
|
|
110
|
-
cv += 1; // add signature v bit.
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
v = cv.toString(16);
|
|
114
|
-
}
|
|
101
|
+
const v = result.v;
|
|
115
102
|
|
|
116
103
|
tx.v = Buffer.from(v, "hex");
|
|
117
104
|
tx.r = Buffer.from(result.r, "hex");
|
|
@@ -6,6 +6,7 @@ import type { Account, SubAccount } from "../../types";
|
|
|
6
6
|
import { getAccountBridge } from "../../bridge";
|
|
7
7
|
import { makeBridgeCacheSystem } from "../../bridge/cache";
|
|
8
8
|
import { ethereum1 } from "./test-dataset";
|
|
9
|
+
|
|
9
10
|
describe("blacklistedTokenIds functionality", () => {
|
|
10
11
|
const account = fromAccountRaw(ethereum1);
|
|
11
12
|
const localCache = {};
|
|
@@ -15,13 +15,12 @@ import {
|
|
|
15
15
|
} from "../../account";
|
|
16
16
|
import { listTokensForCryptoCurrency } from "../../currencies";
|
|
17
17
|
import { encodeAccountId } from "../../account";
|
|
18
|
-
import type { Operation, TokenAccount, Account
|
|
18
|
+
import type { Operation, TokenAccount, Account } from "../../types";
|
|
19
19
|
import { API, apiForCurrency, Tx } from "../../api/Ethereum";
|
|
20
20
|
import { digestTokenAccounts, prepareTokenAccounts } from "./modules";
|
|
21
21
|
import { findTokenByAddressInCurrency } from "@ledgerhq/cryptoassets";
|
|
22
|
-
import { encodeNftId, nftsFromOperations } from "../../nft";
|
|
22
|
+
import { encodeNftId, isNFTActive, nftsFromOperations } from "../../nft";
|
|
23
23
|
import { NFT_VERSION } from "./versions";
|
|
24
|
-
import { getEnv } from "../../env";
|
|
25
24
|
|
|
26
25
|
export const getAccountShape: GetAccountShape = async (
|
|
27
26
|
infoInput,
|
|
@@ -41,24 +40,24 @@ export const getAccountShape: GetAccountShape = async (
|
|
|
41
40
|
const initialStableOperations = initialAccount
|
|
42
41
|
? stableOperations(initialAccount)
|
|
43
42
|
: [];
|
|
43
|
+
const shouldNFTBeActive = isNFTActive(currency);
|
|
44
44
|
// fetch transactions, incrementally if possible
|
|
45
45
|
const mostRecentStableOperation = initialStableOperations[0];
|
|
46
46
|
// when new tokens are added / blacklist changes, we need to sync again because we need to go through all operations again
|
|
47
47
|
const syncHash =
|
|
48
48
|
JSON.stringify(blacklistedTokenIds || []) +
|
|
49
49
|
"_" +
|
|
50
|
+
shouldNFTBeActive +
|
|
51
|
+
"_" +
|
|
50
52
|
listTokensForCryptoCurrency(currency, {
|
|
51
53
|
withDelisted: true,
|
|
52
54
|
}).length;
|
|
53
|
-
const
|
|
54
|
-
const firstNftSync =
|
|
55
|
-
getEnv("NFT") && typeof initialAccount?.nfts === "undefined";
|
|
55
|
+
const outdatedSyncHash = initialAccount?.syncHash !== syncHash;
|
|
56
56
|
const pullFromBlockHash =
|
|
57
57
|
initialAccount &&
|
|
58
58
|
areAllOperationsLoaded(initialAccount) &&
|
|
59
59
|
mostRecentStableOperation &&
|
|
60
|
-
!
|
|
61
|
-
!firstNftSync &&
|
|
60
|
+
!outdatedSyncHash &&
|
|
62
61
|
NFT_VERSION
|
|
63
62
|
? mostRecentStableOperation.blockHash
|
|
64
63
|
: undefined;
|
|
@@ -83,10 +82,8 @@ export const getAccountShape: GetAccountShape = async (
|
|
|
83
82
|
let newOps = flatMap(txs, txToOps({ address, id: accountId, currency }));
|
|
84
83
|
// extracting out the sub operations by token account
|
|
85
84
|
const perTokenAccountIdOperations = {};
|
|
86
|
-
// extracting and concat all nft operations for an account
|
|
87
|
-
const flatNftOps: Operation[] = [];
|
|
88
85
|
newOps.forEach((op) => {
|
|
89
|
-
const { subOperations
|
|
86
|
+
const { subOperations } = op;
|
|
90
87
|
|
|
91
88
|
if (subOperations?.length) {
|
|
92
89
|
subOperations.forEach((sop) => {
|
|
@@ -97,10 +94,6 @@ export const getAccountShape: GetAccountShape = async (
|
|
|
97
94
|
perTokenAccountIdOperations[sop.accountId].push(sop);
|
|
98
95
|
});
|
|
99
96
|
}
|
|
100
|
-
|
|
101
|
-
if (nftOperations?.length) {
|
|
102
|
-
nftOperations.forEach((nop) => flatNftOps.push(nop));
|
|
103
|
-
}
|
|
104
97
|
});
|
|
105
98
|
const subAccountsExisting = {};
|
|
106
99
|
initialAccount?.subAccounts?.forEach((a) => {
|
|
@@ -173,8 +166,8 @@ export const getAccountShape: GetAccountShape = async (
|
|
|
173
166
|
}));
|
|
174
167
|
const operations = mergeOps(initialStableOperations, newOps);
|
|
175
168
|
|
|
176
|
-
const nfts =
|
|
177
|
-
? mergeNfts(initialAccount?.nfts,
|
|
169
|
+
const nfts = isNFTActive(currency)
|
|
170
|
+
? mergeNfts(initialAccount?.nfts, nftsFromOperations(operations))
|
|
178
171
|
: undefined;
|
|
179
172
|
|
|
180
173
|
const accountShape: Partial<Account> = {
|
|
@@ -334,91 +327,23 @@ const txToOps =
|
|
|
334
327
|
});
|
|
335
328
|
|
|
336
329
|
// Creating NFTOps from transfer events related to ERC721 only
|
|
337
|
-
const erc721Operations =
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
if (!sending && !receiving) {
|
|
349
|
-
return [];
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
const all: Operation[] = [];
|
|
353
|
-
|
|
354
|
-
if (sending) {
|
|
355
|
-
const type = "NFT_OUT";
|
|
356
|
-
all.push({
|
|
357
|
-
id: `${nftId}-${hash}-${type}`,
|
|
358
|
-
senders: [sender],
|
|
359
|
-
recipients: [receiver],
|
|
360
|
-
contract,
|
|
361
|
-
fee,
|
|
362
|
-
standard: "ERC721",
|
|
363
|
-
tokenId,
|
|
364
|
-
value: new BigNumber(1),
|
|
365
|
-
hash,
|
|
366
|
-
type,
|
|
367
|
-
blockHeight,
|
|
368
|
-
blockHash,
|
|
369
|
-
date,
|
|
370
|
-
transactionSequenceNumber,
|
|
371
|
-
accountId: id,
|
|
372
|
-
extra: {},
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (receiving) {
|
|
377
|
-
const type = "NFT_IN";
|
|
378
|
-
all.push({
|
|
379
|
-
id: `${nftId}-${hash}-${type}`,
|
|
380
|
-
senders: [sender],
|
|
381
|
-
recipients: [receiver],
|
|
382
|
-
contract,
|
|
383
|
-
fee,
|
|
384
|
-
standard: "ERC721",
|
|
385
|
-
tokenId,
|
|
386
|
-
value: new BigNumber(1),
|
|
387
|
-
hash,
|
|
388
|
-
type,
|
|
389
|
-
blockHeight,
|
|
390
|
-
blockHash,
|
|
391
|
-
date,
|
|
392
|
-
transactionSequenceNumber,
|
|
393
|
-
accountId: id,
|
|
394
|
-
extra: {},
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return all;
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
// Creating NFTOps from transfer events related to ERC1155 only
|
|
402
|
-
const erc1155Operations = !erc1155_transfer_events
|
|
403
|
-
? []
|
|
404
|
-
: flatMap(erc1155_transfer_events, (event) => {
|
|
405
|
-
const sender = safeEncodeEIP55(event.sender);
|
|
406
|
-
const receiver = safeEncodeEIP55(event.receiver);
|
|
407
|
-
const contract = safeEncodeEIP55(event.contract);
|
|
408
|
-
const operator = safeEncodeEIP55(event.operator);
|
|
409
|
-
const sending = addr === sender;
|
|
410
|
-
const receiving = addr === receiver;
|
|
411
|
-
|
|
412
|
-
if (!sending && !receiving) {
|
|
413
|
-
return [];
|
|
414
|
-
}
|
|
330
|
+
const erc721Operations =
|
|
331
|
+
!erc721_transfer_events || !isNFTActive(currency)
|
|
332
|
+
? []
|
|
333
|
+
: flatMap(erc721_transfer_events, (event) => {
|
|
334
|
+
const sender = safeEncodeEIP55(event.sender);
|
|
335
|
+
const receiver = safeEncodeEIP55(event.receiver);
|
|
336
|
+
const contract = safeEncodeEIP55(event.contract);
|
|
337
|
+
const tokenId = event.token_id;
|
|
338
|
+
const nftId = encodeNftId(id, event.contract, tokenId);
|
|
339
|
+
const sending = addr === sender;
|
|
340
|
+
const receiving = addr === receiver;
|
|
415
341
|
|
|
416
|
-
|
|
342
|
+
if (!sending && !receiving) {
|
|
343
|
+
return [];
|
|
344
|
+
}
|
|
417
345
|
|
|
418
|
-
|
|
419
|
-
const tokenId = transfer.id;
|
|
420
|
-
const value = new BigNumber(transfer.value);
|
|
421
|
-
const nftId = encodeNftId(id, event.contract, tokenId);
|
|
346
|
+
const all: Operation[] = [];
|
|
422
347
|
|
|
423
348
|
if (sending) {
|
|
424
349
|
const type = "NFT_OUT";
|
|
@@ -428,10 +353,9 @@ const txToOps =
|
|
|
428
353
|
recipients: [receiver],
|
|
429
354
|
contract,
|
|
430
355
|
fee,
|
|
431
|
-
|
|
432
|
-
standard: "ERC1155",
|
|
356
|
+
standard: "ERC721",
|
|
433
357
|
tokenId,
|
|
434
|
-
value,
|
|
358
|
+
value: new BigNumber(1),
|
|
435
359
|
hash,
|
|
436
360
|
type,
|
|
437
361
|
blockHeight,
|
|
@@ -451,10 +375,9 @@ const txToOps =
|
|
|
451
375
|
recipients: [receiver],
|
|
452
376
|
contract,
|
|
453
377
|
fee,
|
|
454
|
-
|
|
455
|
-
standard: "ERC1155",
|
|
378
|
+
standard: "ERC721",
|
|
456
379
|
tokenId,
|
|
457
|
-
value,
|
|
380
|
+
value: new BigNumber(1),
|
|
458
381
|
hash,
|
|
459
382
|
type,
|
|
460
383
|
blockHeight,
|
|
@@ -465,15 +388,88 @@ const txToOps =
|
|
|
465
388
|
extra: {},
|
|
466
389
|
});
|
|
467
390
|
}
|
|
391
|
+
|
|
392
|
+
return all;
|
|
468
393
|
});
|
|
469
394
|
|
|
470
|
-
|
|
471
|
-
|
|
395
|
+
// Creating NFTOps from transfer events related to ERC1155 only
|
|
396
|
+
const erc1155Operations =
|
|
397
|
+
!erc1155_transfer_events || !isNFTActive(currency)
|
|
398
|
+
? []
|
|
399
|
+
: flatMap(erc1155_transfer_events, (event) => {
|
|
400
|
+
const sender = safeEncodeEIP55(event.sender);
|
|
401
|
+
const receiver = safeEncodeEIP55(event.receiver);
|
|
402
|
+
const contract = safeEncodeEIP55(event.contract);
|
|
403
|
+
const operator = safeEncodeEIP55(event.operator);
|
|
404
|
+
const sending = addr === sender;
|
|
405
|
+
const receiving = addr === receiver;
|
|
406
|
+
|
|
407
|
+
if (!sending && !receiving) {
|
|
408
|
+
return [];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const all: Operation[] = [];
|
|
412
|
+
|
|
413
|
+
event.transfers.forEach((transfer) => {
|
|
414
|
+
const tokenId = transfer.id;
|
|
415
|
+
const value = new BigNumber(transfer.value);
|
|
416
|
+
const nftId = encodeNftId(id, event.contract, tokenId);
|
|
417
|
+
|
|
418
|
+
if (sending) {
|
|
419
|
+
const type = "NFT_OUT";
|
|
420
|
+
all.push({
|
|
421
|
+
id: `${nftId}-${hash}-${type}`,
|
|
422
|
+
senders: [sender],
|
|
423
|
+
recipients: [receiver],
|
|
424
|
+
contract,
|
|
425
|
+
fee,
|
|
426
|
+
operator,
|
|
427
|
+
standard: "ERC1155",
|
|
428
|
+
tokenId,
|
|
429
|
+
value,
|
|
430
|
+
hash,
|
|
431
|
+
type,
|
|
432
|
+
blockHeight,
|
|
433
|
+
blockHash,
|
|
434
|
+
date,
|
|
435
|
+
transactionSequenceNumber,
|
|
436
|
+
accountId: id,
|
|
437
|
+
extra: {},
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (receiving) {
|
|
442
|
+
const type = "NFT_IN";
|
|
443
|
+
all.push({
|
|
444
|
+
id: `${nftId}-${hash}-${type}`,
|
|
445
|
+
senders: [sender],
|
|
446
|
+
recipients: [receiver],
|
|
447
|
+
contract,
|
|
448
|
+
fee,
|
|
449
|
+
operator,
|
|
450
|
+
standard: "ERC1155",
|
|
451
|
+
tokenId,
|
|
452
|
+
value,
|
|
453
|
+
hash,
|
|
454
|
+
type,
|
|
455
|
+
blockHeight,
|
|
456
|
+
blockHash,
|
|
457
|
+
date,
|
|
458
|
+
transactionSequenceNumber,
|
|
459
|
+
accountId: id,
|
|
460
|
+
extra: {},
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
return all;
|
|
466
|
+
});
|
|
472
467
|
|
|
473
468
|
const nftOperations = erc721Operations
|
|
474
469
|
.concat(erc1155Operations)
|
|
475
470
|
/** @warning is this necessary ? Do we need the operations to be chronologically organised for LLD/LLM ? */
|
|
476
471
|
.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
472
|
+
|
|
477
473
|
const ops: Operation[] = [];
|
|
478
474
|
|
|
479
475
|
if (sending) {
|
|
@@ -619,11 +615,6 @@ async function loadERC20Balances(tokenAccounts, address, api) {
|
|
|
619
615
|
.filter(Boolean);
|
|
620
616
|
}
|
|
621
617
|
|
|
622
|
-
function getNfts(nftOperations: Operation[]): NFT[] {
|
|
623
|
-
const nfts: NFT[] = nftsFromOperations(nftOperations);
|
|
624
|
-
return nfts.filter((nft) => nft.amount.gt(0));
|
|
625
|
-
}
|
|
626
|
-
|
|
627
618
|
const SAFE_REORG_THRESHOLD = 80;
|
|
628
619
|
|
|
629
620
|
function stableOperations(a) {
|
|
@@ -90,12 +90,14 @@ export const formatTransaction = (
|
|
|
90
90
|
const header = (() => {
|
|
91
91
|
switch (t.mode) {
|
|
92
92
|
case "erc721.transfer":
|
|
93
|
-
return `${t.mode.toUpperCase()} Collection: ${t.collection}
|
|
94
|
-
t.
|
|
95
|
-
}`;
|
|
93
|
+
return `${t.mode.toUpperCase()} Collection: ${t.collection} (${
|
|
94
|
+
t.collectionName || ""
|
|
95
|
+
}) TokenId: ${t.tokenIds?.[0]}`;
|
|
96
96
|
case "erc1155.transfer":
|
|
97
97
|
return (
|
|
98
|
-
`${t.mode.toUpperCase()} Collection: ${t.collection}
|
|
98
|
+
`${t.mode.toUpperCase()} Collection: ${t.collection} (${
|
|
99
|
+
t.collectionName || ""
|
|
100
|
+
})` +
|
|
99
101
|
t.tokenIds
|
|
100
102
|
?.map((tokenId, index) => {
|
|
101
103
|
return `\n - TokenId: ${tokenId} Quantity: ${
|
|
@@ -153,6 +155,7 @@ export const fromTransactionRaw = (tr: TransactionRaw): Transaction => {
|
|
|
153
155
|
feesStrategy: tr.feesStrategy,
|
|
154
156
|
tokenIds: tr.tokenIds,
|
|
155
157
|
collection: tr.collection,
|
|
158
|
+
collectionName: tr.collectionName,
|
|
156
159
|
quantities: tr.quantities?.map((q) => new BigNumber(q)),
|
|
157
160
|
};
|
|
158
161
|
};
|
|
@@ -180,6 +183,7 @@ export const toTransactionRaw = (t: Transaction): TransactionRaw => {
|
|
|
180
183
|
feesStrategy: t.feesStrategy,
|
|
181
184
|
tokenIds: t.tokenIds,
|
|
182
185
|
collection: t.collection,
|
|
186
|
+
collectionName: t.collectionName,
|
|
183
187
|
quantities: t.quantities?.map((q) => q.toString()),
|
|
184
188
|
};
|
|
185
189
|
};
|
|
@@ -38,6 +38,7 @@ export type Transaction = TransactionCommon & {
|
|
|
38
38
|
networkInfo: NetworkInfo | null | undefined;
|
|
39
39
|
allowZeroAmount?: boolean;
|
|
40
40
|
collection?: string;
|
|
41
|
+
collectionName?: string;
|
|
41
42
|
tokenIds?: string[];
|
|
42
43
|
quantities?: BigNumber[];
|
|
43
44
|
};
|
|
@@ -54,6 +55,7 @@ export type TransactionRaw = TransactionCommonRaw & {
|
|
|
54
55
|
allowZeroAmount?: boolean;
|
|
55
56
|
tokenIds?: string[];
|
|
56
57
|
collection?: string;
|
|
58
|
+
collectionName?: string;
|
|
57
59
|
quantities?: string[];
|
|
58
60
|
};
|
|
59
61
|
export type TypedMessage = {
|