@ledgerhq/coin-xrp 0.9.2 → 1.0.0-nightly.1
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 +2 -2
- package/CHANGELOG.md +11 -10
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.integ.test.js +35 -36
- package/lib/api/index.integ.test.js.map +1 -1
- package/lib/api/index.js +65 -50
- package/lib/api/index.js.map +1 -1
- package/lib/api/index.test.js +66 -44
- package/lib/api/index.test.js.map +1 -1
- package/lib/bridge/broadcast.js +3 -12
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +9 -14
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/getTransactionStatus.js +4 -13
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/prepareTransaction.js +4 -13
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/signOperation.js +60 -68
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/synchronization.js +32 -45
- package/lib/bridge/synchronization.js.map +1 -1
- package/lib/bridge/synchronization.test.js +21 -17
- package/lib/bridge/synchronization.test.js.map +1 -1
- package/lib/bridge/transaction.js +16 -4
- package/lib/bridge/transaction.js.map +1 -1
- package/lib/logic/broadcast.js +8 -19
- package/lib/logic/broadcast.js.map +1 -1
- package/lib/logic/broadcast.test.js +6 -15
- package/lib/logic/broadcast.test.js.map +1 -1
- package/lib/logic/combine.js +2 -2
- package/lib/logic/combine.js.map +1 -1
- package/lib/logic/craftTransaction.js +28 -34
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/craftTransaction.test.js +8 -17
- package/lib/logic/craftTransaction.test.js.map +1 -1
- package/lib/logic/estimateFees.js +17 -28
- package/lib/logic/estimateFees.js.map +1 -1
- package/lib/logic/estimateFees.test.js +10 -19
- package/lib/logic/estimateFees.test.js.map +1 -1
- package/lib/logic/getBalance.js +3 -14
- package/lib/logic/getBalance.js.map +1 -1
- package/lib/logic/getBalance.test.js +4 -13
- package/lib/logic/getBalance.test.js.map +1 -1
- package/lib/logic/lastBlock.js +7 -18
- package/lib/logic/lastBlock.js.map +1 -1
- package/lib/logic/listOperations.d.ts +15 -5
- package/lib/logic/listOperations.d.ts.map +1 -1
- package/lib/logic/listOperations.js +84 -71
- package/lib/logic/listOperations.js.map +1 -1
- package/lib/logic/listOperations.test.js +66 -62
- package/lib/logic/listOperations.test.js.map +1 -1
- package/lib/logic/utils.js +9 -18
- package/lib/logic/utils.js.map +1 -1
- package/lib/logic/utils.test.js +9 -18
- package/lib/logic/utils.test.js.map +1 -1
- package/lib/network/index.d.ts +6 -3
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +40 -48
- package/lib/network/index.js.map +1 -1
- package/lib/network/index.test.js +9 -18
- package/lib/network/index.test.js.map +1 -1
- package/lib/network/types.d.ts +5 -0
- package/lib/network/types.d.ts.map +1 -1
- package/lib/network/types.js.map +1 -1
- package/lib/signer/getAddress.js +3 -12
- package/lib/signer/getAddress.js.map +1 -1
- package/lib/test/cli.js +5 -1
- package/lib/test/cli.js.map +1 -1
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.integ.test.js +35 -36
- package/lib-es/api/index.integ.test.js.map +1 -1
- package/lib-es/api/index.js +65 -50
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/api/index.test.js +66 -44
- package/lib-es/api/index.test.js.map +1 -1
- package/lib-es/bridge/broadcast.js +3 -12
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +9 -14
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +4 -13
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +4 -13
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/signOperation.js +60 -68
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/synchronization.js +32 -45
- package/lib-es/bridge/synchronization.js.map +1 -1
- package/lib-es/bridge/synchronization.test.js +21 -17
- package/lib-es/bridge/synchronization.test.js.map +1 -1
- package/lib-es/bridge/transaction.js +16 -4
- package/lib-es/bridge/transaction.js.map +1 -1
- package/lib-es/logic/broadcast.js +8 -19
- package/lib-es/logic/broadcast.js.map +1 -1
- package/lib-es/logic/broadcast.test.js +6 -15
- package/lib-es/logic/broadcast.test.js.map +1 -1
- package/lib-es/logic/combine.js +2 -2
- package/lib-es/logic/combine.js.map +1 -1
- package/lib-es/logic/craftTransaction.js +28 -34
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/craftTransaction.test.js +8 -17
- package/lib-es/logic/craftTransaction.test.js.map +1 -1
- package/lib-es/logic/estimateFees.js +17 -28
- package/lib-es/logic/estimateFees.js.map +1 -1
- package/lib-es/logic/estimateFees.test.js +10 -19
- package/lib-es/logic/estimateFees.test.js.map +1 -1
- package/lib-es/logic/getBalance.js +3 -14
- package/lib-es/logic/getBalance.js.map +1 -1
- package/lib-es/logic/getBalance.test.js +4 -13
- package/lib-es/logic/getBalance.test.js.map +1 -1
- package/lib-es/logic/lastBlock.js +7 -18
- package/lib-es/logic/lastBlock.js.map +1 -1
- package/lib-es/logic/listOperations.d.ts +15 -5
- package/lib-es/logic/listOperations.d.ts.map +1 -1
- package/lib-es/logic/listOperations.js +84 -71
- package/lib-es/logic/listOperations.js.map +1 -1
- package/lib-es/logic/listOperations.test.js +66 -62
- package/lib-es/logic/listOperations.test.js.map +1 -1
- package/lib-es/logic/utils.js +9 -18
- package/lib-es/logic/utils.js.map +1 -1
- package/lib-es/logic/utils.test.js +9 -18
- package/lib-es/logic/utils.test.js.map +1 -1
- package/lib-es/network/index.d.ts +6 -3
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +39 -47
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/index.test.js +9 -18
- package/lib-es/network/index.test.js.map +1 -1
- package/lib-es/network/types.d.ts +5 -0
- package/lib-es/network/types.d.ts.map +1 -1
- package/lib-es/network/types.js.map +1 -1
- package/lib-es/signer/getAddress.js +3 -12
- package/lib-es/signer/getAddress.js.map +1 -1
- package/lib-es/test/cli.js +5 -1
- package/lib-es/test/cli.js.map +1 -1
- package/package.json +7 -6
- package/src/api/index.integ.test.ts +12 -6
- package/src/api/index.test.ts +119 -75
- package/src/api/index.ts +62 -10
- package/src/bridge/synchronization.test.ts +31 -15
- package/src/logic/listOperations.test.ts +104 -85
- package/src/logic/listOperations.ts +47 -34
- package/src/network/index.ts +21 -8
- package/src/network/types.ts +6 -0
- package/tsconfig.json +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { assert } from "console";
|
|
2
2
|
import { listOperations } from "./listOperations";
|
|
3
3
|
import { RIPPLE_EPOCH } from "./utils";
|
|
4
|
+
import { Marker } from "../network/types";
|
|
4
5
|
|
|
5
6
|
const maxHeight = 2;
|
|
6
7
|
const minHeight = 1;
|
|
@@ -9,45 +10,60 @@ const mockGetServerInfos = jest.fn().mockResolvedValue({
|
|
|
9
10
|
complete_ledgers: `${minHeight}-${maxHeight}`,
|
|
10
11
|
},
|
|
11
12
|
});
|
|
12
|
-
const
|
|
13
|
+
const mockNetworkGetTransactions = jest.fn();
|
|
13
14
|
jest.mock("../network", () => ({
|
|
14
15
|
getServerInfos: () => mockGetServerInfos(),
|
|
15
|
-
getTransactions: () =>
|
|
16
|
+
getTransactions: () => mockNetworkGetTransactions(),
|
|
16
17
|
}));
|
|
17
18
|
|
|
18
19
|
describe("listOperations", () => {
|
|
19
20
|
afterEach(() => {
|
|
20
21
|
mockGetServerInfos.mockClear();
|
|
21
|
-
|
|
22
|
+
mockNetworkGetTransactions.mockClear();
|
|
22
23
|
});
|
|
23
24
|
|
|
25
|
+
const someMarker: Marker = { ledger: 1, seq: 1 };
|
|
26
|
+
function mockNetworkTxs(txs: unknown): unknown {
|
|
27
|
+
return {
|
|
28
|
+
account: "account",
|
|
29
|
+
ledger_index_max: 1,
|
|
30
|
+
ledger_index_min: 1,
|
|
31
|
+
limit: 1,
|
|
32
|
+
validated: false,
|
|
33
|
+
transactions: txs,
|
|
34
|
+
marker: someMarker,
|
|
35
|
+
error: "",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
it("when there are no transactions then the result is empty", async () => {
|
|
25
40
|
// Given
|
|
26
|
-
|
|
41
|
+
mockNetworkGetTransactions.mockResolvedValue(mockNetworkTxs([]));
|
|
27
42
|
// When
|
|
28
43
|
const [results, token] = await listOperations("any address", { minHeight: 0 });
|
|
29
44
|
// Then
|
|
30
45
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
31
|
-
expect(
|
|
46
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(1);
|
|
32
47
|
expect(results).toEqual([]);
|
|
33
|
-
expect(token).toEqual(
|
|
48
|
+
expect(JSON.parse(token)).toEqual(someMarker);
|
|
34
49
|
});
|
|
35
50
|
|
|
36
51
|
it("when there are no transactions and a limit then the result is empty", async () => {
|
|
37
52
|
// Given
|
|
38
|
-
|
|
53
|
+
mockNetworkGetTransactions.mockResolvedValue(mockNetworkTxs([]));
|
|
39
54
|
// When
|
|
40
55
|
const [results, token] = await listOperations("any address", { minHeight: 0, limit: 1 });
|
|
41
56
|
// Then
|
|
42
57
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
43
|
-
expect(
|
|
58
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(1);
|
|
44
59
|
expect(results).toEqual([]);
|
|
45
|
-
expect(token).toEqual(
|
|
60
|
+
expect(JSON.parse(token)).toEqual(someMarker);
|
|
46
61
|
});
|
|
47
62
|
|
|
48
63
|
const paymentTx = {
|
|
49
64
|
ledger_hash: "HASH_VALUE_BLOCK",
|
|
50
65
|
hash: "HASH_VALUE",
|
|
66
|
+
validated: true,
|
|
51
67
|
close_time_iso: "2000-01-01T00:00:01Z",
|
|
52
68
|
meta: { delivered_amount: "100" },
|
|
53
69
|
tx_json: {
|
|
@@ -65,8 +81,9 @@ describe("listOperations", () => {
|
|
|
65
81
|
it("should only list operations of type payment", async () => {
|
|
66
82
|
// Given
|
|
67
83
|
const lastTransaction = paymentTx;
|
|
68
|
-
|
|
69
|
-
|
|
84
|
+
const txs = [paymentTx, otherTx, lastTransaction];
|
|
85
|
+
mockNetworkGetTransactions.mockResolvedValueOnce(mockNetworkTxs(txs));
|
|
86
|
+
mockNetworkGetTransactions.mockResolvedValue(mockNetworkTxs([])); // subsequent calls
|
|
70
87
|
|
|
71
88
|
// When
|
|
72
89
|
const [results, token] = await listOperations("any address", { minHeight: 0, limit: 3 });
|
|
@@ -74,39 +91,39 @@ describe("listOperations", () => {
|
|
|
74
91
|
// Then
|
|
75
92
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
76
93
|
// it's called twice because first call yields only 2 transactions, and 3 are asked
|
|
77
|
-
expect(
|
|
94
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(2);
|
|
78
95
|
expect(results.length).toEqual(2);
|
|
79
|
-
expect(token).toEqual(
|
|
96
|
+
expect(JSON.parse(token)).toEqual(someMarker);
|
|
80
97
|
});
|
|
81
98
|
|
|
82
99
|
it("should make enough calls so that the limit requested is satified", async () => {
|
|
83
|
-
const lastTransaction = otherTx;
|
|
84
100
|
const txs = [paymentTx, paymentTx, otherTx, otherTx, otherTx, otherTx, otherTx, otherTx];
|
|
85
101
|
assert(txs.length === 8);
|
|
86
|
-
|
|
102
|
+
mockNetworkGetTransactions.mockResolvedValue(mockNetworkTxs(txs));
|
|
87
103
|
|
|
88
104
|
const [results, token] = await listOperations("any address", { minHeight: 0, limit: 8 });
|
|
89
105
|
|
|
90
106
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
91
107
|
// it's called 4 times because each call yields only 2 transactions, and 8 are asked
|
|
92
|
-
expect(
|
|
108
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(4);
|
|
93
109
|
expect(results.length).toEqual(8);
|
|
94
|
-
expect(token).toEqual(
|
|
110
|
+
expect(JSON.parse(token)).toEqual(someMarker);
|
|
95
111
|
});
|
|
96
112
|
|
|
97
113
|
it("should make enough calls, even if there is not enough txs to satisfy the limit", async () => {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
114
|
+
mockNetworkGetTransactions.mockResolvedValueOnce(
|
|
115
|
+
mockNetworkTxs([otherTx, otherTx, otherTx, otherTx]),
|
|
116
|
+
);
|
|
117
|
+
mockNetworkGetTransactions.mockResolvedValueOnce(mockNetworkTxs([paymentTx, paymentTx]));
|
|
118
|
+
mockNetworkGetTransactions.mockResolvedValue([]); // subsequent calls
|
|
102
119
|
|
|
103
120
|
const [results, token] = await listOperations("any address", { minHeight: 0, limit: 4 });
|
|
104
121
|
|
|
105
122
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
106
123
|
// it's called 2 times because the second call is a shortage of txs
|
|
107
|
-
expect(
|
|
124
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(2);
|
|
108
125
|
expect(results.length).toEqual(2);
|
|
109
|
-
expect(token).toEqual(
|
|
126
|
+
expect(JSON.parse(token)).toEqual(someMarker);
|
|
110
127
|
});
|
|
111
128
|
|
|
112
129
|
it.each([
|
|
@@ -128,69 +145,71 @@ describe("listOperations", () => {
|
|
|
128
145
|
// Given
|
|
129
146
|
const deliveredAmount = 100;
|
|
130
147
|
const fee = 10;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
mockNetworkGetTransactions.mockResolvedValue(
|
|
149
|
+
mockNetworkTxs([
|
|
150
|
+
{
|
|
151
|
+
ledger_hash: "HASH_VALUE_BLOCK",
|
|
152
|
+
hash: "HASH_VALUE",
|
|
153
|
+
close_time_iso: "2000-01-01T00:00:01Z",
|
|
154
|
+
meta: { delivered_amount: deliveredAmount.toString() },
|
|
155
|
+
tx_json: {
|
|
156
|
+
TransactionType: "Payment",
|
|
157
|
+
Fee: fee.toString(),
|
|
158
|
+
ledger_index: 1,
|
|
159
|
+
date: 1000,
|
|
160
|
+
Account: opSender,
|
|
161
|
+
Destination: opDestination,
|
|
162
|
+
Sequence: 1,
|
|
163
|
+
},
|
|
145
164
|
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
165
|
+
{
|
|
166
|
+
ledger_hash: "HASH_VALUE_BLOCK",
|
|
167
|
+
hash: "HASH_VALUE",
|
|
168
|
+
close_time_iso: "2000-01-01T00:00:01Z",
|
|
169
|
+
meta: { delivered_amount: deliveredAmount.toString() },
|
|
170
|
+
tx_json: {
|
|
171
|
+
TransactionType: "Payment",
|
|
172
|
+
Fee: fee.toString(),
|
|
173
|
+
ledger_index: 1,
|
|
174
|
+
date: 1000,
|
|
175
|
+
Account: opSender,
|
|
176
|
+
Destination: opDestination,
|
|
177
|
+
DestinationTag: 509555,
|
|
178
|
+
Sequence: 1,
|
|
179
|
+
},
|
|
161
180
|
},
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
{
|
|
182
|
+
ledger_hash: "HASH_VALUE_BLOCK",
|
|
183
|
+
hash: "HASH_VALUE",
|
|
184
|
+
close_time_iso: "2000-01-01T00:00:01Z",
|
|
185
|
+
meta: { delivered_amount: deliveredAmount.toString() },
|
|
186
|
+
tx_json: {
|
|
187
|
+
TransactionType: "Payment",
|
|
188
|
+
Fee: fee.toString(),
|
|
189
|
+
ledger_index: 1,
|
|
190
|
+
date: 1000,
|
|
191
|
+
Account: opSender,
|
|
192
|
+
Destination: opDestination,
|
|
193
|
+
Memos: [
|
|
194
|
+
{
|
|
195
|
+
Memo: {
|
|
196
|
+
MemoType: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
|
|
197
|
+
MemoData: "72656e74",
|
|
198
|
+
},
|
|
180
199
|
},
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
200
|
+
],
|
|
201
|
+
Sequence: 1,
|
|
202
|
+
},
|
|
184
203
|
},
|
|
185
|
-
|
|
186
|
-
|
|
204
|
+
]),
|
|
205
|
+
);
|
|
187
206
|
|
|
188
207
|
// When
|
|
189
|
-
const [results, _] = await listOperations(address, { minHeight: 0 });
|
|
208
|
+
const [results, _] = await listOperations(address, { minHeight: 0, order: "asc" });
|
|
190
209
|
|
|
191
210
|
// Then
|
|
192
211
|
expect(mockGetServerInfos).toHaveBeenCalledTimes(1);
|
|
193
|
-
expect(
|
|
212
|
+
expect(mockNetworkGetTransactions).toHaveBeenCalledTimes(1);
|
|
194
213
|
// if expectedType is "OUT", compute value with fees (i.e. delivered_amount + Fee)
|
|
195
214
|
const expectedValue =
|
|
196
215
|
expectedType === "IN" ? BigInt(deliveredAmount) : BigInt(deliveredAmount + fee);
|
|
@@ -209,6 +228,14 @@ describe("listOperations", () => {
|
|
|
209
228
|
recipients: [opDestination],
|
|
210
229
|
date: new Date(1000000 + RIPPLE_EPOCH * 1000),
|
|
211
230
|
transactionSequenceNumber: 1,
|
|
231
|
+
details: {
|
|
232
|
+
memos: [
|
|
233
|
+
{
|
|
234
|
+
type: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
|
|
235
|
+
data: "72656e74",
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
212
239
|
},
|
|
213
240
|
{
|
|
214
241
|
hash: "HASH_VALUE",
|
|
@@ -242,14 +269,6 @@ describe("listOperations", () => {
|
|
|
242
269
|
recipients: [opDestination],
|
|
243
270
|
date: new Date(1000000 + RIPPLE_EPOCH * 1000),
|
|
244
271
|
transactionSequenceNumber: 1,
|
|
245
|
-
details: {
|
|
246
|
-
memos: [
|
|
247
|
-
{
|
|
248
|
-
type: "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963",
|
|
249
|
-
data: "72656e74",
|
|
250
|
-
},
|
|
251
|
-
],
|
|
252
|
-
},
|
|
253
272
|
},
|
|
254
273
|
]);
|
|
255
274
|
},
|
|
@@ -1,41 +1,50 @@
|
|
|
1
|
-
import { getServerInfos, getTransactions } from "../network";
|
|
1
|
+
import { getServerInfos, getTransactions, GetTransactionsOptions } from "../network";
|
|
2
2
|
import type { XrplOperation } from "../network/types";
|
|
3
3
|
import { XrpMemo, XrpOperation } from "../types";
|
|
4
4
|
import { RIPPLE_EPOCH } from "./utils";
|
|
5
5
|
|
|
6
|
+
type Order = "asc" | "desc";
|
|
6
7
|
/**
|
|
7
8
|
* Returns list of "Payment" Operations associated to an account.
|
|
8
9
|
* @param address Account address
|
|
9
|
-
* @param
|
|
10
|
-
*
|
|
10
|
+
* @param minHeight retrieve operations from a specific block height until top most (inclusive)
|
|
11
|
+
* if not provided, it will start from the oldest possible history.
|
|
12
|
+
* The result is not guaranteed to contain all operations until top height (it depends of the underlying explorer),
|
|
13
|
+
* so you might need to call this function multiple times to get all operations.
|
|
14
|
+
* @param order whether to return operations from the top block or from the oldest block
|
|
15
|
+
* it defaults to "desc" (newest first)
|
|
16
|
+
* it doesn't control the order of the operations in the result list.
|
|
17
|
+
* this parameter is added as a workaround for the issue LIVE-16705
|
|
18
|
+
* @returns a list of operations is descending order and a token to be used for pagination
|
|
11
19
|
*/
|
|
12
20
|
export async function listOperations(
|
|
13
21
|
address: string,
|
|
14
22
|
{
|
|
15
23
|
limit,
|
|
16
|
-
maxHeight,
|
|
17
24
|
minHeight,
|
|
25
|
+
token,
|
|
26
|
+
order,
|
|
18
27
|
}: {
|
|
28
|
+
// pagination:
|
|
19
29
|
limit?: number;
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
token?: string;
|
|
31
|
+
order?: Order;
|
|
32
|
+
// filters:
|
|
33
|
+
minHeight?: number;
|
|
22
34
|
},
|
|
23
|
-
): Promise<[XrpOperation[],
|
|
35
|
+
): Promise<[XrpOperation[], string]> {
|
|
24
36
|
const serverInfo = await getServerInfos();
|
|
25
37
|
const ledgers = serverInfo.info.complete_ledgers.split("-");
|
|
26
38
|
const minLedgerVersion = Number(ledgers[0]);
|
|
27
|
-
const maxLedgerVersion = Number(ledgers[1]);
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
40
|
+
// by default the explorer queries the transactions in descending order (newest first)
|
|
41
|
+
let forward = false;
|
|
42
|
+
if (order && order === "asc") {
|
|
43
|
+
forward = true;
|
|
44
|
+
}
|
|
35
45
|
|
|
36
|
-
let options:
|
|
37
|
-
|
|
38
|
-
tx_type: "Payment",
|
|
46
|
+
let options: GetTransactionsOptions = {
|
|
47
|
+
forward: forward,
|
|
39
48
|
};
|
|
40
49
|
|
|
41
50
|
if (limit) {
|
|
@@ -44,7 +53,15 @@ export async function listOperations(
|
|
|
44
53
|
limit,
|
|
45
54
|
};
|
|
46
55
|
}
|
|
47
|
-
|
|
56
|
+
|
|
57
|
+
if (token) {
|
|
58
|
+
options = {
|
|
59
|
+
...options,
|
|
60
|
+
marker: JSON.parse(token),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (minHeight !== undefined) {
|
|
48
65
|
options = {
|
|
49
66
|
...options,
|
|
50
67
|
// if there is no ops, it might be after a clear and we prefer to pull from the oldest possible history
|
|
@@ -54,25 +71,22 @@ export async function listOperations(
|
|
|
54
71
|
|
|
55
72
|
async function getPaymentTransactions(
|
|
56
73
|
address: string,
|
|
57
|
-
options:
|
|
58
|
-
): Promise<[boolean,
|
|
59
|
-
const
|
|
74
|
+
options: GetTransactionsOptions,
|
|
75
|
+
): Promise<[boolean, GetTransactionsOptions, XrplOperation[]]> {
|
|
76
|
+
const response = await getTransactions(address, options);
|
|
77
|
+
const txs = response.transactions;
|
|
78
|
+
const marker = response.marker;
|
|
60
79
|
// Filter out the transactions that are not "Payment" type because the filter on "tx_type" of the node RPC is not working as expected.
|
|
61
80
|
const paymentTxs = txs.filter(tx => tx.tx_json.TransactionType === "Payment");
|
|
62
81
|
const shortage = (options.limit && txs.length < options.limit) || false;
|
|
63
|
-
const lastTransaction = txs.slice(-1)[0];
|
|
64
82
|
const nextOptions = { ...options };
|
|
65
|
-
if (
|
|
66
|
-
nextOptions.
|
|
83
|
+
if (marker) {
|
|
84
|
+
nextOptions.marker = marker;
|
|
67
85
|
if (nextOptions.limit) nextOptions.limit -= paymentTxs.length;
|
|
68
86
|
}
|
|
69
87
|
return [shortage, nextOptions, paymentTxs];
|
|
70
88
|
}
|
|
71
89
|
|
|
72
|
-
// TODO BUG: given the number of txs belonging to the SAME block > limit
|
|
73
|
-
// when user loop over pages using the provided token
|
|
74
|
-
// then user misses some txs that doesn't fit the page size limit
|
|
75
|
-
// because the "next token" is a block height (solution is to use an opaque token instead)
|
|
76
90
|
let [txShortage, nextOptions, transactions] = await getPaymentTransactions(address, options);
|
|
77
91
|
const isEnough = () => txShortage || (limit && transactions.length >= limit);
|
|
78
92
|
// We need to call the node RPC multiple times to get the desired number of transactions by the limiter.
|
|
@@ -86,13 +100,12 @@ export async function listOperations(
|
|
|
86
100
|
transactions = transactions.concat(newTransactions);
|
|
87
101
|
}
|
|
88
102
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const nextIndex = lastTransaction
|
|
92
|
-
? Math.max(lastTransaction.tx_json.ledger_index - 1, minLedgerVersion)
|
|
93
|
-
: minLedgerVersion;
|
|
103
|
+
// the order is reversed so that the results are always sorted by newest tx first element of the list
|
|
104
|
+
if (order === "asc") transactions.reverse();
|
|
94
105
|
|
|
95
|
-
|
|
106
|
+
// the next index to start the pagination from
|
|
107
|
+
const next = nextOptions.marker ? JSON.stringify(nextOptions.marker) : "";
|
|
108
|
+
return [transactions.map(convertToCoreOperation(address)), next];
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
const convertToCoreOperation =
|
package/src/network/index.ts
CHANGED
|
@@ -4,13 +4,13 @@ import type { AccountInfo } from "../types/model";
|
|
|
4
4
|
import {
|
|
5
5
|
isErrorResponse,
|
|
6
6
|
isResponseStatus,
|
|
7
|
+
Marker,
|
|
7
8
|
type AccountInfoResponse,
|
|
8
9
|
type AccountTxResponse,
|
|
9
10
|
type ErrorResponse,
|
|
10
11
|
type LedgerResponse,
|
|
11
12
|
type ServerInfoResponse,
|
|
12
13
|
type SubmitReponse,
|
|
13
|
-
type XrplOperation,
|
|
14
14
|
} from "./types";
|
|
15
15
|
|
|
16
16
|
const getNodeUrl = () => coinConfig.getCoinConfig().node;
|
|
@@ -66,19 +66,32 @@ export const getServerInfos = async (): Promise<ServerInfoResponse> => {
|
|
|
66
66
|
return rpcCall<ServerInfoResponse>("server_info", { ledger_index: "validated" });
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
+
// https://xrpl.org/docs/references/http-websocket-apis/public-api-methods/account-methods/account_tx
|
|
70
|
+
export type GetTransactionsOptions = {
|
|
71
|
+
ledger_index_min?: number;
|
|
72
|
+
ledger_index_max?: number;
|
|
73
|
+
limit?: number;
|
|
74
|
+
marker?: Marker;
|
|
75
|
+
// this property controls the order of the transactions
|
|
76
|
+
// true: oldest first
|
|
77
|
+
// false: newest first
|
|
78
|
+
forward: boolean;
|
|
79
|
+
};
|
|
80
|
+
|
|
69
81
|
export const getTransactions = async (
|
|
70
82
|
address: string,
|
|
71
|
-
options:
|
|
72
|
-
): Promise<
|
|
83
|
+
options: GetTransactionsOptions | undefined,
|
|
84
|
+
): Promise<AccountTxResponse> => {
|
|
73
85
|
const result = await rpcCall<AccountTxResponse>("account_tx", {
|
|
74
86
|
account: address,
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
|
|
87
|
+
// this property controls the order of the transactions
|
|
88
|
+
// looks like there is a bug in LL (https://ledgerhq.atlassian.net/browse/LIVE-16705)
|
|
89
|
+
// so we need to set it to false (newest first) to get the transactions in the right order
|
|
90
|
+
// for lama-adapter we need to set it to true (oldest first)
|
|
78
91
|
...options,
|
|
79
92
|
api_version: 2,
|
|
80
93
|
});
|
|
81
|
-
return result
|
|
94
|
+
return result;
|
|
82
95
|
};
|
|
83
96
|
|
|
84
97
|
export async function getLedger(): Promise<LedgerResponse> {
|
|
@@ -93,7 +106,7 @@ export async function getLedgerIndex(): Promise<number> {
|
|
|
93
106
|
|
|
94
107
|
async function rpcCall<T extends object>(
|
|
95
108
|
method: string,
|
|
96
|
-
params: Record<string,
|
|
109
|
+
params: Record<string, unknown> = {},
|
|
97
110
|
): Promise<T> {
|
|
98
111
|
const {
|
|
99
112
|
data: { result },
|
package/src/network/types.ts
CHANGED
|
@@ -168,6 +168,11 @@ export type ServerInfoResponse = {
|
|
|
168
168
|
};
|
|
169
169
|
} & ResponseStatus;
|
|
170
170
|
|
|
171
|
+
export type Marker = {
|
|
172
|
+
ledger: number;
|
|
173
|
+
seq: number;
|
|
174
|
+
};
|
|
175
|
+
|
|
171
176
|
export type AccountTxResponse = {
|
|
172
177
|
account: string;
|
|
173
178
|
ledger_index_max: number;
|
|
@@ -175,6 +180,7 @@ export type AccountTxResponse = {
|
|
|
175
180
|
limit: number;
|
|
176
181
|
transactions: XrplOperation[];
|
|
177
182
|
validated: boolean;
|
|
183
|
+
marker?: Marker;
|
|
178
184
|
} & ResponseStatus;
|
|
179
185
|
|
|
180
186
|
export type LedgerResponse = {
|