@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.mjs
CHANGED
@@ -2,33 +2,73 @@ import { isEmpty, some, uniqBy, orderBy, ensureDefaults, NotSupportedError, uniq
|
|
2
2
|
import { ErgoAddress } from '@fleet-sdk/core';
|
3
3
|
|
4
4
|
// src/ergo-graphql/ergoGraphQLProvider.ts
|
5
|
+
async function request(path, opt) {
|
6
|
+
const url = buildURL(path, opt?.query, opt?.base);
|
7
|
+
let response;
|
8
|
+
if (opt?.retry) {
|
9
|
+
const routes = some(opt.retry.fallbacks) ? [url, ...opt.retry.fallbacks] : [url];
|
10
|
+
const attempts = opt.retry.attempts;
|
11
|
+
response = await exponentialRetry(
|
12
|
+
(r) => fetch(resolveUrl(routes, attempts - r), opt.httpOptions),
|
13
|
+
opt.retry
|
14
|
+
);
|
15
|
+
} else {
|
16
|
+
response = await fetch(url, opt?.httpOptions);
|
17
|
+
}
|
18
|
+
return (opt?.parser || JSON).parse(await response.text());
|
19
|
+
}
|
20
|
+
function resolveUrl(routes, attempt) {
|
21
|
+
const route = routes[attempt % routes.length];
|
22
|
+
return typeof route === "string" ? route : buildURL(route.path, route.query, route.base).toString();
|
23
|
+
}
|
24
|
+
function buildURL(path, query, base) {
|
25
|
+
if (!base && !query) return path;
|
26
|
+
const url = new URL(path, base);
|
27
|
+
if (some(query)) {
|
28
|
+
for (const key in query) url.searchParams.append(key, String(query[key]));
|
29
|
+
}
|
30
|
+
return url.toString();
|
31
|
+
}
|
32
|
+
async function exponentialRetry(operation, { attempts, delay }) {
|
33
|
+
try {
|
34
|
+
return await operation(attempts);
|
35
|
+
} catch (e) {
|
36
|
+
if (attempts > 0) {
|
37
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
38
|
+
return exponentialRetry(operation, { attempts: attempts - 1, delay: delay * 2 });
|
39
|
+
}
|
40
|
+
throw e;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
// src/utils/graphql.ts
|
5
45
|
var OP_NAME_REGEX = /(query|mutation)\s?([\w\-_]+)?/;
|
6
46
|
var DEFAULT_HEADERS = {
|
7
47
|
"content-type": "application/json; charset=utf-8",
|
8
48
|
accept: "application/graphql-response+json, application/json"
|
9
49
|
};
|
10
50
|
function createGqlOperation(query, options) {
|
11
|
-
return async (variables) => {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
51
|
+
return async (variables, url) => {
|
52
|
+
url = url ?? options?.url;
|
53
|
+
if (!url) throw new Error("URL is required");
|
54
|
+
const response = await request(url, {
|
55
|
+
...options,
|
56
|
+
httpOptions: {
|
57
|
+
...options?.httpOptions,
|
58
|
+
method: "POST",
|
59
|
+
headers: ensureDefaults(options?.httpOptions?.headers, DEFAULT_HEADERS),
|
60
|
+
body: (options?.parser ?? JSON).stringify({
|
61
|
+
operationName: getOpName(query),
|
62
|
+
query,
|
63
|
+
variables: variables ? clearUndefined(variables) : void 0
|
64
|
+
})
|
65
|
+
}
|
21
66
|
});
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
);
|
26
|
-
if (options.throwOnNonNetworkErrors && some(parsedData.errors) && isEmpty(parsedData.data)) {
|
27
|
-
throw new BlockchainProviderError(parsedData.errors[0].message, {
|
28
|
-
cause: parsedData.errors
|
29
|
-
});
|
67
|
+
if (options?.throwOnNonNetworkErrors && some(response.errors) && isEmpty(response.data)) {
|
68
|
+
const msg = response.errors[0].message;
|
69
|
+
throw new BlockchainProviderError(msg, { cause: response.errors });
|
30
70
|
}
|
31
|
-
return
|
71
|
+
return response;
|
32
72
|
};
|
33
73
|
}
|
34
74
|
function getOpName(query) {
|
@@ -40,41 +80,62 @@ function isRequestParam(obj) {
|
|
40
80
|
|
41
81
|
// src/ergo-graphql/queries.ts
|
42
82
|
var B = [
|
43
|
-
"
|
83
|
+
"$boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int",
|
44
84
|
"boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take",
|
45
|
-
"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters
|
85
|
+
"boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters"
|
46
86
|
];
|
47
|
-
var CONF_BOXES_QUERY =
|
48
|
-
var UNCONF_BOXES_QUERY =
|
49
|
-
var ALL_BOXES_QUERY =
|
87
|
+
var CONF_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } }`;
|
88
|
+
var UNCONF_BOXES_QUERY = `query boxes(${B[0]}) { mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;
|
89
|
+
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 } } }`;
|
50
90
|
var HEADERS_QUERY = "query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }";
|
51
91
|
var CHECK_TX_MUTATION = "mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }";
|
52
92
|
var SEND_TX_MUTATION = "mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }";
|
93
|
+
var T = [
|
94
|
+
"$addresses: [String!], $transactionIds: [String!], $skip: Int, $take: Int",
|
95
|
+
"addresses: $addresses, transactionIds: $transactionIds, skip: $skip, take: $take",
|
96
|
+
`transactionId timestamp inputs { proofBytes extension index box { ${B[2]} } } dataInputs { boxId }`
|
97
|
+
];
|
98
|
+
var CONF_TX_QUERY = `query confirmedTransactions(${T[0]} $relevantOnly: Boolean) { transactions(${T[1]}) { ${T[2]} outputs(relevantOnly: $relevantOnly) { ${B[2]} } inclusionHeight headerId index } }`;
|
99
|
+
var UNCONF_TX_QUERY = `query unconfirmedTransactions(${T[0]}) { mempool { transactions(${T[1]}) { ${T[2]} outputs { ${B[2]} } } } }`;
|
53
100
|
|
54
101
|
// src/ergo-graphql/ergoGraphQLProvider.ts
|
55
102
|
var PAGE_SIZE = 50;
|
56
103
|
var ErgoGraphQLProvider = class {
|
57
104
|
#options;
|
58
|
-
#
|
59
|
-
#
|
105
|
+
#biMapper;
|
106
|
+
#getConfirmedBoxes;
|
107
|
+
#getUnconfirmedBoxes;
|
60
108
|
#getAllBoxes;
|
109
|
+
#getConfirmedTransactions;
|
110
|
+
#getUnconfirmedTransactions;
|
111
|
+
#checkTransaction;
|
112
|
+
#sendTransaction;
|
61
113
|
#getHeaders;
|
62
|
-
#checkTx;
|
63
|
-
#sendTx;
|
64
114
|
constructor(optOrUrl) {
|
65
115
|
this.#options = {
|
66
116
|
...isRequestParam(optOrUrl) ? optOrUrl : { url: optOrUrl },
|
67
117
|
throwOnNonNetworkErrors: true
|
68
118
|
};
|
69
|
-
this.#
|
70
|
-
this.#
|
119
|
+
this.#biMapper = (value) => BigInt(value);
|
120
|
+
this.#getConfirmedBoxes = this.createOperation(CONF_BOXES_QUERY);
|
121
|
+
this.#getUnconfirmedBoxes = this.createOperation(UNCONF_BOXES_QUERY);
|
71
122
|
this.#getAllBoxes = this.createOperation(ALL_BOXES_QUERY);
|
123
|
+
this.#getConfirmedTransactions = this.createOperation(CONF_TX_QUERY);
|
124
|
+
this.#getUnconfirmedTransactions = this.createOperation(UNCONF_TX_QUERY);
|
125
|
+
this.#checkTransaction = this.createOperation(CHECK_TX_MUTATION);
|
126
|
+
this.#sendTransaction = this.createOperation(SEND_TX_MUTATION);
|
72
127
|
this.#getHeaders = this.createOperation(HEADERS_QUERY);
|
73
|
-
this.#checkTx = this.createOperation(CHECK_TX_MUTATION);
|
74
|
-
this.#sendTx = this.createOperation(SEND_TX_MUTATION);
|
75
128
|
}
|
76
129
|
#fetchBoxes(args, inclConf, inclUnconf) {
|
77
|
-
return inclConf && inclUnconf ? this.#getAllBoxes(args) : inclUnconf ? this.#
|
130
|
+
return inclConf && inclUnconf ? this.#getAllBoxes(args, this.#options.url) : inclUnconf ? this.#getUnconfirmedBoxes(args, this.#options.url) : this.#getConfirmedBoxes(args, this.#options.url);
|
131
|
+
}
|
132
|
+
setUrl(url) {
|
133
|
+
this.#options.url = url;
|
134
|
+
return this;
|
135
|
+
}
|
136
|
+
setBigIntMapper(mapper) {
|
137
|
+
this.#biMapper = mapper;
|
138
|
+
return this;
|
78
139
|
}
|
79
140
|
async *streamBoxes(query) {
|
80
141
|
if (isEmpty(query.where)) {
|
@@ -88,19 +149,18 @@ var ErgoGraphQLProvider = class {
|
|
88
149
|
let inclPool = from !== "blockchain";
|
89
150
|
const isMempoolAware = inclPool;
|
90
151
|
do {
|
91
|
-
const
|
92
|
-
const { data } = response;
|
152
|
+
const { data } = await this.#fetchBoxes(args, inclChain, inclPool);
|
93
153
|
let boxes = [];
|
94
154
|
if (inclChain && hasConfirmed(data)) {
|
95
155
|
if (some(data.boxes)) {
|
96
|
-
const confirmedBoxes = (isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes).map(
|
156
|
+
const confirmedBoxes = (isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes).map((b) => mapConfirmedBox(b, this.#biMapper));
|
97
157
|
boxes = boxes.concat(confirmedBoxes);
|
98
158
|
}
|
99
159
|
inclChain = data.boxes.length === PAGE_SIZE;
|
100
160
|
}
|
101
161
|
if (isMempoolAware && hasMempool(data)) {
|
102
162
|
if (some(data.mempool.boxes)) {
|
103
|
-
const mempoolBoxes = data.mempool.boxes.filter(notBeingSpent).map(
|
163
|
+
const mempoolBoxes = data.mempool.boxes.filter(notBeingSpent).map((b) => mapUnconfirmedBox(b, this.#biMapper));
|
104
164
|
boxes = boxes.concat(mempoolBoxes);
|
105
165
|
}
|
106
166
|
inclPool = data.mempool.boxes.length === PAGE_SIZE;
|
@@ -119,14 +179,54 @@ var ErgoGraphQLProvider = class {
|
|
119
179
|
} while (inclChain || inclPool);
|
120
180
|
}
|
121
181
|
async getBoxes(query) {
|
122
|
-
|
123
|
-
for await (const chunk of this.streamBoxes(query))
|
124
|
-
|
182
|
+
const boxes = [];
|
183
|
+
for await (const chunk of this.streamBoxes(query)) boxes.push(chunk);
|
184
|
+
return orderBy(boxes.flat(), (box) => box.creationHeight);
|
185
|
+
}
|
186
|
+
async *streamUnconfirmedTransactions(query) {
|
187
|
+
const args = buildGqlUnconfirmedTxQueryArgs(query.where);
|
188
|
+
let keepFetching = true;
|
189
|
+
while (keepFetching) {
|
190
|
+
const response = await this.#getUnconfirmedTransactions(args);
|
191
|
+
if (some(response.data?.mempool?.transactions)) {
|
192
|
+
yield response.data.mempool.transactions.map(
|
193
|
+
(t) => mapUnconfirmedTransaction(t, this.#biMapper)
|
194
|
+
);
|
195
|
+
}
|
196
|
+
keepFetching = response.data?.mempool?.transactions?.length === PAGE_SIZE;
|
197
|
+
if (keepFetching) args.skip += PAGE_SIZE;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
async getUnconfirmedTransactions(query) {
|
201
|
+
const transactions = [];
|
202
|
+
for await (const chunk of this.streamUnconfirmedTransactions(query)) {
|
203
|
+
transactions.push(chunk);
|
204
|
+
}
|
205
|
+
return transactions.flat();
|
206
|
+
}
|
207
|
+
async *streamConfirmedTransactions(query) {
|
208
|
+
const args = buildGqlConfirmedTxQueryArgs(query.where);
|
209
|
+
let keepFetching = true;
|
210
|
+
while (keepFetching) {
|
211
|
+
const response = await this.#getConfirmedTransactions(args);
|
212
|
+
if (some(response.data?.transactions)) {
|
213
|
+
yield response.data.transactions.map(
|
214
|
+
(t) => mapConfirmedTransaction(t, this.#biMapper)
|
215
|
+
);
|
216
|
+
}
|
217
|
+
keepFetching = response.data?.transactions?.length === PAGE_SIZE;
|
218
|
+
if (keepFetching) args.skip += PAGE_SIZE;
|
125
219
|
}
|
126
|
-
|
220
|
+
}
|
221
|
+
async getConfirmedTransactions(query) {
|
222
|
+
const transactions = [];
|
223
|
+
for await (const chunk of this.streamConfirmedTransactions(query)) {
|
224
|
+
transactions.push(chunk);
|
225
|
+
}
|
226
|
+
return transactions.flat();
|
127
227
|
}
|
128
228
|
async getHeaders(query) {
|
129
|
-
const response = await this.#getHeaders(query);
|
229
|
+
const response = await this.#getHeaders(query, this.#options.url);
|
130
230
|
return response.data?.blockHeaders.map((header) => ({
|
131
231
|
...header,
|
132
232
|
id: header.headerId,
|
@@ -142,7 +242,10 @@ var ErgoGraphQLProvider = class {
|
|
142
242
|
}
|
143
243
|
async checkTransaction(signedTransaction) {
|
144
244
|
try {
|
145
|
-
const response = await this.#
|
245
|
+
const response = await this.#checkTransaction(
|
246
|
+
{ signedTransaction },
|
247
|
+
this.#options.url
|
248
|
+
);
|
146
249
|
return { success: true, transactionId: response.data.checkTransaction };
|
147
250
|
} catch (e) {
|
148
251
|
return { success: false, message: e.message };
|
@@ -150,16 +253,17 @@ var ErgoGraphQLProvider = class {
|
|
150
253
|
}
|
151
254
|
async submitTransaction(signedTransaction) {
|
152
255
|
try {
|
153
|
-
const response = await this.#
|
256
|
+
const response = await this.#sendTransaction(
|
257
|
+
{ signedTransaction },
|
258
|
+
this.#options.url
|
259
|
+
);
|
154
260
|
return { success: true, transactionId: response.data.submitTransaction };
|
155
261
|
} catch (e) {
|
156
262
|
return { success: false, message: e.message };
|
157
263
|
}
|
158
264
|
}
|
159
265
|
reduceTransaction() {
|
160
|
-
throw new NotSupportedError(
|
161
|
-
"Transaction reducing is not supported by ergo-graphql."
|
162
|
-
);
|
266
|
+
throw new NotSupportedError("Transaction reducing is not supported by ergo-graphql.");
|
163
267
|
}
|
164
268
|
};
|
165
269
|
function buildGqlBoxQueryArgs(where) {
|
@@ -175,14 +279,38 @@ function buildGqlBoxQueryArgs(where) {
|
|
175
279
|
const addresses = merge(where.addresses, where.address);
|
176
280
|
if (some(addresses)) {
|
177
281
|
const trees = addresses.map(
|
178
|
-
(address) => typeof address === "string" ? ErgoAddress.
|
179
|
-
);
|
180
|
-
args.ergoTrees = uniq(
|
181
|
-
some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees
|
282
|
+
(address) => typeof address === "string" ? ErgoAddress.decode(address).ergoTree : address.ergoTree
|
182
283
|
);
|
284
|
+
args.ergoTrees = uniq(some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees);
|
183
285
|
}
|
184
286
|
return args;
|
185
287
|
}
|
288
|
+
function buildGqlUnconfirmedTxQueryArgs(where) {
|
289
|
+
const addresses = uniq(
|
290
|
+
[
|
291
|
+
merge(where.addresses, where.address)?.map(
|
292
|
+
(address) => typeof address === "string" ? address : address.encode()
|
293
|
+
) ?? [],
|
294
|
+
merge(where.ergoTrees, where.ergoTree)?.map(
|
295
|
+
(tree) => ErgoAddress.fromErgoTree(tree).encode()
|
296
|
+
) ?? []
|
297
|
+
].flat()
|
298
|
+
);
|
299
|
+
return {
|
300
|
+
addresses: addresses.length ? addresses : void 0,
|
301
|
+
transactionIds: merge(where.transactionIds, where.transactionId),
|
302
|
+
skip: 0,
|
303
|
+
take: PAGE_SIZE
|
304
|
+
};
|
305
|
+
}
|
306
|
+
function buildGqlConfirmedTxQueryArgs(where) {
|
307
|
+
return {
|
308
|
+
...buildGqlUnconfirmedTxQueryArgs(where),
|
309
|
+
headerId: where.headerId,
|
310
|
+
minHeight: where.minHeight,
|
311
|
+
onlyRelevantOutputs: where.onlyRelevantOutputs
|
312
|
+
};
|
313
|
+
}
|
186
314
|
function merge(array, el) {
|
187
315
|
if (isEmpty(array) && isUndefined(el)) return;
|
188
316
|
const set = new Set(array ?? []);
|
@@ -195,18 +323,70 @@ function hasMempool(data) {
|
|
195
323
|
function hasConfirmed(data) {
|
196
324
|
return !!data?.boxes;
|
197
325
|
}
|
198
|
-
function
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
326
|
+
function mapConfirmedBox(box, mapper) {
|
327
|
+
const mapped = mapBox(box, mapper);
|
328
|
+
mapped.confirmed = true;
|
329
|
+
return mapped;
|
330
|
+
}
|
331
|
+
function mapUnconfirmedBox(box, mapper) {
|
332
|
+
const mapped = mapBox(box, mapper);
|
333
|
+
mapped.confirmed = false;
|
334
|
+
return mapped;
|
335
|
+
}
|
336
|
+
function mapBox(box, mapper) {
|
337
|
+
return {
|
338
|
+
boxId: box.boxId,
|
339
|
+
transactionId: box.transactionId,
|
340
|
+
value: mapper(box.value),
|
341
|
+
ergoTree: box.ergoTree,
|
342
|
+
assets: box.assets.map((t) => ({ tokenId: t.tokenId, amount: mapper(t.amount) })),
|
343
|
+
creationHeight: box.creationHeight,
|
344
|
+
additionalRegisters: box.additionalRegisters,
|
345
|
+
index: box.index
|
346
|
+
};
|
347
|
+
}
|
348
|
+
function mapUnconfirmedTransaction(tx, mapper) {
|
349
|
+
return {
|
350
|
+
transactionId: tx.transactionId,
|
351
|
+
timestamp: Number(tx.timestamp),
|
352
|
+
inputs: tx.inputs.map((i) => ({
|
353
|
+
spendingProof: {
|
354
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
355
|
+
extension: i.extension,
|
356
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
357
|
+
proofBytes: i.proofBytes
|
358
|
+
},
|
359
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
360
|
+
...mapBox(i.box, mapper)
|
205
361
|
})),
|
206
|
-
|
207
|
-
|
362
|
+
dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
|
363
|
+
outputs: tx.outputs.map((b) => mapBox(b, mapper)),
|
364
|
+
confirmed: false
|
365
|
+
};
|
366
|
+
}
|
367
|
+
function mapConfirmedTransaction(tx, mapper) {
|
368
|
+
return {
|
369
|
+
transactionId: tx.transactionId,
|
370
|
+
timestamp: Number(tx.timestamp),
|
371
|
+
inputs: tx.inputs.map((i) => ({
|
372
|
+
spendingProof: {
|
373
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
374
|
+
extension: i.extension,
|
375
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
376
|
+
proofBytes: i.proofBytes
|
377
|
+
},
|
378
|
+
// biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
|
379
|
+
...mapBox(i.box, mapper)
|
380
|
+
})),
|
381
|
+
dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
|
382
|
+
outputs: tx.outputs.map((b) => mapBox(b, mapper)),
|
383
|
+
height: tx.inclusionHeight,
|
384
|
+
headerId: tx.headerId,
|
385
|
+
index: tx.index,
|
386
|
+
confirmed: true
|
387
|
+
};
|
208
388
|
}
|
209
389
|
|
210
390
|
export { ErgoGraphQLProvider };
|
211
|
-
//# sourceMappingURL=
|
391
|
+
//# sourceMappingURL=index.mjs.map
|
212
392
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.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":";AAMA;AAAA,EAGE,kBAAAA;AAAA,EAEA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,QAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAAmB;;;ACpB5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,IAAM,gBAAgB;AACf,IAAM,kBAA2B;AAAA,EACtC,gBAAgB;AAAA,EAChB,QAAQ;AACV;AAqEO,SAAS,mBAId,OACA,SACyC;AACzC,SAAO,OAAO,cAA+C;AAC3D,UAAM,WAAW,OAAO,QAAQ,WAAW,OAAO,QAAQ,KAAK;AAAA,MAC7D,QAAQ;AAAA,MACR,SAAS,eAAe,QAAQ,SAAS,eAAe;AAAA,MACxD,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ,UAAU,MAAM,UAAU;AAAA,QACvC,eAAe,UAAU,KAAK;AAAA,QAC9B;AAAA,QACA,WAAW,YAAY,eAAe,SAAS,IAAI;AAAA,MACrD,CAAkB;AAAA,IACpB,CAAC;AAED,UAAM,UAAU,MAAM,SAAS,KAAK;AACpC,UAAM,cAAc,QAAQ,UAAU,MAAM;AAAA,MAC1C;AAAA,IACF;AAEA,QACE,QAAQ,2BACR,KAAK,WAAW,MAAM,KACtB,QAAQ,WAAW,IAAI,GACvB;AACA,YAAM,IAAI,wBAAwB,WAAW,OAAO,CAAC,EAAE,SAAS;AAAA,QAC9D,OAAO,WAAW;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AACF;AAMO,SAAS,UAAU,OAAmC;AAC3D,SAAO,cAAc,KAAK,KAAK,GAAG,GAAG,CAAC;AACxC;AAEO,SAAS,eAAe,KAA4C;AACzE,SACE,OAAO,QAAQ,YAAa,IAA8B,QAAQ;AAEtE;;;ACnIA,IAAM,IAAI;AAAA,EACR;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,mBAAmB,GAAG,EAAE,CAAC,CAAC,0BAA0B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AACzE,IAAM,qBAAqB,GAAG,EAAE,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AACvE,IAAM,kBAAkB,GAAG,EAAE,CAAC,CAAC,0BAA0B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,sBAAsB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC7G,IAAM,gBACX;AACK,IAAM,oBACX;AACK,IAAM,mBACX;;;AF2DF,IAAM,YAAY;AAEX,IAAM,sBAAN,MAAmE;AAAA,EACxE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIA,YAAY,UAAoD;AAC9D,SAAK,WAAW;AAAA,MACd,GAAI,eAAe,QAAQ,IAAI,WAAW,EAAE,KAAK,SAAS;AAAA,MAC1D,yBAAyB;AAAA,IAC3B;AAEA,SAAK,gBAAgB,KAAK,gBAGxB,gBAAgB;AAElB,SAAK,kBAAkB,KAAK,gBAG1B,kBAAkB;AAEpB,SAAK,eAAe,KAAK,gBAGvB,eAAe;AAEjB,SAAK,cAAc,KAAK,gBAGtB,aAAa;AAEf,SAAK,WAAW,KAAK,gBAGnB,iBAAiB;AAEnB,SAAK,UAAU,KAAK,gBAGlB,gBAAgB;AAAA,EACpB;AAAA,EAEA,YAAY,MAAsB,UAAmB,YAAqB;AACxE,WAAO,YAAY,aACf,KAAK,aAAa,IAAI,IACtB,aACE,KAAK,gBAAgB,IAAI,IACzB,KAAK,cAAc,IAAI;AAAA,EAC/B;AAAA,EAEA,OAAO,YACL,OACoC;AACpC,QAAID,SAAQ,MAAM,KAAK,GAAG;AACxB,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,UAAM,gBAAgB,CAAC,QAAa,CAAC,IAAI;AACzC,UAAM,iBAAiB,oBAAI,IAAY;AACvC,UAAM,EAAE,OAAO,KAAK,IAAI;AACxB,UAAM,OAAO,qBAAqB,KAAK;AAEvC,QAAI,YAAY,SAAS;AACzB,QAAI,WAAW,SAAS;AACxB,UAAM,iBAAiB;AAEvB,OAAG;AACD,YAAM,WAAW,MAAM,KAAK,YAAY,MAAM,WAAW,QAAQ;AAEjE,YAAM,EAAE,KAAK,IAAI;AACjB,UAAI,QAA4B,CAAC;AAEjC,UAAI,aAAa,aAAa,IAAI,GAAG;AACnC,YAAIC,MAAK,KAAK,KAAK,GAAG;AACpB,gBAAM,kBACJ,iBAAiB,KAAK,MAAM,OAAO,aAAa,IAAI,KAAK,OACzD,IAAI,YAAY,IAAI,CAAC;AAEvB,kBAAQ,MAAM,OAAO,cAAc;AAAA,QACrC;AAEA,oBAAY,KAAK,MAAM,WAAW;AAAA,MACpC;AAEA,UAAI,kBAAkB,WAAW,IAAI,GAAG;AACtC,YAAIA,MAAK,KAAK,QAAQ,KAAK,GAAG;AAC5B,gBAAM,eAAe,KAAK,QAAQ,MAC/B,OAAO,aAAa,EACpB,IAAI,YAAY,KAAK,CAAC;AACzB,kBAAQ,MAAM,OAAO,YAAY;AAAA,QACnC;AAEA,mBAAW,KAAK,QAAQ,MAAM,WAAW;AAAA,MAC3C;AAEA,UAAIA,MAAK,KAAK,GAAG;AAGf,YAAI,MAAM,KAAK,CAAC,QAAQ,eAAe,IAAI,IAAI,KAAK,CAAC,GAAG;AACtD,kBAAQ,MAAM,OAAO,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,KAAK,CAAC;AAAA,QAC1D;AAEA,YAAIA,MAAK,KAAK,GAAG;AACf,kBAAQ,OAAO,OAAO,CAAC,QAAQ,IAAI,KAAK;AACxC,qBAAW,OAAO,MAAO,gBAAe,IAAI,IAAI,KAAK;AACrD,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,UAAI,aAAa,SAAU,MAAK,QAAQ;AAAA,IAC1C,SAAS,aAAa;AAAA,EACxB;AAAA,EAEA,MAAM,SAAS,OAAqD;AAClE,QAAI,QAA4B,CAAC;AACjC,qBAAiB,SAAS,KAAK,YAAY,KAAK,GAAG;AACjD,cAAQ,MAAM,OAAO,KAAK;AAAA,IAC5B;AAEA,WAAO,QAAQ,OAAO,CAAC,QAAQ,IAAI,cAAc;AAAA,EACnD;AAAA,EAEA,MAAM,WAAW,OAA4C;AAC3D,UAAM,WAAW,MAAM,KAAK,YAAY,KAAK;AAE7C,WACE,SAAS,MAAM,aAAa,IAAI,CAAC,YAAY;AAAA,MAC3C,GAAG;AAAA,MACH,IAAI,OAAO;AAAA,MACX,WAAW,OAAO,OAAO,SAAS;AAAA,MAClC,OAAO,OAAO,OAAO,KAAK;AAAA,MAC1B,OAAO,OAAO,MAAM,KAAK,EAAE;AAAA,IAC7B,EAAE,KAAK,CAAC;AAAA,EAEZ;AAAA,EAEA,gBACE,OACA,SACgD;AAChD,UAAM,MAAMF,gBAAe,SAAS,KAAK,QAAQ;AACjD,QAAI,0BAA0B;AAE9B,WAAO,mBAAmB,OAAO,GAAG;AAAA,EACtC;AAAA,EAEA,MAAM,iBACJ,mBACsC;AACtC,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,SAAS,EAAE,kBAAkB,CAAC;AAE1D,aAAO,EAAE,SAAS,MAAM,eAAe,SAAS,KAAK,iBAAiB;AAAA,IACxE,SAAS,GAAG;AACV,aAAO,EAAE,SAAS,OAAO,SAAU,EAAY,QAAQ;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAM,kBACJ,mBACsC;AACtC,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,EAAE,kBAAkB,CAAC;AAEzD,aAAO,EAAE,SAAS,MAAM,eAAe,SAAS,KAAK,kBAAkB;AAAA,IACzE,SAAS,GAAG;AACV,aAAO,EAAE,SAAS,OAAO,SAAU,EAAY,QAAQ;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,oBAAyD;AACvD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,OAAwB;AACpD,QAAM,OAAO;AAAA,IACX,OAAO;AAAA,IACP,QAAQ,MAAM,MAAM,QAAQ,MAAM,KAAK;AAAA,IACvC,WAAW,MAAM,MAAM,WAAW,MAAM,QAAQ;AAAA,IAChD,sBAAsB,MAAM;AAAA,IAC5B,SAAS,MAAM;AAAA,IACf,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,QAAM,YAAY,MAAM,MAAM,WAAW,MAAM,OAAO;AACtD,MAAIE,MAAK,SAAS,GAAG;AACnB,UAAM,QAAQ,UAAU;AAAA,MAAI,CAAC,YAC3B,OAAO,YAAY,WACf,YAAY,WAAW,OAAO,EAAE,WAChC,QAAQ;AAAA,IACd;AAEA,SAAK,YAAY;AAAA,MACfA,MAAK,KAAK,SAAS,IAAI,KAAK,UAAU,OAAO,KAAK,IAAI;AAAA,IACxD;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,MAAS,OAAa,IAAQ;AACrC,MAAID,SAAQ,KAAK,KAAK,YAAY,EAAE,EAAG;AAEvC,QAAM,MAAM,IAAI,IAAO,SAAS,CAAC,CAAC;AAClC,MAAI,CAAC,YAAY,EAAE,EAAG,KAAI,IAAI,EAAE;AAChC,SAAO,MAAM,KAAK,IAAI,OAAO,CAAC;AAChC;AAEA,SAAS,WAAW,MAAiD;AACnE,SAAO,CAAC,CAAE,MAAmC,SAAS;AACxD;AAEA,SAAS,aAAa,MAA+C;AACnE,SAAO,CAAC,CAAE,MAAiC;AAC7C;AAEA,SAAS,YAAY,WAAoB;AACvC,SAAO,CAAC,SAAgC;AAAA,IACtC,GAAG;AAAA,IACH,OAAO,OAAO,IAAI,KAAK;AAAA,IACvB,QAAQ,IAAI,OAAO,IAAI,CAAC,WAAW;AAAA,MACjC,SAAS,MAAM;AAAA,MACf,QAAQ,OAAO,MAAM,MAAM;AAAA,IAC7B,EAAE;AAAA,IACF;AAAA,EACF;AACF","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","isEmpty","ensureDefaults"],"mappings":"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","file":"index.mjs","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"]}
|