@fleet-sdk/blockchain-providers 0.5.0 → 0.6.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/CHANGELOG.md +12 -0
- package/dist/index.d.mts +124 -33
- package/dist/index.d.ts +124 -33
- package/dist/index.js +241 -61
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +241 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/ergo-graphql/ergoGraphQLProvider.ts +256 -86
- package/src/ergo-graphql/queries.ts +14 -5
- package/src/types/blockchainProvider.ts +101 -18
- package/src/utils/_tests.ts +6 -10
- package/src/utils/graphql.ts +54 -62
- package/src/utils/networking.ts +84 -0
package/dist/index.js
CHANGED
@@ -4,33 +4,73 @@ var common = require('@fleet-sdk/common');
|
|
4
4
|
var core = require('@fleet-sdk/core');
|
5
5
|
|
6
6
|
// src/ergo-graphql/ergoGraphQLProvider.ts
|
7
|
+
async function request(path, opt) {
|
8
|
+
const url = buildURL(path, opt?.query, opt?.base);
|
9
|
+
let response;
|
10
|
+
if (opt?.retry) {
|
11
|
+
const routes = common.some(opt.retry.fallbacks) ? [url, ...opt.retry.fallbacks] : [url];
|
12
|
+
const attempts = opt.retry.attempts;
|
13
|
+
response = await exponentialRetry(
|
14
|
+
(r) => fetch(resolveUrl(routes, attempts - r), opt.httpOptions),
|
15
|
+
opt.retry
|
16
|
+
);
|
17
|
+
} else {
|
18
|
+
response = await fetch(url, opt?.httpOptions);
|
19
|
+
}
|
20
|
+
return (opt?.parser || JSON).parse(await response.text());
|
21
|
+
}
|
22
|
+
function resolveUrl(routes, attempt) {
|
23
|
+
const route = routes[attempt % routes.length];
|
24
|
+
return typeof route === "string" ? route : buildURL(route.path, route.query, route.base).toString();
|
25
|
+
}
|
26
|
+
function buildURL(path, query, base) {
|
27
|
+
if (!base && !query) return path;
|
28
|
+
const url = new URL(path, base);
|
29
|
+
if (common.some(query)) {
|
30
|
+
for (const key in query) url.searchParams.append(key, String(query[key]));
|
31
|
+
}
|
32
|
+
return url.toString();
|
33
|
+
}
|
34
|
+
async function exponentialRetry(operation, { attempts, delay }) {
|
35
|
+
try {
|
36
|
+
return await operation(attempts);
|
37
|
+
} catch (e) {
|
38
|
+
if (attempts > 0) {
|
39
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
40
|
+
return exponentialRetry(operation, { attempts: attempts - 1, delay: delay * 2 });
|
41
|
+
}
|
42
|
+
throw e;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
// src/utils/graphql.ts
|
7
47
|
var OP_NAME_REGEX = /(query|mutation)\s?([\w\-_]+)?/;
|
8
48
|
var DEFAULT_HEADERS = {
|
9
49
|
"content-type": "application/json; charset=utf-8",
|
10
50
|
accept: "application/graphql-response+json, application/json"
|
11
51
|
};
|
12
52
|
function createGqlOperation(query, options) {
|
13
|
-
return async (variables) => {
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
53
|
+
return async (variables, url) => {
|
54
|
+
url = url ?? options?.url;
|
55
|
+
if (!url) throw new Error("URL is required");
|
56
|
+
const response = await request(url, {
|
57
|
+
...options,
|
58
|
+
httpOptions: {
|
59
|
+
...options?.httpOptions,
|
60
|
+
method: "POST",
|
61
|
+
headers: common.ensureDefaults(options?.httpOptions?.headers, DEFAULT_HEADERS),
|
62
|
+
body: (options?.parser ?? JSON).stringify({
|
63
|
+
operationName: getOpName(query),
|
64
|
+
query,
|
65
|
+
variables: variables ? common.clearUndefined(variables) : void 0
|
66
|
+
})
|
67
|
+
}
|
23
68
|
});
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
);
|
28
|
-
if (options.throwOnNonNetworkErrors && common.some(parsedData.errors) && common.isEmpty(parsedData.data)) {
|
29
|
-
throw new common.BlockchainProviderError(parsedData.errors[0].message, {
|
30
|
-
cause: parsedData.errors
|
31
|
-
});
|
69
|
+
if (options?.throwOnNonNetworkErrors && common.some(response.errors) && common.isEmpty(response.data)) {
|
70
|
+
const msg = response.errors[0].message;
|
71
|
+
throw new common.BlockchainProviderError(msg, { cause: response.errors });
|
32
72
|
}
|
33
|
-
return
|
73
|
+
return response;
|
34
74
|
};
|
35
75
|
}
|
36
76
|
function getOpName(query) {
|
@@ -42,41 +82,62 @@ function isRequestParam(obj) {
|
|
42
82
|
|
43
83
|
// src/ergo-graphql/queries.ts
|
44
84
|
var B = [
|
45
|
-
"
|
85
|
+
"$boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int",
|
46
86
|
"boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take",
|
47
|
-
"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters
|
87
|
+
"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters"
|
48
88
|
];
|
49
|
-
var CONF_BOXES_QUERY =
|
50
|
-
var UNCONF_BOXES_QUERY =
|
51
|
-
var ALL_BOXES_QUERY =
|
89
|
+
var CONF_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } }`;
|
90
|
+
var UNCONF_BOXES_QUERY = `query boxes(${B[0]}) { mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;
|
91
|
+
var ALL_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;
|
52
92
|
var HEADERS_QUERY = "query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }";
|
53
93
|
var CHECK_TX_MUTATION = "mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }";
|
54
94
|
var SEND_TX_MUTATION = "mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }";
|
95
|
+
var T = [
|
96
|
+
"$addresses: [String!], $transactionIds: [String!], $skip: Int, $take: Int",
|
97
|
+
"addresses: $addresses, transactionIds: $transactionIds, skip: $skip, take: $take",
|
98
|
+
`transactionId timestamp inputs { proofBytes extension index box { ${B[2]} } } dataInputs { boxId }`
|
99
|
+
];
|
100
|
+
var CONF_TX_QUERY = `query confirmedTransactions(${T[0]} $relevantOnly: Boolean) { transactions(${T[1]}) { ${T[2]} outputs(relevantOnly: $relevantOnly) { ${B[2]} } inclusionHeight headerId index } }`;
|
101
|
+
var UNCONF_TX_QUERY = `query unconfirmedTransactions(${T[0]}) { mempool { transactions(${T[1]}) { ${T[2]} outputs { ${B[2]} } } } }`;
|
55
102
|
|
56
103
|
// src/ergo-graphql/ergoGraphQLProvider.ts
|
57
104
|
var PAGE_SIZE = 50;
|
58
105
|
var ErgoGraphQLProvider = class {
|
59
106
|
#options;
|
60
|
-
#
|
61
|
-
#
|
107
|
+
#biMapper;
|
108
|
+
#getConfirmedBoxes;
|
109
|
+
#getUnconfirmedBoxes;
|
62
110
|
#getAllBoxes;
|
111
|
+
#getConfirmedTransactions;
|
112
|
+
#getUnconfirmedTransactions;
|
113
|
+
#checkTransaction;
|
114
|
+
#sendTransaction;
|
63
115
|
#getHeaders;
|
64
|
-
#checkTx;
|
65
|
-
#sendTx;
|
66
116
|
constructor(optOrUrl) {
|
67
117
|
this.#options = {
|
68
118
|
...isRequestParam(optOrUrl) ? optOrUrl : { url: optOrUrl },
|
69
119
|
throwOnNonNetworkErrors: true
|
70
120
|
};
|
71
|
-
this.#
|
72
|
-
this.#
|
121
|
+
this.#biMapper = (value) => BigInt(value);
|
122
|
+
this.#getConfirmedBoxes = this.createOperation(CONF_BOXES_QUERY);
|
123
|
+
this.#getUnconfirmedBoxes = this.createOperation(UNCONF_BOXES_QUERY);
|
73
124
|
this.#getAllBoxes = this.createOperation(ALL_BOXES_QUERY);
|
125
|
+
this.#getConfirmedTransactions = this.createOperation(CONF_TX_QUERY);
|
126
|
+
this.#getUnconfirmedTransactions = this.createOperation(UNCONF_TX_QUERY);
|
127
|
+
this.#checkTransaction = this.createOperation(CHECK_TX_MUTATION);
|
128
|
+
this.#sendTransaction = this.createOperation(SEND_TX_MUTATION);
|
74
129
|
this.#getHeaders = this.createOperation(HEADERS_QUERY);
|
75
|
-
this.#checkTx = this.createOperation(CHECK_TX_MUTATION);
|
76
|
-
this.#sendTx = this.createOperation(SEND_TX_MUTATION);
|
77
130
|
}
|
78
131
|
#fetchBoxes(args, inclConf, inclUnconf) {
|
79
|
-
return inclConf && inclUnconf ? this.#getAllBoxes(args) : inclUnconf ? this.#
|
132
|
+
return inclConf && inclUnconf ? this.#getAllBoxes(args, this.#options.url) : inclUnconf ? this.#getUnconfirmedBoxes(args, this.#options.url) : this.#getConfirmedBoxes(args, this.#options.url);
|
133
|
+
}
|
134
|
+
setUrl(url) {
|
135
|
+
this.#options.url = url;
|
136
|
+
return this;
|
137
|
+
}
|
138
|
+
setBigIntMapper(mapper) {
|
139
|
+
this.#biMapper = mapper;
|
140
|
+
return this;
|
80
141
|
}
|
81
142
|
async *streamBoxes(query) {
|
82
143
|
if (common.isEmpty(query.where)) {
|
@@ -90,19 +151,18 @@ var ErgoGraphQLProvider = class {
|
|
90
151
|
let inclPool = from !== "blockchain";
|
91
152
|
const isMempoolAware = inclPool;
|
92
153
|
do {
|
93
|
-
const
|
94
|
-
const { data } = response;
|
154
|
+
const { data } = await this.#fetchBoxes(args, inclChain, inclPool);
|
95
155
|
let boxes = [];
|
96
156
|
if (inclChain && hasConfirmed(data)) {
|
97
157
|
if (common.some(data.boxes)) {
|
98
|
-
const confirmedBoxes = (isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes).map(
|
158
|
+
const confirmedBoxes = (isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes).map((b) => mapConfirmedBox(b, this.#biMapper));
|
99
159
|
boxes = boxes.concat(confirmedBoxes);
|
100
160
|
}
|
101
161
|
inclChain = data.boxes.length === PAGE_SIZE;
|
102
162
|
}
|
103
163
|
if (isMempoolAware && hasMempool(data)) {
|
104
164
|
if (common.some(data.mempool.boxes)) {
|
105
|
-
const mempoolBoxes = data.mempool.boxes.filter(notBeingSpent).map(
|
165
|
+
const mempoolBoxes = data.mempool.boxes.filter(notBeingSpent).map((b) => mapUnconfirmedBox(b, this.#biMapper));
|
106
166
|
boxes = boxes.concat(mempoolBoxes);
|
107
167
|
}
|
108
168
|
inclPool = data.mempool.boxes.length === PAGE_SIZE;
|
@@ -121,14 +181,54 @@ var ErgoGraphQLProvider = class {
|
|
121
181
|
} while (inclChain || inclPool);
|
122
182
|
}
|
123
183
|
async getBoxes(query) {
|
124
|
-
|
125
|
-
for await (const chunk of this.streamBoxes(query))
|
126
|
-
|
184
|
+
const boxes = [];
|
185
|
+
for await (const chunk of this.streamBoxes(query)) boxes.push(chunk);
|
186
|
+
return common.orderBy(boxes.flat(), (box) => box.creationHeight);
|
187
|
+
}
|
188
|
+
async *streamUnconfirmedTransactions(query) {
|
189
|
+
const args = buildGqlUnconfirmedTxQueryArgs(query.where);
|
190
|
+
let keepFetching = true;
|
191
|
+
while (keepFetching) {
|
192
|
+
const response = await this.#getUnconfirmedTransactions(args);
|
193
|
+
if (common.some(response.data?.mempool?.transactions)) {
|
194
|
+
yield response.data.mempool.transactions.map(
|
195
|
+
(t) => mapUnconfirmedTransaction(t, this.#biMapper)
|
196
|
+
);
|
197
|
+
}
|
198
|
+
keepFetching = response.data?.mempool?.transactions?.length === PAGE_SIZE;
|
199
|
+
if (keepFetching) args.skip += PAGE_SIZE;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
async getUnconfirmedTransactions(query) {
|
203
|
+
const transactions = [];
|
204
|
+
for await (const chunk of this.streamUnconfirmedTransactions(query)) {
|
205
|
+
transactions.push(chunk);
|
206
|
+
}
|
207
|
+
return transactions.flat();
|
208
|
+
}
|
209
|
+
async *streamConfirmedTransactions(query) {
|
210
|
+
const args = buildGqlConfirmedTxQueryArgs(query.where);
|
211
|
+
let keepFetching = true;
|
212
|
+
while (keepFetching) {
|
213
|
+
const response = await this.#getConfirmedTransactions(args);
|
214
|
+
if (common.some(response.data?.transactions)) {
|
215
|
+
yield response.data.transactions.map(
|
216
|
+
(t) => mapConfirmedTransaction(t, this.#biMapper)
|
217
|
+
);
|
218
|
+
}
|
219
|
+
keepFetching = response.data?.transactions?.length === PAGE_SIZE;
|
220
|
+
if (keepFetching) args.skip += PAGE_SIZE;
|
127
221
|
}
|
128
|
-
|
222
|
+
}
|
223
|
+
async getConfirmedTransactions(query) {
|
224
|
+
const transactions = [];
|
225
|
+
for await (const chunk of this.streamConfirmedTransactions(query)) {
|
226
|
+
transactions.push(chunk);
|
227
|
+
}
|
228
|
+
return transactions.flat();
|
129
229
|
}
|
130
230
|
async getHeaders(query) {
|
131
|
-
const response = await this.#getHeaders(query);
|
231
|
+
const response = await this.#getHeaders(query, this.#options.url);
|
132
232
|
return response.data?.blockHeaders.map((header) => ({
|
133
233
|
...header,
|
134
234
|
id: header.headerId,
|
@@ -144,7 +244,10 @@ var ErgoGraphQLProvider = class {
|
|
144
244
|
}
|
145
245
|
async checkTransaction(signedTransaction) {
|
146
246
|
try {
|
147
|
-
const response = await this.#
|
247
|
+
const response = await this.#checkTransaction(
|
248
|
+
{ signedTransaction },
|
249
|
+
this.#options.url
|
250
|
+
);
|
148
251
|
return { success: true, transactionId: response.data.checkTransaction };
|
149
252
|
} catch (e) {
|
150
253
|
return { success: false, message: e.message };
|
@@ -152,16 +255,17 @@ var ErgoGraphQLProvider = class {
|
|
152
255
|
}
|
153
256
|
async submitTransaction(signedTransaction) {
|
154
257
|
try {
|
155
|
-
const response = await this.#
|
258
|
+
const response = await this.#sendTransaction(
|
259
|
+
{ signedTransaction },
|
260
|
+
this.#options.url
|
261
|
+
);
|
156
262
|
return { success: true, transactionId: response.data.submitTransaction };
|
157
263
|
} catch (e) {
|
158
264
|
return { success: false, message: e.message };
|
159
265
|
}
|
160
266
|
}
|
161
267
|
reduceTransaction() {
|
162
|
-
throw new common.NotSupportedError(
|
163
|
-
"Transaction reducing is not supported by ergo-graphql."
|
164
|
-
);
|
268
|
+
throw new common.NotSupportedError("Transaction reducing is not supported by ergo-graphql.");
|
165
269
|
}
|
166
270
|
};
|
167
271
|
function buildGqlBoxQueryArgs(where) {
|
@@ -177,14 +281,38 @@ function buildGqlBoxQueryArgs(where) {
|
|
177
281
|
const addresses = merge(where.addresses, where.address);
|
178
282
|
if (common.some(addresses)) {
|
179
283
|
const trees = addresses.map(
|
180
|
-
(address) => typeof address === "string" ? core.ErgoAddress.
|
181
|
-
);
|
182
|
-
args.ergoTrees = common.uniq(
|
183
|
-
common.some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees
|
284
|
+
(address) => typeof address === "string" ? core.ErgoAddress.decode(address).ergoTree : address.ergoTree
|
184
285
|
);
|
286
|
+
args.ergoTrees = common.uniq(common.some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees);
|
185
287
|
}
|
186
288
|
return args;
|
187
289
|
}
|
290
|
+
function buildGqlUnconfirmedTxQueryArgs(where) {
|
291
|
+
const addresses = common.uniq(
|
292
|
+
[
|
293
|
+
merge(where.addresses, where.address)?.map(
|
294
|
+
(address) => typeof address === "string" ? address : address.encode()
|
295
|
+
) ?? [],
|
296
|
+
merge(where.ergoTrees, where.ergoTree)?.map(
|
297
|
+
(tree) => core.ErgoAddress.fromErgoTree(tree).encode()
|
298
|
+
) ?? []
|
299
|
+
].flat()
|
300
|
+
);
|
301
|
+
return {
|
302
|
+
addresses: addresses.length ? addresses : void 0,
|
303
|
+
transactionIds: merge(where.transactionIds, where.transactionId),
|
304
|
+
skip: 0,
|
305
|
+
take: PAGE_SIZE
|
306
|
+
};
|
307
|
+
}
|
308
|
+
function buildGqlConfirmedTxQueryArgs(where) {
|
309
|
+
return {
|
310
|
+
...buildGqlUnconfirmedTxQueryArgs(where),
|
311
|
+
headerId: where.headerId,
|
312
|
+
minHeight: where.minHeight,
|
313
|
+
onlyRelevantOutputs: where.onlyRelevantOutputs
|
314
|
+
};
|
315
|
+
}
|
188
316
|
function merge(array, el) {
|
189
317
|
if (common.isEmpty(array) && common.isUndefined(el)) return;
|
190
318
|
const set = new Set(array ?? []);
|
@@ -197,18 +325,70 @@ function hasMempool(data) {
|
|
197
325
|
function hasConfirmed(data) {
|
198
326
|
return !!data?.boxes;
|
199
327
|
}
|
200
|
-
function
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
328
|
+
function mapConfirmedBox(box, mapper) {
|
329
|
+
const mapped = mapBox(box, mapper);
|
330
|
+
mapped.confirmed = true;
|
331
|
+
return mapped;
|
332
|
+
}
|
333
|
+
function mapUnconfirmedBox(box, mapper) {
|
334
|
+
const mapped = mapBox(box, mapper);
|
335
|
+
mapped.confirmed = false;
|
336
|
+
return mapped;
|
337
|
+
}
|
338
|
+
function mapBox(box, mapper) {
|
339
|
+
return {
|
340
|
+
boxId: box.boxId,
|
341
|
+
transactionId: box.transactionId,
|
342
|
+
value: mapper(box.value),
|
343
|
+
ergoTree: box.ergoTree,
|
344
|
+
assets: box.assets.map((t) => ({ tokenId: t.tokenId, amount: mapper(t.amount) })),
|
345
|
+
creationHeight: box.creationHeight,
|
346
|
+
additionalRegisters: box.additionalRegisters,
|
347
|
+
index: box.index
|
348
|
+
};
|
349
|
+
}
|
350
|
+
function mapUnconfirmedTransaction(tx, mapper) {
|
351
|
+
return {
|
352
|
+
transactionId: tx.transactionId,
|
353
|
+
timestamp: Number(tx.timestamp),
|
354
|
+
inputs: tx.inputs.map((i) => ({
|
355
|
+
spendingProof: {
|
356
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
357
|
+
extension: i.extension,
|
358
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
359
|
+
proofBytes: i.proofBytes
|
360
|
+
},
|
361
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
362
|
+
...mapBox(i.box, mapper)
|
207
363
|
})),
|
208
|
-
|
209
|
-
|
364
|
+
dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
|
365
|
+
outputs: tx.outputs.map((b) => mapBox(b, mapper)),
|
366
|
+
confirmed: false
|
367
|
+
};
|
368
|
+
}
|
369
|
+
function mapConfirmedTransaction(tx, mapper) {
|
370
|
+
return {
|
371
|
+
transactionId: tx.transactionId,
|
372
|
+
timestamp: Number(tx.timestamp),
|
373
|
+
inputs: tx.inputs.map((i) => ({
|
374
|
+
spendingProof: {
|
375
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
376
|
+
extension: i.extension,
|
377
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
378
|
+
proofBytes: i.proofBytes
|
379
|
+
},
|
380
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
381
|
+
...mapBox(i.box, mapper)
|
382
|
+
})),
|
383
|
+
dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
|
384
|
+
outputs: tx.outputs.map((b) => mapBox(b, mapper)),
|
385
|
+
height: tx.inclusionHeight,
|
386
|
+
headerId: tx.headerId,
|
387
|
+
index: tx.index,
|
388
|
+
confirmed: true
|
389
|
+
};
|
210
390
|
}
|
211
391
|
|
212
392
|
exports.ErgoGraphQLProvider = ErgoGraphQLProvider;
|
213
|
-
//# sourceMappingURL=
|
393
|
+
//# sourceMappingURL=index.js.map
|
214
394
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/ergo-graphql/ergoGraphQLProvider.ts","../src/utils/graphql.ts","../src/ergo-graphql/queries.ts"],"names":["ensureDefaults","isEmpty","some"],"mappings":"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","sourcesContent":["import type {\n Box,\n QueryBoxesArgs,\n Header,\n QueryBlockHeadersArgs\n} from \"@ergo-graphql/types\";\nimport {\n type Base58String,\n type BlockHeader,\n ensureDefaults,\n type HexString,\n isEmpty,\n isUndefined,\n NotSupportedError,\n orderBy,\n type SignedTransaction,\n some,\n uniq,\n uniqBy\n} from \"@fleet-sdk/common\";\nimport { ErgoAddress } from \"@fleet-sdk/core\";\nimport type {\n BoxQuery,\n BoxWhere,\n ChainProviderBox,\n HeaderQuery,\n IBlockchainProvider,\n TransactionEvaluationResult,\n TransactionReductionResult\n} from \"../types/blockchainProvider\";\nimport {\n createGqlOperation,\n type GraphQLOperation,\n type GraphQLRequestOptions,\n type GraphQLSuccessResponse,\n type GraphQLThrowableOptions,\n type GraphQLVariables,\n isRequestParam\n} from \"../utils\";\nimport {\n ALL_BOXES_QUERY,\n CHECK_TX_MUTATION,\n CONF_BOXES_QUERY,\n HEADERS_QUERY,\n SEND_TX_MUTATION,\n UNCONF_BOXES_QUERY\n} from \"./queries\";\n\nexport type GraphQLBoxWhere = BoxWhere & {\n /** Base16-encoded BoxIds */\n boxIds?: HexString[];\n\n /** Base16-encoded ErgoTrees */\n ergoTrees?: HexString[];\n\n /** Base58-encoded addresses or `ErgoAddress` objects */\n addresses?: (Base58String | ErgoAddress)[];\n};\n\nexport type GraphQLBoxQuery = BoxQuery<GraphQLBoxWhere>;\nexport type ErgoGraphQLRequestOptions = Omit<\n GraphQLRequestOptions,\n \"throwOnNonNetworkError\"\n>;\n\ntype ConfirmedBoxesResponse = { boxes: Box[] };\ntype UnconfirmedBoxesResponse = { mempool: { boxes: Box[] } };\ntype CombinedBoxesResponse = ConfirmedBoxesResponse & UnconfirmedBoxesResponse;\ntype BlockHeadersResponse = { blockHeaders: Header[] };\ntype CheckTransactionResponse = { checkTransaction: string };\ntype TransactionSubmissionResponse = { submitTransaction: string };\ntype SignedTxArgsResp = { signedTransaction: SignedTransaction };\n\nconst PAGE_SIZE = 50;\n\nexport class ErgoGraphQLProvider implements IBlockchainProvider<BoxWhere> {\n #options: GraphQLThrowableOptions;\n\n #getConfBoxes;\n #getUnconfBoxes;\n #getAllBoxes;\n #getHeaders;\n #checkTx;\n #sendTx;\n\n constructor(url: string | URL);\n constructor(url: ErgoGraphQLRequestOptions);\n constructor(optOrUrl: ErgoGraphQLRequestOptions | string | URL) {\n this.#options = {\n ...(isRequestParam(optOrUrl) ? optOrUrl : { url: optOrUrl }),\n throwOnNonNetworkErrors: true\n };\n\n this.#getConfBoxes = this.createOperation<\n ConfirmedBoxesResponse,\n QueryBoxesArgs\n >(CONF_BOXES_QUERY);\n\n this.#getUnconfBoxes = this.createOperation<\n UnconfirmedBoxesResponse,\n QueryBoxesArgs\n >(UNCONF_BOXES_QUERY);\n\n this.#getAllBoxes = this.createOperation<\n CombinedBoxesResponse,\n QueryBoxesArgs\n >(ALL_BOXES_QUERY);\n\n this.#getHeaders = this.createOperation<\n BlockHeadersResponse,\n QueryBlockHeadersArgs\n >(HEADERS_QUERY);\n\n this.#checkTx = this.createOperation<\n CheckTransactionResponse,\n SignedTxArgsResp\n >(CHECK_TX_MUTATION);\n\n this.#sendTx = this.createOperation<\n TransactionSubmissionResponse,\n SignedTxArgsResp\n >(SEND_TX_MUTATION);\n }\n\n #fetchBoxes(args: QueryBoxesArgs, inclConf: boolean, inclUnconf: boolean) {\n return inclConf && inclUnconf\n ? this.#getAllBoxes(args)\n : inclUnconf\n ? this.#getUnconfBoxes(args)\n : this.#getConfBoxes(args);\n }\n\n async *streamBoxes(\n query: GraphQLBoxQuery\n ): AsyncGenerator<ChainProviderBox[]> {\n if (isEmpty(query.where)) {\n throw new Error(\"Cannot fetch unspent boxes without a where clause.\");\n }\n\n const notBeingSpent = (box: Box) => !box.beingSpent;\n const returnedBoxIds = new Set<string>();\n const { where, from } = query;\n const args = buildGqlBoxQueryArgs(where);\n\n let inclChain = from !== \"mempool\";\n let inclPool = from !== \"blockchain\";\n const isMempoolAware = inclPool;\n\n do {\n const response = await this.#fetchBoxes(args, inclChain, inclPool);\n\n const { data } = response;\n let boxes: ChainProviderBox[] = [];\n\n if (inclChain && hasConfirmed(data)) {\n if (some(data.boxes)) {\n const confirmedBoxes = (\n isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes\n ).map(asConfirmed(true));\n\n boxes = boxes.concat(confirmedBoxes);\n }\n\n inclChain = data.boxes.length === PAGE_SIZE;\n }\n\n if (isMempoolAware && hasMempool(data)) {\n if (some(data.mempool.boxes)) {\n const mempoolBoxes = data.mempool.boxes\n .filter(notBeingSpent)\n .map(asConfirmed(false));\n boxes = boxes.concat(mempoolBoxes);\n }\n\n inclPool = data.mempool.boxes.length === PAGE_SIZE;\n }\n\n if (some(boxes)) {\n // boxes can be moved from the mempool to the blockchain while streaming,\n // so we need to filter out boxes that have already been returned.\n if (boxes.some((box) => returnedBoxIds.has(box.boxId))) {\n boxes = boxes.filter((b) => !returnedBoxIds.has(b.boxId));\n }\n\n if (some(boxes)) {\n boxes = uniqBy(boxes, (box) => box.boxId);\n for (const box of boxes) returnedBoxIds.add(box.boxId);\n yield boxes;\n }\n }\n\n if (inclChain || inclPool) args.skip += PAGE_SIZE;\n } while (inclChain || inclPool);\n }\n\n async getBoxes(query: GraphQLBoxQuery): Promise<ChainProviderBox[]> {\n let boxes: ChainProviderBox[] = [];\n for await (const chunk of this.streamBoxes(query)) {\n boxes = boxes.concat(chunk);\n }\n\n return orderBy(boxes, (box) => box.creationHeight);\n }\n\n async getHeaders(query: HeaderQuery): Promise<BlockHeader[]> {\n const response = await this.#getHeaders(query);\n\n return (\n response.data?.blockHeaders.map((header) => ({\n ...header,\n id: header.headerId,\n timestamp: Number(header.timestamp),\n nBits: Number(header.nBits),\n votes: header.votes.join(\"\")\n })) ?? []\n );\n }\n\n createOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options?: Partial<ErgoGraphQLRequestOptions>\n ): GraphQLOperation<GraphQLSuccessResponse<R>, V> {\n const opt = ensureDefaults(options, this.#options);\n opt.throwOnNonNetworkErrors = true;\n\n return createGqlOperation(query, opt);\n }\n\n async checkTransaction(\n signedTransaction: SignedTransaction\n ): Promise<TransactionEvaluationResult> {\n try {\n const response = await this.#checkTx({ signedTransaction });\n\n return { success: true, transactionId: response.data.checkTransaction };\n } catch (e) {\n return { success: false, message: (e as Error).message };\n }\n }\n\n async submitTransaction(\n signedTransaction: SignedTransaction\n ): Promise<TransactionEvaluationResult> {\n try {\n const response = await this.#sendTx({ signedTransaction });\n\n return { success: true, transactionId: response.data.submitTransaction };\n } catch (e) {\n return { success: false, message: (e as Error).message };\n }\n }\n\n reduceTransaction(): Promise<TransactionReductionResult> {\n throw new NotSupportedError(\n \"Transaction reducing is not supported by ergo-graphql.\"\n );\n }\n}\n\nfunction buildGqlBoxQueryArgs(where: GraphQLBoxWhere) {\n const args = {\n spent: false,\n boxIds: merge(where.boxIds, where.boxId),\n ergoTrees: merge(where.ergoTrees, where.ergoTree),\n ergoTreeTemplateHash: where.templateHash,\n tokenId: where.tokenId,\n skip: 0,\n take: PAGE_SIZE\n } satisfies QueryBoxesArgs;\n\n const addresses = merge(where.addresses, where.address);\n if (some(addresses)) {\n const trees = addresses.map((address) =>\n typeof address === \"string\"\n ? ErgoAddress.fromBase58(address).ergoTree\n : address.ergoTree\n );\n\n args.ergoTrees = uniq(\n some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees\n );\n }\n\n return args;\n}\n\nfunction merge<T>(array?: T[], el?: T) {\n if (isEmpty(array) && isUndefined(el)) return;\n\n const set = new Set<T>(array ?? []);\n if (!isUndefined(el)) set.add(el);\n return Array.from(set.values());\n}\n\nfunction hasMempool(data: unknown): data is UnconfirmedBoxesResponse {\n return !!(data as UnconfirmedBoxesResponse)?.mempool?.boxes;\n}\n\nfunction hasConfirmed(data: unknown): data is ConfirmedBoxesResponse {\n return !!(data as ConfirmedBoxesResponse)?.boxes;\n}\n\nfunction asConfirmed(confirmed: boolean) {\n return (box: Box): ChainProviderBox => ({\n ...box,\n value: BigInt(box.value),\n assets: box.assets.map((asset) => ({\n tokenId: asset.tokenId,\n amount: BigInt(asset.amount)\n })),\n confirmed\n });\n}\n","import {\n BlockchainProviderError,\n clearUndefined,\n ensureDefaults,\n isEmpty,\n some\n} from \"@fleet-sdk/common\";\n\nconst OP_NAME_REGEX = /(query|mutation)\\s?([\\w\\-_]+)?/;\nexport const DEFAULT_HEADERS: Headers = {\n \"content-type\": \"application/json; charset=utf-8\",\n accept: \"application/graphql-response+json, application/json\"\n};\n\ntype Credentials = RequestCredentials;\ntype Headers = HeadersInit;\ntype Fetcher = typeof fetch;\n\nexport type GraphQLVariables = Record<string, unknown> | null;\n\nexport interface GraphQLError {\n message: string;\n}\n\nexport interface GraphQLSuccessResponse<T = unknown> {\n data: T;\n errors: null;\n}\n\nexport interface GraphQLErrorResponse {\n data: null;\n errors: GraphQLError[];\n}\n\nexport type GraphQLResponse<T = unknown> =\n | GraphQLSuccessResponse<T>\n | GraphQLErrorResponse;\n\nexport type GraphQLOperation<\n R extends GraphQLResponse,\n V extends GraphQLVariables\n> = (variables?: V) => Promise<R>;\n\nexport interface ResponseParser {\n parse<T>(text: string): T;\n stringify<T>(value: T): string;\n}\n\nexport interface RequestParams {\n operationName?: string | null;\n query: string;\n variables?: Record<string, unknown> | null;\n}\n\nexport interface GraphQLRequestOptions {\n url: URL | string;\n headers?: Headers;\n parser?: ResponseParser;\n fetcher?: Fetcher;\n credentials?: Credentials;\n throwOnNonNetworkErrors?: boolean;\n}\n\nexport interface GraphQLThrowableOptions extends GraphQLRequestOptions {\n throwOnNonNetworkErrors: true;\n}\n\nexport function createGqlOperation<\n R,\n V extends GraphQLVariables = GraphQLVariables\n>(\n query: string,\n options: GraphQLThrowableOptions\n): GraphQLOperation<GraphQLSuccessResponse<R>, V>;\nexport function createGqlOperation<\n R,\n V extends GraphQLVariables = GraphQLVariables\n>(\n query: string,\n options: GraphQLRequestOptions\n): GraphQLOperation<GraphQLResponse<R>, V>;\nexport function createGqlOperation<\n R,\n V extends GraphQLVariables = GraphQLVariables\n>(\n query: string,\n options: GraphQLRequestOptions\n): GraphQLOperation<GraphQLResponse<R>, V> {\n return async (variables?: V): Promise<GraphQLResponse<R>> => {\n const response = await (options.fetcher ?? fetch)(options.url, {\n method: \"POST\",\n headers: ensureDefaults(options.headers, DEFAULT_HEADERS),\n credentials: options.credentials,\n body: (options.parser ?? JSON).stringify({\n operationName: getOpName(query),\n query,\n variables: variables ? clearUndefined(variables) : undefined\n } as RequestParams)\n });\n\n const rawData = await response.text();\n const parsedData = (options.parser ?? JSON).parse(\n rawData\n ) as GraphQLResponse<R>;\n\n if (\n options.throwOnNonNetworkErrors &&\n some(parsedData.errors) &&\n isEmpty(parsedData.data)\n ) {\n throw new BlockchainProviderError(parsedData.errors[0].message, {\n cause: parsedData.errors\n });\n }\n\n return parsedData;\n };\n}\n\nexport function gql(query: TemplateStringsArray): string {\n return query[0];\n}\n\nexport function getOpName(query: string): string | undefined {\n return OP_NAME_REGEX.exec(query)?.at(2);\n}\n\nexport function isRequestParam(obj: unknown): obj is GraphQLRequestOptions {\n return (\n typeof obj === \"object\" && (obj as GraphQLRequestOptions).url !== undefined\n );\n}\n","const B = [\n \"query boxes($spent: Boolean! $boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int)\",\n \"boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take\",\n \"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters beingSpent\"\n];\n\nexport const CONF_BOXES_QUERY = `${B[0]} { boxes(spent: $spent ${B[1]}) { ${B[2]} } }`;\nexport const UNCONF_BOXES_QUERY = `${B[0]} { mempool { boxes(${B[1]}) { ${B[2]} } } }`;\nexport const ALL_BOXES_QUERY = `${B[0]} { boxes(spent: $spent ${B[1]}) { ${B[2]} } mempool { boxes(${B[1]}) { ${B[2]} } } }`;\nexport const HEADERS_QUERY =\n \"query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }\";\nexport const CHECK_TX_MUTATION =\n \"mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }\";\nexport const SEND_TX_MUTATION =\n \"mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }\";\n"]}
|
1
|
+
{"version":3,"sources":["../src/utils/networking.ts","../src/utils/graphql.ts","../src/ergo-graphql/queries.ts","../src/ergo-graphql/ergoGraphQLProvider.ts"],"names":["some","ensureDefaults","clearUndefined","isEmpty","BlockchainProviderError","uniqBy","orderBy","NotSupportedError","ErgoAddress","uniq","isUndefined"],"mappings":"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","file":"index.js","sourcesContent":["import { some } from \"@fleet-sdk/common\";\nimport { isEmpty } from \"packages/common/src\";\n\nexport interface ParserLike {\n parse<T>(text: string): T;\n stringify<T>(value: T): string;\n}\n\nexport type Route = { base: string; path: string; query?: Record<string, unknown> };\nexport type URLLike = string | Route;\nexport type FallbackRetryOptions = { fallbacks?: URLLike[] } & RetryOptions;\n\nexport type FetchOptions = {\n parser?: ParserLike;\n base?: string;\n query?: Record<string, unknown>;\n retry?: FallbackRetryOptions;\n httpOptions?: RequestInit;\n};\n\nexport async function request<T>(path: string, opt?: Partial<FetchOptions>): Promise<T> {\n const url = buildURL(path, opt?.query, opt?.base);\n\n let response: Response;\n if (opt?.retry) {\n const routes = some(opt.retry.fallbacks) ? [url, ...opt.retry.fallbacks] : [url];\n const attempts = opt.retry.attempts;\n response = await exponentialRetry(\n (r) => fetch(resolveUrl(routes, attempts - r), opt.httpOptions),\n opt.retry\n );\n } else {\n response = await fetch(url, opt?.httpOptions);\n }\n\n return (opt?.parser || JSON).parse(await response.text());\n}\n\nfunction resolveUrl(routes: URLLike[], attempt: number) {\n const route = routes[attempt % routes.length];\n return typeof route === \"string\"\n ? route\n : buildURL(route.path, route.query, route.base).toString();\n}\n\nfunction buildURL(path: string, query?: Record<string, unknown>, base?: string) {\n if (!base && !query) return path;\n\n const url = new URL(path, base);\n if (some(query)) {\n for (const key in query) url.searchParams.append(key, String(query[key]));\n }\n\n return url.toString();\n}\n\nexport type RetryOptions = {\n attempts: number;\n delay: number;\n};\n\n/**\n * Retries an asynchronous operation a specified number of times with a delay\n * growing exponentially between each attempt.\n * @param operation - The asynchronous operation to retry.\n * @param options - The retry options.\n * @returns A promise that resolves to the result of the operation, or undefined\n * if all attempts fail.\n */\nexport async function exponentialRetry<T>(\n operation: (remainingAttempts: number) => Promise<T>,\n { attempts, delay }: RetryOptions\n): Promise<T> {\n try {\n return await operation(attempts);\n } catch (e) {\n if (attempts > 0) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n return exponentialRetry(operation, { attempts: attempts - 1, delay: delay * 2 });\n }\n\n throw e;\n }\n}\n","import {\n BlockchainProviderError,\n clearUndefined,\n ensureDefaults,\n isEmpty,\n some\n} from \"@fleet-sdk/common\";\nimport type { FallbackRetryOptions, ParserLike } from \"./networking\";\nimport { request } from \"./networking\";\n\nconst OP_NAME_REGEX = /(query|mutation)\\s?([\\w\\-_]+)?/;\nexport const DEFAULT_HEADERS = {\n \"content-type\": \"application/json; charset=utf-8\",\n accept: \"application/graphql-response+json, application/json\"\n};\n\nexport type GraphQLVariables = Record<string, unknown> | null;\n\nexport interface GraphQLError {\n message: string;\n}\n\nexport interface GraphQLSuccessResponse<T = unknown> {\n data: T;\n errors: null;\n}\n\nexport interface GraphQLErrorResponse {\n data: null;\n errors: GraphQLError[];\n}\n\nexport type GraphQLResponse<T = unknown> =\n | GraphQLSuccessResponse<T>\n | GraphQLErrorResponse;\n\nexport type GraphQLOperation<R extends GraphQLResponse, V extends GraphQLVariables> = (\n variables?: V,\n url?: string\n) => Promise<R>;\n\nexport type GraphQLRequiredUrlOperation<\n R extends GraphQLResponse,\n V extends GraphQLVariables\n> = (variables: V | undefined, url: string) => Promise<R>;\n\ninterface RequestParams {\n operationName?: string | null;\n query: string;\n variables?: Record<string, unknown> | null;\n}\n\nexport interface GraphQLRequestOptions {\n url?: string;\n parser?: ParserLike;\n retry?: FallbackRetryOptions;\n throwOnNonNetworkErrors?: boolean;\n httpOptions?: Omit<RequestInit, \"body\" | \"method\">;\n}\n\nexport function createGqlOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options: GraphQLRequestOptions & { throwOnNonNetworkErrors: true }\n): GraphQLOperation<GraphQLSuccessResponse<R>, V>;\nexport function createGqlOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options?: GraphQLRequestOptions & { url: undefined }\n): GraphQLRequiredUrlOperation<GraphQLResponse<R>, V>;\nexport function createGqlOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options: GraphQLRequestOptions & { url: undefined; throwOnNonNetworkErrors: true }\n): GraphQLRequiredUrlOperation<GraphQLSuccessResponse<R>, V>;\nexport function createGqlOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options: GraphQLRequestOptions\n): GraphQLOperation<GraphQLResponse<R>, V>;\nexport function createGqlOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options?: GraphQLRequestOptions\n):\n | GraphQLOperation<GraphQLResponse<R>, V>\n | GraphQLRequiredUrlOperation<GraphQLResponse<R>, V> {\n return async (variables?: V, url?: string): Promise<GraphQLResponse<R>> => {\n url = url ?? options?.url;\n if (!url) throw new Error(\"URL is required\");\n\n const response = await request<GraphQLResponse<R>>(url, {\n ...options,\n httpOptions: {\n ...options?.httpOptions,\n method: \"POST\",\n headers: ensureDefaults(options?.httpOptions?.headers, DEFAULT_HEADERS),\n body: (options?.parser ?? JSON).stringify({\n operationName: getOpName(query),\n query,\n variables: variables ? clearUndefined(variables) : undefined\n } as RequestParams)\n }\n });\n\n if (\n options?.throwOnNonNetworkErrors &&\n some(response.errors) &&\n isEmpty(response.data)\n ) {\n const msg = response.errors[0].message;\n throw new BlockchainProviderError(msg, { cause: response.errors });\n }\n\n return response;\n };\n}\n\nexport function gql(query: TemplateStringsArray): string {\n return query[0];\n}\n\nexport function getOpName(query: string): string | undefined {\n return OP_NAME_REGEX.exec(query)?.at(2);\n}\n\nexport function isRequestParam(obj: unknown): obj is GraphQLRequestOptions {\n return typeof obj === \"object\" && (obj as GraphQLRequestOptions).url !== undefined;\n}\n","const B = [\n \"$boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int\",\n \"boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take\",\n \"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters\"\n];\n\nexport const CONF_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } }`;\nexport const UNCONF_BOXES_QUERY = `query boxes(${B[0]}) { mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;\nexport const ALL_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;\n\nexport const HEADERS_QUERY =\n \"query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }\";\nexport const CHECK_TX_MUTATION =\n \"mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }\";\nexport const SEND_TX_MUTATION =\n \"mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }\";\n\nconst T = [\n \"$addresses: [String!], $transactionIds: [String!], $skip: Int, $take: Int\",\n \"addresses: $addresses, transactionIds: $transactionIds, skip: $skip, take: $take\",\n `transactionId timestamp inputs { proofBytes extension index box { ${B[2]} } } dataInputs { boxId }`\n];\nexport const CONF_TX_QUERY = `query confirmedTransactions(${T[0]} $relevantOnly: Boolean) { transactions(${T[1]}) { ${T[2]} outputs(relevantOnly: $relevantOnly) { ${B[2]} } inclusionHeight headerId index } }`;\nexport const UNCONF_TX_QUERY = `query unconfirmedTransactions(${T[0]}) { mempool { transactions(${T[1]}) { ${T[2]} outputs { ${B[2]} } } } }`;\n","import type {\n Box as GQLBox,\n QueryBoxesArgs,\n Header,\n QueryBlockHeadersArgs,\n Transaction,\n QueryTransactionsArgs,\n MempoolTransactionsArgs,\n UnconfirmedTransaction,\n UnconfirmedBox as GQLUnconfirmedBox\n} from \"@ergo-graphql/types\";\nimport {\n type Base58String,\n type BlockHeader,\n ensureDefaults,\n type HexString,\n isEmpty,\n isUndefined,\n NotSupportedError,\n orderBy,\n type SignedTransaction,\n some,\n uniq,\n uniqBy\n} from \"@fleet-sdk/common\";\nimport { ErgoAddress } from \"@fleet-sdk/core\";\nimport type {\n BoxQuery,\n BoxWhere,\n ChainProviderBox,\n ChainProviderConfirmedTransaction,\n ChainProviderUnconfirmedTransaction,\n HeaderQuery,\n IBlockchainProvider,\n TransactionEvaluationResult,\n TransactionQuery,\n TransactionReductionResult,\n ConfirmedTransactionWhere,\n UnconfirmedTransactionWhere\n} from \"../types/blockchainProvider\";\nimport {\n createGqlOperation,\n type GraphQLOperation,\n type GraphQLRequestOptions,\n type GraphQLSuccessResponse,\n type GraphQLVariables,\n isRequestParam\n} from \"../utils\";\nimport {\n ALL_BOXES_QUERY,\n CHECK_TX_MUTATION,\n CONF_BOXES_QUERY,\n CONF_TX_QUERY,\n HEADERS_QUERY,\n SEND_TX_MUTATION,\n UNCONF_BOXES_QUERY,\n UNCONF_TX_QUERY\n} from \"./queries\";\n\ntype GraphQLThrowableOptions = GraphQLRequestOptions & { throwOnNonNetworkErrors: true };\ntype OP<R, V extends GraphQLVariables> = GraphQLOperation<GraphQLSuccessResponse<R>, V>;\ntype BiMapper<T> = (value: string) => T;\n\nexport type GraphQLBoxWhere = BoxWhere & {\n /** Base16-encoded BoxIds */\n boxIds?: HexString[];\n\n /** Base16-encoded ErgoTrees */\n ergoTrees?: HexString[];\n\n /** Base58-encoded addresses or `ErgoAddress` objects */\n addresses?: (Base58String | ErgoAddress)[];\n};\n\nexport type GraphQLConfirmedTransactionWhere = ConfirmedTransactionWhere & {\n transactionIds?: HexString[];\n addresses?: (Base58String | ErgoAddress)[];\n ergoTrees?: HexString[];\n};\n\nexport type GraphQLUnconfirmedTransactionWhere = UnconfirmedTransactionWhere & {\n transactionIds?: HexString[];\n addresses?: (Base58String | ErgoAddress)[];\n ergoTrees?: HexString[];\n};\n\nexport type GraphQLBoxQuery = BoxQuery<GraphQLBoxWhere>;\nexport type ErgoGraphQLRequestOptions = Omit<\n GraphQLRequestOptions,\n \"throwOnNonNetworkError\"\n>;\n\ntype ConfirmedBoxesResponse = { boxes: GQLBox[] };\ntype UnconfirmedBoxesResponse = { mempool: { boxes: GQLBox[] } };\ntype CombinedBoxesResponse = ConfirmedBoxesResponse & UnconfirmedBoxesResponse;\ntype UnconfirmedTxResponse = { mempool: { transactions: UnconfirmedTransaction[] } };\ntype ConfirmedTxResponse = { transactions: Transaction[] };\ntype BlockHeadersResponse = { blockHeaders: Header[] };\ntype CheckTransactionResponse = { checkTransaction: string };\ntype TransactionSubmissionResponse = { submitTransaction: string };\ntype SignedTxArgsResp = { signedTransaction: SignedTransaction };\n\nconst PAGE_SIZE = 50;\n\nexport class ErgoGraphQLProvider<I = bigint> implements IBlockchainProvider<I> {\n #options: GraphQLThrowableOptions;\n #biMapper: BiMapper<I>;\n\n #getConfirmedBoxes: OP<ConfirmedBoxesResponse, QueryBoxesArgs>;\n #getUnconfirmedBoxes: OP<UnconfirmedBoxesResponse, QueryBoxesArgs>;\n #getAllBoxes: OP<CombinedBoxesResponse, QueryBoxesArgs>;\n #getConfirmedTransactions: OP<ConfirmedTxResponse, QueryTransactionsArgs>;\n #getUnconfirmedTransactions: OP<UnconfirmedTxResponse, MempoolTransactionsArgs>;\n #checkTransaction: OP<CheckTransactionResponse, SignedTxArgsResp>;\n #sendTransaction: OP<TransactionSubmissionResponse, SignedTxArgsResp>;\n #getHeaders!: OP<BlockHeadersResponse, QueryBlockHeadersArgs>;\n\n constructor(url: string);\n constructor(url: ErgoGraphQLRequestOptions);\n constructor(optOrUrl: ErgoGraphQLRequestOptions | string) {\n this.#options = {\n ...(isRequestParam(optOrUrl) ? optOrUrl : { url: optOrUrl }),\n throwOnNonNetworkErrors: true\n };\n\n this.#biMapper = (value) => BigInt(value) as I;\n\n this.#getConfirmedBoxes = this.createOperation(CONF_BOXES_QUERY);\n this.#getUnconfirmedBoxes = this.createOperation(UNCONF_BOXES_QUERY);\n this.#getAllBoxes = this.createOperation(ALL_BOXES_QUERY);\n this.#getConfirmedTransactions = this.createOperation(CONF_TX_QUERY);\n this.#getUnconfirmedTransactions = this.createOperation(UNCONF_TX_QUERY);\n this.#checkTransaction = this.createOperation(CHECK_TX_MUTATION);\n this.#sendTransaction = this.createOperation(SEND_TX_MUTATION);\n this.#getHeaders = this.createOperation(HEADERS_QUERY);\n }\n\n #fetchBoxes(args: QueryBoxesArgs, inclConf: boolean, inclUnconf: boolean) {\n return inclConf && inclUnconf\n ? this.#getAllBoxes(args, this.#options.url)\n : inclUnconf\n ? this.#getUnconfirmedBoxes(args, this.#options.url)\n : this.#getConfirmedBoxes(args, this.#options.url);\n }\n\n setUrl(url: string): ErgoGraphQLProvider<I> {\n this.#options.url = url;\n return this;\n }\n\n setBigIntMapper<M>(mapper: BiMapper<M>): ErgoGraphQLProvider<M> {\n this.#biMapper = mapper as unknown as BiMapper<I>;\n return this as unknown as ErgoGraphQLProvider<M>;\n }\n\n async *streamBoxes(query: GraphQLBoxQuery): AsyncGenerator<ChainProviderBox<I>[]> {\n if (isEmpty(query.where)) {\n throw new Error(\"Cannot fetch unspent boxes without a where clause.\");\n }\n\n const notBeingSpent = (box: GQLBox) => !box.beingSpent;\n const returnedBoxIds = new Set<string>();\n const { where, from } = query;\n const args = buildGqlBoxQueryArgs(where);\n\n let inclChain = from !== \"mempool\";\n let inclPool = from !== \"blockchain\";\n const isMempoolAware = inclPool;\n\n do {\n const { data } = await this.#fetchBoxes(args, inclChain, inclPool);\n let boxes: ChainProviderBox<I>[] = [];\n\n if (inclChain && hasConfirmed(data)) {\n if (some(data.boxes)) {\n const confirmedBoxes = (\n isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes\n ).map((b) => mapConfirmedBox(b, this.#biMapper));\n\n boxes = boxes.concat(confirmedBoxes);\n }\n\n inclChain = data.boxes.length === PAGE_SIZE;\n }\n\n if (isMempoolAware && hasMempool(data)) {\n if (some(data.mempool.boxes)) {\n const mempoolBoxes = data.mempool.boxes\n .filter(notBeingSpent)\n .map((b) => mapUnconfirmedBox(b, this.#biMapper));\n boxes = boxes.concat(mempoolBoxes);\n }\n\n inclPool = data.mempool.boxes.length === PAGE_SIZE;\n }\n\n if (some(boxes)) {\n // boxes can be moved from the mempool to the blockchain while streaming,\n // so we need to filter out boxes that have already been returned.\n if (boxes.some((box) => returnedBoxIds.has(box.boxId))) {\n boxes = boxes.filter((b) => !returnedBoxIds.has(b.boxId));\n }\n\n if (some(boxes)) {\n boxes = uniqBy(boxes, (box) => box.boxId);\n for (const box of boxes) returnedBoxIds.add(box.boxId);\n yield boxes;\n }\n }\n\n if (inclChain || inclPool) args.skip += PAGE_SIZE;\n } while (inclChain || inclPool);\n }\n\n async getBoxes(query: GraphQLBoxQuery): Promise<ChainProviderBox<I>[]> {\n const boxes: ChainProviderBox<I>[][] = [];\n for await (const chunk of this.streamBoxes(query)) boxes.push(chunk);\n return orderBy(boxes.flat(), (box) => box.creationHeight);\n }\n\n async *streamUnconfirmedTransactions(\n query: TransactionQuery<GraphQLUnconfirmedTransactionWhere>\n ): AsyncIterable<ChainProviderUnconfirmedTransaction<I>[]> {\n const args = buildGqlUnconfirmedTxQueryArgs(query.where);\n\n let keepFetching = true;\n while (keepFetching) {\n const response = await this.#getUnconfirmedTransactions(args);\n if (some(response.data?.mempool?.transactions)) {\n yield response.data.mempool.transactions.map((t) =>\n mapUnconfirmedTransaction(t, this.#biMapper)\n );\n }\n\n keepFetching = response.data?.mempool?.transactions?.length === PAGE_SIZE;\n if (keepFetching) args.skip += PAGE_SIZE;\n }\n }\n\n async getUnconfirmedTransactions(\n query: TransactionQuery<GraphQLUnconfirmedTransactionWhere>\n ): Promise<ChainProviderUnconfirmedTransaction<I>[]> {\n const transactions: ChainProviderUnconfirmedTransaction<I>[][] = [];\n for await (const chunk of this.streamUnconfirmedTransactions(query)) {\n transactions.push(chunk);\n }\n\n return transactions.flat();\n }\n\n async *streamConfirmedTransactions(\n query: TransactionQuery<GraphQLConfirmedTransactionWhere>\n ): AsyncIterable<ChainProviderConfirmedTransaction<I>[]> {\n const args = buildGqlConfirmedTxQueryArgs(query.where);\n\n let keepFetching = true;\n while (keepFetching) {\n const response = await this.#getConfirmedTransactions(args);\n if (some(response.data?.transactions)) {\n yield response.data.transactions.map((t) =>\n mapConfirmedTransaction(t, this.#biMapper)\n );\n }\n\n keepFetching = response.data?.transactions?.length === PAGE_SIZE;\n if (keepFetching) args.skip += PAGE_SIZE;\n }\n }\n\n async getConfirmedTransactions(\n query: TransactionQuery<GraphQLConfirmedTransactionWhere>\n ): Promise<ChainProviderConfirmedTransaction<I>[]> {\n const transactions: ChainProviderConfirmedTransaction<I>[][] = [];\n for await (const chunk of this.streamConfirmedTransactions(query)) {\n transactions.push(chunk);\n }\n\n return transactions.flat();\n }\n\n async getHeaders(query: HeaderQuery): Promise<BlockHeader[]> {\n const response = await this.#getHeaders(query, this.#options.url);\n\n return (\n response.data?.blockHeaders.map((header) => ({\n ...header,\n id: header.headerId,\n timestamp: Number(header.timestamp),\n nBits: Number(header.nBits),\n votes: header.votes.join(\"\")\n })) ?? []\n );\n }\n\n createOperation<R, V extends GraphQLVariables = GraphQLVariables>(\n query: string,\n options?: Partial<ErgoGraphQLRequestOptions>\n ): GraphQLOperation<GraphQLSuccessResponse<R>, V> {\n const opt = ensureDefaults(options, this.#options);\n opt.throwOnNonNetworkErrors = true;\n\n return createGqlOperation(query, opt);\n }\n\n async checkTransaction(\n signedTransaction: SignedTransaction\n ): Promise<TransactionEvaluationResult> {\n try {\n const response = await this.#checkTransaction(\n { signedTransaction },\n this.#options.url\n );\n return { success: true, transactionId: response.data.checkTransaction };\n } catch (e) {\n return { success: false, message: (e as Error).message };\n }\n }\n\n async submitTransaction(\n signedTransaction: SignedTransaction\n ): Promise<TransactionEvaluationResult> {\n try {\n const response = await this.#sendTransaction(\n { signedTransaction },\n this.#options.url\n );\n return { success: true, transactionId: response.data.submitTransaction };\n } catch (e) {\n return { success: false, message: (e as Error).message };\n }\n }\n\n reduceTransaction(): Promise<TransactionReductionResult> {\n throw new NotSupportedError(\"Transaction reducing is not supported by ergo-graphql.\");\n }\n}\n\nfunction buildGqlBoxQueryArgs(where: GraphQLBoxWhere) {\n const args = {\n spent: false,\n boxIds: merge(where.boxIds, where.boxId),\n ergoTrees: merge(where.ergoTrees, where.ergoTree),\n ergoTreeTemplateHash: where.templateHash,\n tokenId: where.tokenId,\n skip: 0,\n take: PAGE_SIZE\n } satisfies QueryBoxesArgs;\n\n const addresses = merge(where.addresses, where.address);\n if (some(addresses)) {\n const trees = addresses.map((address) =>\n typeof address === \"string\"\n ? ErgoAddress.decode(address).ergoTree\n : address.ergoTree\n );\n\n args.ergoTrees = uniq(some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees);\n }\n\n return args;\n}\n\nfunction buildGqlUnconfirmedTxQueryArgs(where: GraphQLConfirmedTransactionWhere) {\n const addresses = uniq(\n [\n merge(where.addresses, where.address)?.map((address): string =>\n typeof address === \"string\" ? address : address.encode()\n ) ?? [],\n merge(where.ergoTrees, where.ergoTree)?.map((tree) =>\n ErgoAddress.fromErgoTree(tree).encode()\n ) ?? []\n ].flat()\n );\n\n return {\n addresses: addresses.length ? addresses : undefined,\n transactionIds: merge(where.transactionIds, where.transactionId),\n skip: 0,\n take: PAGE_SIZE\n };\n}\n\nfunction buildGqlConfirmedTxQueryArgs(where: GraphQLConfirmedTransactionWhere) {\n return {\n ...buildGqlUnconfirmedTxQueryArgs(where),\n headerId: where.headerId,\n minHeight: where.minHeight,\n onlyRelevantOutputs: where.onlyRelevantOutputs\n };\n}\n\nfunction merge<T>(array?: T[], el?: T) {\n if (isEmpty(array) && isUndefined(el)) return;\n\n const set = new Set<T>(array ?? []);\n if (!isUndefined(el)) set.add(el);\n return Array.from(set.values());\n}\n\nfunction hasMempool(data: unknown): data is UnconfirmedBoxesResponse {\n return !!(data as UnconfirmedBoxesResponse)?.mempool?.boxes;\n}\n\nfunction hasConfirmed(data: unknown): data is ConfirmedBoxesResponse {\n return !!(data as ConfirmedBoxesResponse)?.boxes;\n}\n\nfunction mapConfirmedBox<T>(box: GQLBox, mapper: BiMapper<T>): ChainProviderBox<T> {\n const mapped = mapBox(box, mapper) as ChainProviderBox<T>;\n mapped.confirmed = true;\n return mapped;\n}\n\nfunction mapUnconfirmedBox<T>(box: GQLBox, mapper: BiMapper<T>): ChainProviderBox<T> {\n const mapped = mapBox(box, mapper) as ChainProviderBox<T>;\n mapped.confirmed = false;\n return mapped;\n}\n\nfunction mapBox<T>(\n box: GQLBox | GQLUnconfirmedBox,\n mapper: BiMapper<T>\n): Omit<ChainProviderBox<T>, \"confirmed\"> {\n return {\n boxId: box.boxId,\n transactionId: box.transactionId,\n value: mapper(box.value),\n ergoTree: box.ergoTree,\n assets: box.assets.map((t) => ({ tokenId: t.tokenId, amount: mapper(t.amount) })),\n creationHeight: box.creationHeight,\n additionalRegisters: box.additionalRegisters,\n index: box.index\n };\n}\n\nfunction mapUnconfirmedTransaction<T>(\n tx: UnconfirmedTransaction,\n mapper: BiMapper<T>\n): ChainProviderUnconfirmedTransaction<T> {\n return {\n transactionId: tx.transactionId,\n timestamp: Number(tx.timestamp),\n inputs: tx.inputs.map((i) => ({\n spendingProof: {\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n extension: i.extension!,\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n proofBytes: i.proofBytes!\n },\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n ...mapBox(i.box!, mapper)\n })),\n dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),\n outputs: tx.outputs.map((b) => mapBox(b, mapper)),\n confirmed: false\n };\n}\n\nfunction mapConfirmedTransaction<T>(\n tx: Transaction,\n mapper: BiMapper<T>\n): ChainProviderConfirmedTransaction<T> {\n return {\n transactionId: tx.transactionId,\n timestamp: Number(tx.timestamp),\n inputs: tx.inputs.map((i) => ({\n spendingProof: {\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n extension: i.extension!,\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n proofBytes: i.proofBytes!\n },\n // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'\n ...mapBox(i.box!, mapper)\n })),\n dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),\n outputs: tx.outputs.map((b) => mapBox(b, mapper)),\n height: tx.inclusionHeight,\n headerId: tx.headerId,\n index: tx.index,\n confirmed: true\n };\n}\n"]}
|