@ledgerhq/coin-tron 3.1.0-nightly.2 → 4.0.0-next.0
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 +6 -20
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +1 -6
- package/lib/api/index.js.map +1 -1
- package/lib/api/index.test.js +2 -7
- package/lib/api/index.test.js.map +1 -1
- package/lib/logic/listOperations.d.ts +1 -7
- package/lib/logic/listOperations.d.ts.map +1 -1
- package/lib/logic/listOperations.integ.test.js +4 -56
- package/lib/logic/listOperations.integ.test.js.map +1 -1
- package/lib/logic/listOperations.js +7 -20
- package/lib/logic/listOperations.js.map +1 -1
- package/lib/logic/listOperations.unit.test.js +3 -5
- package/lib/logic/listOperations.unit.test.js.map +1 -1
- package/lib/network/format.js +2 -2
- package/lib/network/format.js.map +1 -1
- package/lib/network/index.d.ts +1 -5
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +5 -56
- package/lib/network/index.js.map +1 -1
- package/lib/network/index.test.js +28 -93
- package/lib/network/index.test.js.map +1 -1
- package/lib/network/types.fixture.d.ts +48 -384
- package/lib/network/types.fixture.d.ts.map +1 -1
- package/lib/network/types.fixture.js.map +1 -1
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +1 -6
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/api/index.test.js +2 -7
- package/lib-es/api/index.test.js.map +1 -1
- package/lib-es/logic/listOperations.d.ts +1 -7
- package/lib-es/logic/listOperations.d.ts.map +1 -1
- package/lib-es/logic/listOperations.integ.test.js +5 -57
- package/lib-es/logic/listOperations.integ.test.js.map +1 -1
- package/lib-es/logic/listOperations.js +7 -19
- package/lib-es/logic/listOperations.js.map +1 -1
- package/lib-es/logic/listOperations.unit.test.js +4 -6
- package/lib-es/logic/listOperations.unit.test.js.map +1 -1
- package/lib-es/network/format.js +2 -2
- package/lib-es/network/format.js.map +1 -1
- package/lib-es/network/index.d.ts +1 -5
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +5 -56
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/index.test.js +28 -93
- package/lib-es/network/index.test.js.map +1 -1
- package/lib-es/network/types.fixture.d.ts +48 -384
- package/lib-es/network/types.fixture.d.ts.map +1 -1
- package/lib-es/network/types.fixture.js.map +1 -1
- package/package.json +6 -6
- package/src/api/index.test.ts +2 -7
- package/src/api/index.ts +1 -7
- package/src/logic/listOperations.integ.test.ts +5 -74
- package/src/logic/listOperations.ts +7 -31
- package/src/logic/listOperations.unit.test.ts +4 -8
- package/src/network/format.ts +2 -2
- package/src/network/index.test.ts +27 -120
- package/src/network/index.ts +9 -80
- package/src/network/types.fixture.ts +1 -1
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
import { HttpResponse, http } from "msw";
|
|
2
|
-
import { setupServer
|
|
2
|
+
import { setupServer } from "msw/node";
|
|
3
3
|
import { TRANSACTION_DETAIL_FIXTURE, TRANSACTION_FIXTURE, TRC20_FIXTURE } from "./types.fixture";
|
|
4
4
|
import coinConfig from "../config";
|
|
5
5
|
import { defaultFetchParams, fetchTronAccountTxs } from ".";
|
|
6
|
-
import { assert } from "console";
|
|
7
6
|
|
|
8
7
|
const TRON_BASE_URL_TEST = "https://httpbin.org";
|
|
9
8
|
|
|
10
|
-
const
|
|
11
|
-
`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions`,
|
|
12
|
-
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions/trc20`,
|
|
17
|
-
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
`${TRON_BASE_URL_TEST}/wallet/gettransactioninfobyid`,
|
|
22
|
-
({ request }) => {
|
|
9
|
+
const handlers = [
|
|
10
|
+
http.get(`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions`, () => {
|
|
11
|
+
// const url = new URL(request.url);
|
|
12
|
+
// const _ = url.searchParams.get("get_detail");
|
|
13
|
+
return HttpResponse.json(TRANSACTION_FIXTURE);
|
|
14
|
+
}),
|
|
15
|
+
http.get(`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions/trc20`, () => {
|
|
16
|
+
// const url = new URL(request.url);
|
|
17
|
+
// const _ = url.searchParams.get("get_detail");
|
|
18
|
+
return HttpResponse.json(TRC20_FIXTURE);
|
|
19
|
+
}),
|
|
20
|
+
http.get(`${TRON_BASE_URL_TEST}/wallet/gettransactioninfobyid`, ({ request }) => {
|
|
23
21
|
const url = new URL(request.url);
|
|
24
22
|
const value = url.searchParams.get("value") ?? "UNKNOWN";
|
|
25
23
|
return HttpResponse.json(TRANSACTION_DETAIL_FIXTURE(value));
|
|
26
|
-
},
|
|
27
|
-
|
|
24
|
+
}),
|
|
25
|
+
];
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const mockServer = setupServer(...handlers);
|
|
28
|
+
|
|
29
|
+
describe("fetchTronAccountTxs", () => {
|
|
30
|
+
beforeAll(() => {
|
|
31
31
|
coinConfig.setCoinConfig(() => ({
|
|
32
32
|
status: {
|
|
33
33
|
type: "active",
|
|
@@ -37,26 +37,16 @@ function doBeforeAll(server: SetupServerApi): () => void {
|
|
|
37
37
|
},
|
|
38
38
|
}));
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function doBeforeEach(server: SetupServerApi): () => void {
|
|
45
|
-
return () => server.resetHandlers();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function doAfterAll(server: SetupServerApi): () => void {
|
|
49
|
-
return () => server.close();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
describe("fetchTronAccountTxs", () => {
|
|
53
|
-
const handlers = [defaultGetTransactionsH, defaultGetTrc20TransactionsH, defaultGetTxInfo];
|
|
40
|
+
mockServer.listen();
|
|
41
|
+
});
|
|
54
42
|
|
|
55
|
-
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
mockServer.resetHandlers();
|
|
45
|
+
});
|
|
56
46
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
afterAll(() => {
|
|
48
|
+
mockServer.close();
|
|
49
|
+
});
|
|
60
50
|
|
|
61
51
|
it("convert correctly operations from the blockchain", async () => {
|
|
62
52
|
// WHEN
|
|
@@ -74,86 +64,3 @@ describe("fetchTronAccountTxs", () => {
|
|
|
74
64
|
expect(tx!.to).toEqual("TAVrrARNdnjHgCGMQYeQV7hv4PSu7mVsMj");
|
|
75
65
|
});
|
|
76
66
|
});
|
|
77
|
-
|
|
78
|
-
describe("fetchTronAccountTxs with invalid TRC20 (see LIVE-18992)", () => {
|
|
79
|
-
const tx1Hash = "1237889e91c0ebbe389436c341865df09921f8f0c029d9286102372cbaadc585";
|
|
80
|
-
const tx2Hash = "154164dd04482ae78f930033d0ad95730b8b19fde171a33c3920d18c228426ab";
|
|
81
|
-
let counterGetTrc20 = 0;
|
|
82
|
-
const invalidTrc20Handler = http.get(
|
|
83
|
-
`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions/trc20`,
|
|
84
|
-
() => {
|
|
85
|
-
const ret: any = JSON.parse(JSON.stringify(TRC20_FIXTURE));
|
|
86
|
-
switch (counterGetTrc20) {
|
|
87
|
-
case 0: {
|
|
88
|
-
const tx1 = ret.data[0];
|
|
89
|
-
assert(tx1.transaction_id == tx1Hash);
|
|
90
|
-
ret.data[0].detail.ret = undefined;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
case 1: {
|
|
94
|
-
const tx2 = ret.data[1];
|
|
95
|
-
assert(tx2.transaction_id == tx2Hash);
|
|
96
|
-
ret.data[1].detail.ret = undefined;
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
default:
|
|
100
|
-
// the 3rd call should not happen
|
|
101
|
-
// because merging the 1st and 2nd results is enough to have a full set, perfectly well formed
|
|
102
|
-
throw "results should be merged after 2 calls";
|
|
103
|
-
}
|
|
104
|
-
counterGetTrc20++;
|
|
105
|
-
return HttpResponse.json(ret);
|
|
106
|
-
},
|
|
107
|
-
);
|
|
108
|
-
const handlers = [defaultGetTransactionsH, invalidTrc20Handler, defaultGetTxInfo];
|
|
109
|
-
const mockServer = setupServer(...handlers);
|
|
110
|
-
|
|
111
|
-
beforeAll(doBeforeAll(mockServer));
|
|
112
|
-
beforeEach(doBeforeEach(mockServer));
|
|
113
|
-
afterAll(doAfterAll(mockServer));
|
|
114
|
-
|
|
115
|
-
it("retry several times until result is correct", async () => {
|
|
116
|
-
// WHEN
|
|
117
|
-
const results = await fetchTronAccountTxs("ADDRESS", () => true, {}, defaultFetchParams);
|
|
118
|
-
|
|
119
|
-
// THEN
|
|
120
|
-
const tx1 = results.find(tx => tx.txID === tx1Hash);
|
|
121
|
-
expect(tx1).toBeDefined();
|
|
122
|
-
const tx2 = results.find(tx => tx.txID === tx2Hash);
|
|
123
|
-
expect(tx2).toBeDefined();
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
describe("fetchTronAccountTxs with invalid TRC20 (see LIVE-18992): after 3 tries it throws an exception", () => {
|
|
128
|
-
const tx1Hash = "1237889e91c0ebbe389436c341865df09921f8f0c029d9286102372cbaadc585";
|
|
129
|
-
const alwaysInvalidTrc20Handler = http.get(
|
|
130
|
-
`${TRON_BASE_URL_TEST}/v1/accounts/:addr/transactions/trc20`,
|
|
131
|
-
() => {
|
|
132
|
-
const ret: any = JSON.parse(JSON.stringify(TRC20_FIXTURE));
|
|
133
|
-
const tx1 = ret.data[0];
|
|
134
|
-
assert(tx1.transaction_id == tx1Hash);
|
|
135
|
-
ret.data[0].detail.ret = undefined;
|
|
136
|
-
return HttpResponse.json(ret);
|
|
137
|
-
},
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
const handlers = [defaultGetTransactionsH, alwaysInvalidTrc20Handler, defaultGetTxInfo];
|
|
141
|
-
const mockServer = setupServer(...handlers);
|
|
142
|
-
|
|
143
|
-
beforeAll(doBeforeAll(mockServer));
|
|
144
|
-
beforeEach(doBeforeEach(mockServer));
|
|
145
|
-
afterAll(doAfterAll(mockServer));
|
|
146
|
-
|
|
147
|
-
it("after several retry, it gives up on retry", async () => {
|
|
148
|
-
try {
|
|
149
|
-
await fetchTronAccountTxs("ADDRESS", () => true, {}, defaultFetchParams);
|
|
150
|
-
} catch (e) {
|
|
151
|
-
expect(e).toBeDefined();
|
|
152
|
-
expect((e as Error).message).toBe(
|
|
153
|
-
"getTrc20TxsWithRetry: couldn't fetch trc20 transactions after several attempts",
|
|
154
|
-
);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
fail("should have thrown an error");
|
|
158
|
-
});
|
|
159
|
-
});
|
package/src/network/index.ts
CHANGED
|
@@ -483,18 +483,13 @@ export type FetchTxsStopPredicate = (
|
|
|
483
483
|
) => boolean;
|
|
484
484
|
|
|
485
485
|
export type FetchParams = {
|
|
486
|
-
|
|
487
|
-
limitPerCall: number;
|
|
488
|
-
/** Hint about the number of transactions to be fetched in total (hint to optimize `limitPerCall`) */
|
|
489
|
-
hintGlobalLimit?: number;
|
|
486
|
+
limit: number;
|
|
490
487
|
minTimestamp: number;
|
|
491
|
-
order: "asc" | "desc";
|
|
492
488
|
};
|
|
493
489
|
|
|
494
490
|
export const defaultFetchParams: FetchParams = {
|
|
495
|
-
|
|
491
|
+
limit: 100,
|
|
496
492
|
minTimestamp: 0,
|
|
497
|
-
order: "desc",
|
|
498
493
|
} as const;
|
|
499
494
|
|
|
500
495
|
export async function fetchTronAccountTxs(
|
|
@@ -503,15 +498,12 @@ export async function fetchTronAccountTxs(
|
|
|
503
498
|
cacheTransactionInfoById: Record<string, TronTransactionInfo>,
|
|
504
499
|
params: FetchParams,
|
|
505
500
|
): Promise<TrongridTxInfo[]> {
|
|
506
|
-
const
|
|
507
|
-
? Math.min(params.limitPerCall, params.hintGlobalLimit)
|
|
508
|
-
: params.limitPerCall;
|
|
509
|
-
const queryParams = `limit=${adjustedLimitPerCall}&min_timestamp=${params.minTimestamp}&order_by=block_timestamp,${params.order}`;
|
|
501
|
+
const queryParamsNativeTxs = `limit=${params.limit}&min_timestamp=${params.minTimestamp}`;
|
|
510
502
|
const nativeTxs = (
|
|
511
503
|
await getAllTransactions<
|
|
512
504
|
(TransactionTronAPI & { detail?: TronTransactionInfo }) | MalformedTransactionTronAPI
|
|
513
505
|
>(
|
|
514
|
-
`${getBaseApiUrl()}/v1/accounts/${addr}/transactions?${
|
|
506
|
+
`${getBaseApiUrl()}/v1/accounts/${addr}/transactions?${queryParamsNativeTxs}`,
|
|
515
507
|
shouldFetchMoreTxs,
|
|
516
508
|
getTransactions(cacheTransactionInfoById),
|
|
517
509
|
)
|
|
@@ -536,77 +528,14 @@ export async function fetchTronAccountTxs(
|
|
|
536
528
|
|
|
537
529
|
// we need to fetch and filter trc20 transactions from another endpoint
|
|
538
530
|
// doc https://developers.tron.network/reference/get-trc20-transaction-info-by-account-address
|
|
539
|
-
|
|
540
|
-
const
|
|
531
|
+
const queryParamsTrc20Txs = `limit=${params.limit}&min_timestamp=${params.minTimestamp}`;
|
|
532
|
+
const trc20Txs = (
|
|
541
533
|
await getAllTransactions<Trc20API>(
|
|
542
|
-
`${getBaseApiUrl()}/v1/accounts/${addr}/transactions/trc20?${
|
|
534
|
+
`${getBaseApiUrl()}/v1/accounts/${addr}/transactions/trc20?${queryParamsTrc20Txs}&get_detail=true`,
|
|
543
535
|
shouldFetchMoreTxs,
|
|
544
536
|
getTrc20,
|
|
545
|
-
)
|
|
546
|
-
|
|
547
|
-
type Acc = {
|
|
548
|
-
txs: Trc20API[];
|
|
549
|
-
invalids: number[];
|
|
550
|
-
};
|
|
551
|
-
|
|
552
|
-
function isValid(tx: Trc20API): boolean {
|
|
553
|
-
const ret = tx?.detail?.ret;
|
|
554
|
-
return Array.isArray(ret) && ret.length > 0;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
function getInvalidTxIndexes(txs: Trc20API[]): number[] {
|
|
558
|
-
const invalids: number[] = [];
|
|
559
|
-
for (let i = 0; i < txs.length; i++) {
|
|
560
|
-
if (!isValid(txs[i])) {
|
|
561
|
-
invalids.push(i);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
txs.filter(tx => !isValid(tx)).map((tx, index) => index);
|
|
565
|
-
return invalids;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
function assert(predicate: boolean, message: string) {
|
|
569
|
-
if (!predicate) {
|
|
570
|
-
throw new Error(message);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Merge the two results
|
|
575
|
-
function mergeAccs(acc1: Acc, acc2: Acc): Acc {
|
|
576
|
-
assert(acc1.txs.length == acc2.txs.length, "accs should have the same length");
|
|
577
|
-
const accRet: Acc = { txs: acc1.txs, invalids: [] };
|
|
578
|
-
acc1.invalids.forEach(invalidIndex => {
|
|
579
|
-
acc2.invalids.includes(invalidIndex)
|
|
580
|
-
? accRet.invalids.push(invalidIndex)
|
|
581
|
-
: (accRet.txs[invalidIndex] = acc2.txs[invalidIndex]);
|
|
582
|
-
});
|
|
583
|
-
return accRet;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// see LIVE-18992 for an explanation to why we need this
|
|
587
|
-
async function getTrc20TxsWithRetry(acc: Acc | null, times: number): Promise<Trc20API[]> {
|
|
588
|
-
assert(
|
|
589
|
-
times > 0,
|
|
590
|
-
"getTrc20TxsWithRetry: couldn't fetch trc20 transactions after several attempts",
|
|
591
|
-
);
|
|
592
|
-
const ret = await callTrc20Endpoint();
|
|
593
|
-
const thisAcc: Acc = {
|
|
594
|
-
txs: ret,
|
|
595
|
-
invalids: getInvalidTxIndexes(ret),
|
|
596
|
-
};
|
|
597
|
-
const newAcc = acc ? mergeAccs(acc, thisAcc) : thisAcc;
|
|
598
|
-
if (newAcc.invalids.length == 0) {
|
|
599
|
-
return newAcc.txs;
|
|
600
|
-
} else {
|
|
601
|
-
log(
|
|
602
|
-
"coin-tron",
|
|
603
|
-
`getTrc20TxsWithRetry: got ${newAcc.invalids.length} invalid trc20 transactions, retrying...`,
|
|
604
|
-
);
|
|
605
|
-
return await getTrc20TxsWithRetry(newAcc, times - 1);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
const trc20Txs = (await getTrc20TxsWithRetry(null, 3)).map(formatTrongridTrc20TxResponse);
|
|
537
|
+
)
|
|
538
|
+
).map(tx => formatTrongridTrc20TxResponse(tx));
|
|
610
539
|
|
|
611
540
|
const txInfos: TrongridTxInfo[] = compact(nativeTxs.concat(trc20Txs)).sort(
|
|
612
541
|
(a, b) => b.date.getTime() - a.date.getTime(),
|