@ledgerhq/coin-tron 5.6.0-nightly.4 → 5.6.0-nightly.6
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/.unimportedrc.json +2 -1
- package/CHANGELOG.md +18 -0
- package/lib/bridge/getEstimateFees.test.js +27 -19
- package/lib/bridge/getEstimateFees.test.js.map +1 -1
- package/lib/bridge/synchronization.d.ts.map +1 -1
- package/lib/bridge/synchronization.integ.test.js +4 -4
- package/lib/bridge/synchronization.integ.test.js.map +1 -1
- package/lib/bridge/synchronization.js +49 -52
- package/lib/bridge/synchronization.js.map +1 -1
- package/lib/bridge/synchronization.test.js +87 -4
- package/lib/bridge/synchronization.test.js.map +1 -1
- package/lib/test/bot-specs.js +2 -2
- package/lib/test/bot-specs.js.map +1 -1
- package/lib-es/bridge/getEstimateFees.test.js +27 -19
- package/lib-es/bridge/getEstimateFees.test.js.map +1 -1
- package/lib-es/bridge/synchronization.d.ts.map +1 -1
- package/lib-es/bridge/synchronization.integ.test.js +1 -1
- package/lib-es/bridge/synchronization.integ.test.js.map +1 -1
- package/lib-es/bridge/synchronization.js +49 -52
- package/lib-es/bridge/synchronization.js.map +1 -1
- package/lib-es/bridge/synchronization.test.js +84 -1
- package/lib-es/bridge/synchronization.test.js.map +1 -1
- package/lib-es/test/bot-specs.js +1 -1
- package/lib-es/test/bot-specs.js.map +1 -1
- package/package.json +5 -5
- package/src/bridge/getEstimateFees.test.ts +28 -19
- package/src/bridge/synchronization.integ.test.ts +1 -1
- package/src/bridge/synchronization.test.ts +92 -1
- package/src/bridge/synchronization.ts +75 -80
- package/src/test/bot-specs.ts +1 -1
|
@@ -6,15 +6,18 @@ import { ACTIVATION_FEES, STANDARD_FEES_NATIVE, STANDARD_FEES_TRC_20 } from "../
|
|
|
6
6
|
import { Account, TokenAccount } from "@ledgerhq/types-live";
|
|
7
7
|
import { Transaction } from "../types";
|
|
8
8
|
|
|
9
|
+
// Mock typed functions
|
|
10
|
+
const mockGetAccount = jest.mocked(getAccount);
|
|
11
|
+
const mockEstimateFees = jest.mocked(estimateFees);
|
|
12
|
+
const mockExtractBandwidthInfo = jest.mocked(extractBandwidthInfo);
|
|
13
|
+
|
|
9
14
|
jest.mock("./utils", () => ({
|
|
10
15
|
extractBandwidthInfo: jest.fn(),
|
|
11
16
|
getEstimatedBlockSize: jest.fn().mockReturnValue(new BigNumber(200)),
|
|
12
17
|
}));
|
|
13
18
|
|
|
14
|
-
jest.mock("../logic"
|
|
15
|
-
|
|
16
|
-
getAccount: jest.fn(),
|
|
17
|
-
}));
|
|
19
|
+
jest.mock("../logic/estimateFees");
|
|
20
|
+
jest.mock("../logic/getAccount");
|
|
18
21
|
|
|
19
22
|
describe("getEstimatedFees", () => {
|
|
20
23
|
const mockAccount = {
|
|
@@ -56,8 +59,8 @@ describe("getEstimatedFees", () => {
|
|
|
56
59
|
|
|
57
60
|
describe("getFeesFromBandwidth", () => {
|
|
58
61
|
it("should return STANDARD_FEES_NATIVE if bandwidth is insufficient", async () => {
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
mockGetAccount.mockResolvedValue([{ address: "mock-contract-address", trc20: [] }]);
|
|
63
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
61
64
|
freeUsed: new BigNumber(0),
|
|
62
65
|
freeLimit: new BigNumber(0),
|
|
63
66
|
gainedUsed: new BigNumber(0),
|
|
@@ -69,8 +72,8 @@ describe("getEstimatedFees", () => {
|
|
|
69
72
|
});
|
|
70
73
|
|
|
71
74
|
it("should return 0 if bandwidth is sufficient", async () => {
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
mockGetAccount.mockResolvedValue([{ address: "mock-contract-address", trc20: [] }]);
|
|
76
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
74
77
|
freeUsed: new BigNumber(0),
|
|
75
78
|
freeLimit: new BigNumber(500),
|
|
76
79
|
gainedUsed: new BigNumber(0),
|
|
@@ -84,8 +87,10 @@ describe("getEstimatedFees", () => {
|
|
|
84
87
|
|
|
85
88
|
describe("getFeesFromAccountActivation", () => {
|
|
86
89
|
it("should return ACTIVATION_FEES if recipient account is not active", async () => {
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
mockGetAccount.mockResolvedValue([]);
|
|
91
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
92
|
+
freeUsed: new BigNumber(0),
|
|
93
|
+
freeLimit: new BigNumber(0),
|
|
89
94
|
gainedUsed: new BigNumber(0),
|
|
90
95
|
gainedLimit: new BigNumber(0),
|
|
91
96
|
});
|
|
@@ -95,8 +100,10 @@ describe("getEstimatedFees", () => {
|
|
|
95
100
|
});
|
|
96
101
|
|
|
97
102
|
it("should return STANDARD_FEES_TRC_20 if recipient has TRC20 balance", async () => {
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
mockGetAccount.mockResolvedValue([{ address: "mock-contract-address", trc20: [] }]);
|
|
104
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
105
|
+
freeUsed: new BigNumber(0),
|
|
106
|
+
freeLimit: new BigNumber(0),
|
|
100
107
|
gainedUsed: new BigNumber(0),
|
|
101
108
|
gainedLimit: new BigNumber(500),
|
|
102
109
|
});
|
|
@@ -106,9 +113,11 @@ describe("getEstimatedFees", () => {
|
|
|
106
113
|
});
|
|
107
114
|
|
|
108
115
|
it("should return estimated fees for TRC20 token transfer", async () => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
mockGetAccount.mockResolvedValue([]);
|
|
117
|
+
mockEstimateFees.mockResolvedValue(1000n);
|
|
118
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
119
|
+
freeUsed: new BigNumber(0),
|
|
120
|
+
freeLimit: new BigNumber(0),
|
|
112
121
|
gainedUsed: new BigNumber(0),
|
|
113
122
|
gainedLimit: new BigNumber(0),
|
|
114
123
|
});
|
|
@@ -120,8 +129,8 @@ describe("getEstimatedFees", () => {
|
|
|
120
129
|
|
|
121
130
|
describe("getEstimatedFees", () => {
|
|
122
131
|
it("should prioritize account activation fees over bandwidth fees", async () => {
|
|
123
|
-
|
|
124
|
-
|
|
132
|
+
mockGetAccount.mockResolvedValue([]);
|
|
133
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
125
134
|
freeUsed: new BigNumber(0),
|
|
126
135
|
freeLimit: new BigNumber(0),
|
|
127
136
|
gainedUsed: new BigNumber(0),
|
|
@@ -133,8 +142,8 @@ describe("getEstimatedFees", () => {
|
|
|
133
142
|
});
|
|
134
143
|
|
|
135
144
|
it("should return bandwidth fees if no account activation is required", async () => {
|
|
136
|
-
|
|
137
|
-
|
|
145
|
+
mockGetAccount.mockResolvedValue([{ address: "mock-address", trc20: [] }]);
|
|
146
|
+
mockExtractBandwidthInfo.mockReturnValue({
|
|
138
147
|
freeUsed: new BigNumber(0),
|
|
139
148
|
freeLimit: new BigNumber(500),
|
|
140
149
|
gainedUsed: new BigNumber(0),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets
|
|
1
|
+
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
2
2
|
import { Account, AccountBridge, SyncConfig, TransactionCommon } from "@ledgerhq/types-live";
|
|
3
3
|
import BigNumber from "bignumber.js";
|
|
4
4
|
import { firstValueFrom, reduce } from "rxjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { makeScanAccounts } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
2
|
-
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets
|
|
2
|
+
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
3
3
|
import { Account, AccountBridge, SyncConfig, TransactionCommon } from "@ledgerhq/types-live";
|
|
4
4
|
import BigNumber from "bignumber.js";
|
|
5
5
|
import { firstValueFrom, reduce } from "rxjs";
|
|
@@ -12,6 +12,9 @@ import { createBridges } from "./index";
|
|
|
12
12
|
import { getAccountShape } from "./synchronization";
|
|
13
13
|
import { setupServer } from "msw/node";
|
|
14
14
|
import { AccountTronAPI } from "../network/types";
|
|
15
|
+
import { getCryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/index";
|
|
16
|
+
|
|
17
|
+
jest.mock("@ledgerhq/coin-framework/crypto-assets/index");
|
|
15
18
|
|
|
16
19
|
const currency = getCryptoCurrencyById("tron");
|
|
17
20
|
const defaultSyncConfig = {
|
|
@@ -115,6 +118,88 @@ describe("sync", () => {
|
|
|
115
118
|
let bridge: ReturnType<typeof createBridges>;
|
|
116
119
|
|
|
117
120
|
beforeAll(() => {
|
|
121
|
+
// Mock the crypto assets store with the expected tokens
|
|
122
|
+
const parentCurrency = {
|
|
123
|
+
type: "CryptoCurrency",
|
|
124
|
+
id: "tron",
|
|
125
|
+
coinType: 195,
|
|
126
|
+
name: "Tron",
|
|
127
|
+
managerAppName: "Tron",
|
|
128
|
+
ticker: "TRX",
|
|
129
|
+
scheme: "tron",
|
|
130
|
+
color: "#D9012C",
|
|
131
|
+
family: "tron",
|
|
132
|
+
blockAvgTime: 9,
|
|
133
|
+
units: [{ name: "TRX", code: "TRX", magnitude: 6 }],
|
|
134
|
+
explorerViews: [
|
|
135
|
+
{
|
|
136
|
+
tx: "https://tronscan.org/#/transaction/$hash",
|
|
137
|
+
address: "https://tronscan.org/#/address/$address",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
keywords: ["trx", "tron"],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const mockTokens = {
|
|
144
|
+
"tron/trc10/1002000": {
|
|
145
|
+
type: "TokenCurrency",
|
|
146
|
+
id: "tron/trc10/1002000",
|
|
147
|
+
contractAddress: "TF5Bn4cJCT6GVeUgyCN4rBhDg42KBrpAjg",
|
|
148
|
+
parentCurrency,
|
|
149
|
+
tokenType: "trc10",
|
|
150
|
+
name: "BitTorrent Old",
|
|
151
|
+
ticker: "BTTOLD",
|
|
152
|
+
delisted: true,
|
|
153
|
+
disableCountervalue: false,
|
|
154
|
+
ledgerSignature:
|
|
155
|
+
"0a0a426974546f7272656e7410061a46304402202e2502f36b00e57be785fc79ec4043abcdd4fdd1b58d737ce123599dffad2cb602201702c307f009d014a553503b499591558b3634ceee4c054c61cedd8aca94c02b",
|
|
156
|
+
units: [{ name: "BitTorrent Old", code: "BTTOLD", magnitude: 6 }],
|
|
157
|
+
},
|
|
158
|
+
"tron/trc20/tla2f6vpqdgre67v1736s7bj8ray5wyju7": {
|
|
159
|
+
type: "TokenCurrency",
|
|
160
|
+
id: "tron/trc20/tla2f6vpqdgre67v1736s7bj8ray5wyju7",
|
|
161
|
+
contractAddress: "TLa2f6VPqDgRE67v1736s7bJ8Ray5wYjU7",
|
|
162
|
+
parentCurrency,
|
|
163
|
+
tokenType: "trc20",
|
|
164
|
+
name: "WINK",
|
|
165
|
+
ticker: "WIN",
|
|
166
|
+
delisted: false,
|
|
167
|
+
disableCountervalue: false,
|
|
168
|
+
ledgerSignature: null,
|
|
169
|
+
units: [{ name: "WINK", code: "WIN", magnitude: 6 }],
|
|
170
|
+
},
|
|
171
|
+
"tron/trc20/tcfll5dx5zjdknwuesxxi1vpwjlvmwzzy9": {
|
|
172
|
+
type: "TokenCurrency",
|
|
173
|
+
id: "tron/trc20/tcfll5dx5zjdknwuesxxi1vpwjlvmwzzy9",
|
|
174
|
+
contractAddress: "TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9",
|
|
175
|
+
parentCurrency,
|
|
176
|
+
tokenType: "trc20",
|
|
177
|
+
name: "JUST GOV",
|
|
178
|
+
ticker: "JST",
|
|
179
|
+
delisted: false,
|
|
180
|
+
disableCountervalue: false,
|
|
181
|
+
ledgerSignature: null,
|
|
182
|
+
units: [{ name: "JUST GOV", code: "JST", magnitude: 18 }],
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
(getCryptoAssetsStore as jest.Mock).mockReturnValue({
|
|
187
|
+
findTokenById: jest.fn().mockImplementation((id: string) => {
|
|
188
|
+
return Promise.resolve(mockTokens[id as keyof typeof mockTokens] || null);
|
|
189
|
+
}),
|
|
190
|
+
findTokenByAddressInCurrency: jest
|
|
191
|
+
.fn()
|
|
192
|
+
.mockImplementation((address: string, currencyId: string) => {
|
|
193
|
+
if (currencyId === "tron") {
|
|
194
|
+
const token = Object.values(mockTokens).find(
|
|
195
|
+
token => token.contractAddress.toLowerCase() === address.toLowerCase(),
|
|
196
|
+
);
|
|
197
|
+
return Promise.resolve(token || null);
|
|
198
|
+
}
|
|
199
|
+
return Promise.resolve(null);
|
|
200
|
+
}),
|
|
201
|
+
});
|
|
202
|
+
|
|
118
203
|
const signer = jest.fn();
|
|
119
204
|
const coinConfig = (): TronCoinConfig => ({
|
|
120
205
|
status: {
|
|
@@ -163,6 +248,12 @@ describe("scanAccounts", () => {
|
|
|
163
248
|
beforeAll(() => {
|
|
164
249
|
spyGetTronAccountNetwork = jest.spyOn(tronNetwork, "getTronAccountNetwork");
|
|
165
250
|
|
|
251
|
+
// Mock the crypto assets store for scanAccounts tests - same as sync tests
|
|
252
|
+
(getCryptoAssetsStore as jest.Mock).mockReturnValue({
|
|
253
|
+
findTokenById: jest.fn().mockResolvedValue(null),
|
|
254
|
+
findTokenByAddressInCurrency: jest.fn().mockResolvedValue(null),
|
|
255
|
+
});
|
|
256
|
+
|
|
166
257
|
coinConfig.setCoinConfig(() => ({
|
|
167
258
|
status: {
|
|
168
259
|
type: "active",
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "@ledgerhq/coin-framework/account";
|
|
6
6
|
import { GetAccountShape, makeSync } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
7
7
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
8
|
-
import {
|
|
8
|
+
import { getCryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/index";
|
|
9
9
|
import { Account, TokenAccount } from "@ledgerhq/types-live";
|
|
10
10
|
import BigNumber from "bignumber.js";
|
|
11
11
|
import compact from "lodash/compact";
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
isAccountEmpty,
|
|
23
23
|
} from "./utils";
|
|
24
24
|
import { getAccount } from "../logic/getAccount";
|
|
25
|
+
import { AccountTronAPI } from "../network/types";
|
|
25
26
|
|
|
26
27
|
type TronToken = {
|
|
27
28
|
key: string;
|
|
@@ -32,6 +33,43 @@ type TronToken = {
|
|
|
32
33
|
|
|
33
34
|
// the balance does not update straightaway so we should ignore recent operations if they are in pending for a bit
|
|
34
35
|
const PREFER_PENDING_OPERATIONS_UNTIL_BLOCK_VALIDATION = 35;
|
|
36
|
+
const MAX_OPERATIONS_PAGE_SIZE = 1000;
|
|
37
|
+
|
|
38
|
+
async function getTrc10Tokens(acc: AccountTronAPI): Promise<TronToken[]> {
|
|
39
|
+
const trc10Tokens: TronToken[] = [];
|
|
40
|
+
for (const { key, value } of get(acc, "assetV2", []) as { key: string; value: number }[]) {
|
|
41
|
+
const tokenInfo = await getCryptoAssetsStore().findTokenById(`tron/trc10/${key}`);
|
|
42
|
+
if (tokenInfo) {
|
|
43
|
+
trc10Tokens.push({
|
|
44
|
+
key,
|
|
45
|
+
type: "trc10",
|
|
46
|
+
tokenId: tokenInfo.id,
|
|
47
|
+
balance: value.toString(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return trc10Tokens;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function getTrc20Tokens(acc: AccountTronAPI, currencyId: string): Promise<TronToken[]> {
|
|
55
|
+
const trc20Tokens: TronToken[] = [];
|
|
56
|
+
for (const trc20 of get(acc, "trc20", []) as Record<string, string>[]) {
|
|
57
|
+
const [[contractAddress, balance]] = Object.entries(trc20);
|
|
58
|
+
const tokenInfo = await getCryptoAssetsStore().findTokenByAddressInCurrency(
|
|
59
|
+
contractAddress,
|
|
60
|
+
currencyId,
|
|
61
|
+
);
|
|
62
|
+
if (tokenInfo) {
|
|
63
|
+
trc20Tokens.push({
|
|
64
|
+
key: contractAddress,
|
|
65
|
+
type: "trc20",
|
|
66
|
+
tokenId: tokenInfo.id,
|
|
67
|
+
balance,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return trc20Tokens;
|
|
72
|
+
}
|
|
35
73
|
|
|
36
74
|
export const getAccountShape: GetAccountShape<TronAccount> = async (
|
|
37
75
|
{ initialAccount, currency, address, derivationMode },
|
|
@@ -58,14 +96,10 @@ export const getAccountShape: GetAccountShape<TronAccount> = async (
|
|
|
58
96
|
}
|
|
59
97
|
|
|
60
98
|
const acc = tronAcc[0];
|
|
61
|
-
const cacheTransactionInfoById = initialAccount
|
|
62
|
-
? {
|
|
63
|
-
...(initialAccount?.tronResources?.cacheTransactionInfoById || {}),
|
|
64
|
-
}
|
|
65
|
-
: {};
|
|
99
|
+
const cacheTransactionInfoById = initialAccount?.tronResources?.cacheTransactionInfoById || {};
|
|
66
100
|
const operationsPageSize = Math.min(
|
|
67
|
-
|
|
68
|
-
getOperationsPageSize(initialAccount
|
|
101
|
+
MAX_OPERATIONS_PAGE_SIZE,
|
|
102
|
+
getOperationsPageSize(initialAccount?.id, syncConfig),
|
|
69
103
|
);
|
|
70
104
|
// FIXME: this is not optional especially that we might already have initialAccount
|
|
71
105
|
// use minimalOperationsBuilderSync to reconciliate and KEEP REF
|
|
@@ -86,68 +120,36 @@ export const getAccountShape: GetAccountShape<TronAccount> = async (
|
|
|
86
120
|
parentTxs.map(tx => txInfoToOperation(accountId, address, tx)),
|
|
87
121
|
);
|
|
88
122
|
|
|
89
|
-
const trc10Tokens =
|
|
90
|
-
|
|
91
|
-
const tokenInfo = findTokenById(`tron/trc10/${key}`);
|
|
92
|
-
if (tokenInfo) {
|
|
93
|
-
accumulator.push({
|
|
94
|
-
key,
|
|
95
|
-
type: "trc10",
|
|
96
|
-
tokenId: tokenInfo.id,
|
|
97
|
-
balance: value.toString(),
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
return accumulator;
|
|
101
|
-
},
|
|
102
|
-
[],
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const trc20Tokens = get(acc, "trc20", []).reduce(
|
|
106
|
-
(accumulator: TronToken[], trc20: Record<string, string>) => {
|
|
107
|
-
const [[contractAddress, balance]] = Object.entries(trc20);
|
|
108
|
-
const tokenInfo = findTokenByAddressInCurrency(contractAddress, currency.id);
|
|
109
|
-
if (tokenInfo) {
|
|
110
|
-
accumulator.push({
|
|
111
|
-
key: contractAddress,
|
|
112
|
-
type: "trc20",
|
|
113
|
-
tokenId: tokenInfo.id,
|
|
114
|
-
balance,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
return accumulator;
|
|
118
|
-
},
|
|
119
|
-
[],
|
|
120
|
-
);
|
|
123
|
+
const trc10Tokens = await getTrc10Tokens(acc);
|
|
124
|
+
const trc20Tokens = await getTrc20Tokens(acc, currency.id);
|
|
121
125
|
|
|
122
126
|
const { blacklistedTokenIds = [] } = syncConfig;
|
|
123
127
|
|
|
124
|
-
const subAccounts: TokenAccount[] =
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}),
|
|
150
|
-
);
|
|
128
|
+
const subAccounts: TokenAccount[] = [];
|
|
129
|
+
for (const { key, tokenId, balance } of trc10Tokens.concat(trc20Tokens)) {
|
|
130
|
+
const token = await getCryptoAssetsStore().findTokenById(tokenId);
|
|
131
|
+
if (!token || blacklistedTokenIds.includes(tokenId)) continue;
|
|
132
|
+
const id = encodeTokenAccountId(accountId, token);
|
|
133
|
+
const tokenTxs = txs.filter(tx => tx.tokenId === key);
|
|
134
|
+
const operations = compact(tokenTxs.map(tx => txInfoToOperation(id, address, tx)));
|
|
135
|
+
const maybeExistingSubAccount = initialAccount?.subAccounts?.find(a => a.id === id);
|
|
136
|
+
const bnBalance = new BigNumber(balance);
|
|
137
|
+
const sub: TokenAccount = {
|
|
138
|
+
type: "TokenAccount",
|
|
139
|
+
id,
|
|
140
|
+
parentId: accountId,
|
|
141
|
+
token,
|
|
142
|
+
balance: bnBalance,
|
|
143
|
+
spendableBalance: bnBalance,
|
|
144
|
+
operationsCount: operations.length,
|
|
145
|
+
operations,
|
|
146
|
+
pendingOperations: maybeExistingSubAccount ? maybeExistingSubAccount.pendingOperations : [],
|
|
147
|
+
creationDate: operations.length > 0 ? operations[operations.length - 1].date : new Date(),
|
|
148
|
+
swapHistory: maybeExistingSubAccount ? maybeExistingSubAccount.swapHistory : [],
|
|
149
|
+
balanceHistoryCache: emptyHistoryCache, // calculated in the jsHelpers
|
|
150
|
+
};
|
|
151
|
+
subAccounts.push(sub);
|
|
152
|
+
}
|
|
151
153
|
|
|
152
154
|
// Filter blacklisted tokens from the initial account's subAccounts
|
|
153
155
|
// Could be use to filter out tokens that got their CAL id changed
|
|
@@ -231,19 +233,12 @@ export const postSync = (initial: TronAccount, parent: TronAccount): TronAccount
|
|
|
231
233
|
const mergeSubAccounts = (subAccounts1: TokenAccount[], subAccounts2: TokenAccount[]) => {
|
|
232
234
|
const existingIds = new Set(subAccounts1.map(subAccount => subAccount.id));
|
|
233
235
|
const filteredSubAccounts2: TokenAccount[] = subAccounts2
|
|
234
|
-
.
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
...subAccount,
|
|
241
|
-
balance: new BigNumber(0),
|
|
242
|
-
spendableBalance: new BigNumber(0),
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
})
|
|
246
|
-
.filter((elt): elt is NonNullable<typeof elt> => elt !== null);
|
|
236
|
+
.filter(subAccount => !existingIds.has(subAccount.id))
|
|
237
|
+
.map(subAccount => ({
|
|
238
|
+
...subAccount,
|
|
239
|
+
balance: new BigNumber(0),
|
|
240
|
+
spendableBalance: new BigNumber(0),
|
|
241
|
+
}));
|
|
247
242
|
|
|
248
243
|
return subAccounts1.concat(filteredSubAccounts2);
|
|
249
244
|
};
|
package/src/test/bot-specs.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { BigNumber } from "bignumber.js";
|
|
|
2
2
|
import invariant from "invariant";
|
|
3
3
|
import expect from "expect";
|
|
4
4
|
import type { Transaction } from "../types";
|
|
5
|
-
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets
|
|
5
|
+
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets";
|
|
6
6
|
import { parseCurrencyUnit } from "@ledgerhq/coin-framework/currencies";
|
|
7
7
|
import { botTest, pickSiblings } from "@ledgerhq/coin-framework/bot/specs";
|
|
8
8
|
import type { AppSpec, TransactionDestinationTestInput } from "@ledgerhq/coin-framework/bot/types";
|