@fleet-sdk/blockchain-providers 0.4.1 → 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.
@@ -1,51 +1,66 @@
1
- import {
2
- Box,
3
- QueryBoxesArgs as BoxesArgs,
1
+ import type {
2
+ Box as GQLBox,
3
+ QueryBoxesArgs,
4
4
  Header,
5
- QueryBlockHeadersArgs as HeadersArgs
5
+ QueryBlockHeadersArgs,
6
+ Transaction,
7
+ QueryTransactionsArgs,
8
+ MempoolTransactionsArgs,
9
+ UnconfirmedTransaction,
10
+ UnconfirmedBox as GQLUnconfirmedBox
6
11
  } from "@ergo-graphql/types";
7
12
  import {
8
- Base58String,
9
- BlockHeader,
13
+ type Base58String,
14
+ type BlockHeader,
10
15
  ensureDefaults,
11
- HexString,
16
+ type HexString,
12
17
  isEmpty,
13
18
  isUndefined,
14
19
  NotSupportedError,
15
20
  orderBy,
16
- SignedTransaction,
21
+ type SignedTransaction,
17
22
  some,
18
23
  uniq,
19
24
  uniqBy
20
25
  } from "@fleet-sdk/common";
21
26
  import { ErgoAddress } from "@fleet-sdk/core";
22
- import {
27
+ import type {
23
28
  BoxQuery,
24
29
  BoxWhere,
25
30
  ChainProviderBox,
31
+ ChainProviderConfirmedTransaction,
32
+ ChainProviderUnconfirmedTransaction,
26
33
  HeaderQuery,
27
34
  IBlockchainProvider,
28
35
  TransactionEvaluationResult,
29
- TransactionReductionResult
30
- } from "../types";
36
+ TransactionQuery,
37
+ TransactionReductionResult,
38
+ ConfirmedTransactionWhere,
39
+ UnconfirmedTransactionWhere
40
+ } from "../types/blockchainProvider";
31
41
  import {
32
42
  createGqlOperation,
33
- GraphQLOperation,
34
- GraphQLRequestOptions,
35
- GraphQLSuccessResponse,
36
- GraphQLThrowableOptions,
37
- GraphQLVariables,
43
+ type GraphQLOperation,
44
+ type GraphQLRequestOptions,
45
+ type GraphQLSuccessResponse,
46
+ type GraphQLVariables,
38
47
  isRequestParam
39
48
  } from "../utils";
40
49
  import {
41
50
  ALL_BOXES_QUERY,
42
51
  CHECK_TX_MUTATION,
43
52
  CONF_BOXES_QUERY,
53
+ CONF_TX_QUERY,
44
54
  HEADERS_QUERY,
45
55
  SEND_TX_MUTATION,
46
- UNCONF_BOXES_QUERY
56
+ UNCONF_BOXES_QUERY,
57
+ UNCONF_TX_QUERY
47
58
  } from "./queries";
48
59
 
60
+ type GraphQLThrowableOptions = GraphQLRequestOptions & { throwOnNonNetworkErrors: true };
61
+ type OP<R, V extends GraphQLVariables> = GraphQLOperation<GraphQLSuccessResponse<R>, V>;
62
+ type BiMapper<T> = (value: string) => T;
63
+
49
64
  export type GraphQLBoxWhere = BoxWhere & {
50
65
  /** Base16-encoded BoxIds */
51
66
  boxIds?: HexString[];
@@ -57,94 +72,126 @@ export type GraphQLBoxWhere = BoxWhere & {
57
72
  addresses?: (Base58String | ErgoAddress)[];
58
73
  };
59
74
 
75
+ export type GraphQLConfirmedTransactionWhere = ConfirmedTransactionWhere & {
76
+ transactionIds?: HexString[];
77
+ addresses?: (Base58String | ErgoAddress)[];
78
+ ergoTrees?: HexString[];
79
+ };
80
+
81
+ export type GraphQLUnconfirmedTransactionWhere = UnconfirmedTransactionWhere & {
82
+ transactionIds?: HexString[];
83
+ addresses?: (Base58String | ErgoAddress)[];
84
+ ergoTrees?: HexString[];
85
+ };
86
+
60
87
  export type GraphQLBoxQuery = BoxQuery<GraphQLBoxWhere>;
61
- export type ErgoGraphQLRequestOptions = Omit<GraphQLRequestOptions, "throwOnNonNetworkError">;
62
-
63
- type ConfBoxesResp = { boxes: Box[] };
64
- type UnconfBoxesResp = { mempool: { boxes: Box[] } };
65
- type AllBoxesResp = ConfBoxesResp & UnconfBoxesResp;
66
- type HeadersResp = { blockHeaders: Header[] };
67
- type CheckTxResp = { checkTransaction: string };
68
- type SendTxResp = { submitTransaction: string };
88
+ export type ErgoGraphQLRequestOptions = Omit<
89
+ GraphQLRequestOptions,
90
+ "throwOnNonNetworkError"
91
+ >;
92
+
93
+ type ConfirmedBoxesResponse = { boxes: GQLBox[] };
94
+ type UnconfirmedBoxesResponse = { mempool: { boxes: GQLBox[] } };
95
+ type CombinedBoxesResponse = ConfirmedBoxesResponse & UnconfirmedBoxesResponse;
96
+ type UnconfirmedTxResponse = { mempool: { transactions: UnconfirmedTransaction[] } };
97
+ type ConfirmedTxResponse = { transactions: Transaction[] };
98
+ type BlockHeadersResponse = { blockHeaders: Header[] };
99
+ type CheckTransactionResponse = { checkTransaction: string };
100
+ type TransactionSubmissionResponse = { submitTransaction: string };
69
101
  type SignedTxArgsResp = { signedTransaction: SignedTransaction };
70
102
 
71
103
  const PAGE_SIZE = 50;
72
104
 
73
- export class ErgoGraphQLProvider implements IBlockchainProvider<BoxWhere> {
105
+ export class ErgoGraphQLProvider<I = bigint> implements IBlockchainProvider<I> {
74
106
  #options: GraphQLThrowableOptions;
75
-
76
- #getConfBoxes;
77
- #getUnconfBoxes;
78
- #getAllBoxes;
79
- #getHeaders;
80
- #checkTx;
81
- #sendTx;
82
-
83
- constructor(url: string | URL);
107
+ #biMapper: BiMapper<I>;
108
+
109
+ #getConfirmedBoxes: OP<ConfirmedBoxesResponse, QueryBoxesArgs>;
110
+ #getUnconfirmedBoxes: OP<UnconfirmedBoxesResponse, QueryBoxesArgs>;
111
+ #getAllBoxes: OP<CombinedBoxesResponse, QueryBoxesArgs>;
112
+ #getConfirmedTransactions: OP<ConfirmedTxResponse, QueryTransactionsArgs>;
113
+ #getUnconfirmedTransactions: OP<UnconfirmedTxResponse, MempoolTransactionsArgs>;
114
+ #checkTransaction: OP<CheckTransactionResponse, SignedTxArgsResp>;
115
+ #sendTransaction: OP<TransactionSubmissionResponse, SignedTxArgsResp>;
116
+ #getHeaders!: OP<BlockHeadersResponse, QueryBlockHeadersArgs>;
117
+
118
+ constructor(url: string);
84
119
  constructor(url: ErgoGraphQLRequestOptions);
85
- constructor(optOrUrl: ErgoGraphQLRequestOptions | string | URL) {
120
+ constructor(optOrUrl: ErgoGraphQLRequestOptions | string) {
86
121
  this.#options = {
87
122
  ...(isRequestParam(optOrUrl) ? optOrUrl : { url: optOrUrl }),
88
123
  throwOnNonNetworkErrors: true
89
124
  };
90
125
 
91
- this.#getConfBoxes = this.createOperation<ConfBoxesResp, BoxesArgs>(CONF_BOXES_QUERY);
92
- this.#getUnconfBoxes = this.createOperation<UnconfBoxesResp, BoxesArgs>(UNCONF_BOXES_QUERY);
93
- this.#getAllBoxes = this.createOperation<AllBoxesResp, BoxesArgs>(ALL_BOXES_QUERY);
94
- this.#getHeaders = this.createOperation<HeadersResp, HeadersArgs>(HEADERS_QUERY);
95
- this.#checkTx = this.createOperation<CheckTxResp, SignedTxArgsResp>(CHECK_TX_MUTATION);
96
- this.#sendTx = this.createOperation<SendTxResp, SignedTxArgsResp>(SEND_TX_MUTATION);
126
+ this.#biMapper = (value) => BigInt(value) as I;
127
+
128
+ this.#getConfirmedBoxes = this.createOperation(CONF_BOXES_QUERY);
129
+ this.#getUnconfirmedBoxes = this.createOperation(UNCONF_BOXES_QUERY);
130
+ this.#getAllBoxes = this.createOperation(ALL_BOXES_QUERY);
131
+ this.#getConfirmedTransactions = this.createOperation(CONF_TX_QUERY);
132
+ this.#getUnconfirmedTransactions = this.createOperation(UNCONF_TX_QUERY);
133
+ this.#checkTransaction = this.createOperation(CHECK_TX_MUTATION);
134
+ this.#sendTransaction = this.createOperation(SEND_TX_MUTATION);
135
+ this.#getHeaders = this.createOperation(HEADERS_QUERY);
97
136
  }
98
137
 
99
- #fetchBoxes(args: BoxesArgs, inclConf: boolean, inclUnconf: boolean) {
100
- if (inclConf && inclUnconf) {
101
- return this.#getAllBoxes(args);
102
- } else if (inclUnconf) {
103
- return this.#getUnconfBoxes(args);
104
- } else {
105
- return this.#getConfBoxes(args);
106
- }
138
+ #fetchBoxes(args: QueryBoxesArgs, inclConf: boolean, inclUnconf: boolean) {
139
+ return inclConf && inclUnconf
140
+ ? this.#getAllBoxes(args, this.#options.url)
141
+ : inclUnconf
142
+ ? this.#getUnconfirmedBoxes(args, this.#options.url)
143
+ : this.#getConfirmedBoxes(args, this.#options.url);
144
+ }
145
+
146
+ setUrl(url: string): ErgoGraphQLProvider<I> {
147
+ this.#options.url = url;
148
+ return this;
149
+ }
150
+
151
+ setBigIntMapper<M>(mapper: BiMapper<M>): ErgoGraphQLProvider<M> {
152
+ this.#biMapper = mapper as unknown as BiMapper<I>;
153
+ return this as unknown as ErgoGraphQLProvider<M>;
107
154
  }
108
155
 
109
- async *streamBoxes(query: GraphQLBoxQuery): AsyncGenerator<ChainProviderBox[]> {
156
+ async *streamBoxes(query: GraphQLBoxQuery): AsyncGenerator<ChainProviderBox<I>[]> {
110
157
  if (isEmpty(query.where)) {
111
158
  throw new Error("Cannot fetch unspent boxes without a where clause.");
112
159
  }
113
160
 
114
- const notBeingSpent = (box: Box) => !box.beingSpent;
161
+ const notBeingSpent = (box: GQLBox) => !box.beingSpent;
115
162
  const returnedBoxIds = new Set<string>();
116
163
  const { where, from } = query;
117
164
  const args = buildGqlBoxQueryArgs(where);
118
165
 
119
- let fetchFromChain = from !== "mempool";
120
- let fetchFromMempool = from !== "blockchain";
121
- const isMempoolAware = fetchFromMempool;
166
+ let inclChain = from !== "mempool";
167
+ let inclPool = from !== "blockchain";
168
+ const isMempoolAware = inclPool;
122
169
 
123
170
  do {
124
- const response = await this.#fetchBoxes(args, fetchFromChain, fetchFromMempool);
171
+ const { data } = await this.#fetchBoxes(args, inclChain, inclPool);
172
+ let boxes: ChainProviderBox<I>[] = [];
125
173
 
126
- const { data } = response;
127
- let boxes: ChainProviderBox[] = [];
128
-
129
- if (fetchFromChain && hasConfirmed(data)) {
174
+ if (inclChain && hasConfirmed(data)) {
130
175
  if (some(data.boxes)) {
131
176
  const confirmedBoxes = (
132
177
  isMempoolAware ? data.boxes.filter(notBeingSpent) : data.boxes
133
- ).map(asConfirmed(true));
178
+ ).map((b) => mapConfirmedBox(b, this.#biMapper));
134
179
 
135
180
  boxes = boxes.concat(confirmedBoxes);
136
181
  }
137
182
 
138
- fetchFromChain = data.boxes.length === PAGE_SIZE;
183
+ inclChain = data.boxes.length === PAGE_SIZE;
139
184
  }
140
185
 
141
186
  if (isMempoolAware && hasMempool(data)) {
142
187
  if (some(data.mempool.boxes)) {
143
- const mempoolBoxes = data.mempool.boxes.filter(notBeingSpent).map(asConfirmed(false));
188
+ const mempoolBoxes = data.mempool.boxes
189
+ .filter(notBeingSpent)
190
+ .map((b) => mapUnconfirmedBox(b, this.#biMapper));
144
191
  boxes = boxes.concat(mempoolBoxes);
145
192
  }
146
193
 
147
- fetchFromMempool = data.mempool.boxes.length === PAGE_SIZE;
194
+ inclPool = data.mempool.boxes.length === PAGE_SIZE;
148
195
  }
149
196
 
150
197
  if (some(boxes)) {
@@ -156,27 +203,83 @@ export class ErgoGraphQLProvider implements IBlockchainProvider<BoxWhere> {
156
203
 
157
204
  if (some(boxes)) {
158
205
  boxes = uniqBy(boxes, (box) => box.boxId);
159
- boxes.forEach((box) => returnedBoxIds.add(box.boxId));
160
-
206
+ for (const box of boxes) returnedBoxIds.add(box.boxId);
161
207
  yield boxes;
162
208
  }
163
209
  }
164
210
 
165
- if (fetchFromChain || fetchFromMempool) args.skip += PAGE_SIZE;
166
- } while (fetchFromChain || fetchFromMempool);
211
+ if (inclChain || inclPool) args.skip += PAGE_SIZE;
212
+ } while (inclChain || inclPool);
213
+ }
214
+
215
+ async getBoxes(query: GraphQLBoxQuery): Promise<ChainProviderBox<I>[]> {
216
+ const boxes: ChainProviderBox<I>[][] = [];
217
+ for await (const chunk of this.streamBoxes(query)) boxes.push(chunk);
218
+ return orderBy(boxes.flat(), (box) => box.creationHeight);
219
+ }
220
+
221
+ async *streamUnconfirmedTransactions(
222
+ query: TransactionQuery<GraphQLUnconfirmedTransactionWhere>
223
+ ): AsyncIterable<ChainProviderUnconfirmedTransaction<I>[]> {
224
+ const args = buildGqlUnconfirmedTxQueryArgs(query.where);
225
+
226
+ let keepFetching = true;
227
+ while (keepFetching) {
228
+ const response = await this.#getUnconfirmedTransactions(args);
229
+ if (some(response.data?.mempool?.transactions)) {
230
+ yield response.data.mempool.transactions.map((t) =>
231
+ mapUnconfirmedTransaction(t, this.#biMapper)
232
+ );
233
+ }
234
+
235
+ keepFetching = response.data?.mempool?.transactions?.length === PAGE_SIZE;
236
+ if (keepFetching) args.skip += PAGE_SIZE;
237
+ }
238
+ }
239
+
240
+ async getUnconfirmedTransactions(
241
+ query: TransactionQuery<GraphQLUnconfirmedTransactionWhere>
242
+ ): Promise<ChainProviderUnconfirmedTransaction<I>[]> {
243
+ const transactions: ChainProviderUnconfirmedTransaction<I>[][] = [];
244
+ for await (const chunk of this.streamUnconfirmedTransactions(query)) {
245
+ transactions.push(chunk);
246
+ }
247
+
248
+ return transactions.flat();
249
+ }
250
+
251
+ async *streamConfirmedTransactions(
252
+ query: TransactionQuery<GraphQLConfirmedTransactionWhere>
253
+ ): AsyncIterable<ChainProviderConfirmedTransaction<I>[]> {
254
+ const args = buildGqlConfirmedTxQueryArgs(query.where);
255
+
256
+ let keepFetching = true;
257
+ while (keepFetching) {
258
+ const response = await this.#getConfirmedTransactions(args);
259
+ if (some(response.data?.transactions)) {
260
+ yield response.data.transactions.map((t) =>
261
+ mapConfirmedTransaction(t, this.#biMapper)
262
+ );
263
+ }
264
+
265
+ keepFetching = response.data?.transactions?.length === PAGE_SIZE;
266
+ if (keepFetching) args.skip += PAGE_SIZE;
267
+ }
167
268
  }
168
269
 
169
- async getBoxes(query: GraphQLBoxQuery): Promise<ChainProviderBox[]> {
170
- let boxes: ChainProviderBox[] = [];
171
- for await (const chunk of this.streamBoxes(query)) {
172
- boxes = boxes.concat(chunk);
270
+ async getConfirmedTransactions(
271
+ query: TransactionQuery<GraphQLConfirmedTransactionWhere>
272
+ ): Promise<ChainProviderConfirmedTransaction<I>[]> {
273
+ const transactions: ChainProviderConfirmedTransaction<I>[][] = [];
274
+ for await (const chunk of this.streamConfirmedTransactions(query)) {
275
+ transactions.push(chunk);
173
276
  }
174
277
 
175
- return orderBy(boxes, (box) => box.creationHeight);
278
+ return transactions.flat();
176
279
  }
177
280
 
178
281
  async getHeaders(query: HeaderQuery): Promise<BlockHeader[]> {
179
- const response = await this.#getHeaders(query);
282
+ const response = await this.#getHeaders(query, this.#options.url);
180
283
 
181
284
  return (
182
285
  response.data?.blockHeaders.map((header) => ({
@@ -203,8 +306,10 @@ export class ErgoGraphQLProvider implements IBlockchainProvider<BoxWhere> {
203
306
  signedTransaction: SignedTransaction
204
307
  ): Promise<TransactionEvaluationResult> {
205
308
  try {
206
- const response = await this.#checkTx({ signedTransaction });
207
-
309
+ const response = await this.#checkTransaction(
310
+ { signedTransaction },
311
+ this.#options.url
312
+ );
208
313
  return { success: true, transactionId: response.data.checkTransaction };
209
314
  } catch (e) {
210
315
  return { success: false, message: (e as Error).message };
@@ -215,8 +320,10 @@ export class ErgoGraphQLProvider implements IBlockchainProvider<BoxWhere> {
215
320
  signedTransaction: SignedTransaction
216
321
  ): Promise<TransactionEvaluationResult> {
217
322
  try {
218
- const response = await this.#sendTx({ signedTransaction });
219
-
323
+ const response = await this.#sendTransaction(
324
+ { signedTransaction },
325
+ this.#options.url
326
+ );
220
327
  return { success: true, transactionId: response.data.submitTransaction };
221
328
  } catch (e) {
222
329
  return { success: false, message: (e as Error).message };
@@ -237,12 +344,14 @@ function buildGqlBoxQueryArgs(where: GraphQLBoxWhere) {
237
344
  tokenId: where.tokenId,
238
345
  skip: 0,
239
346
  take: PAGE_SIZE
240
- } satisfies BoxesArgs;
347
+ } satisfies QueryBoxesArgs;
241
348
 
242
349
  const addresses = merge(where.addresses, where.address);
243
350
  if (some(addresses)) {
244
351
  const trees = addresses.map((address) =>
245
- typeof address === "string" ? ErgoAddress.fromBase58(address).ergoTree : address.ergoTree
352
+ typeof address === "string"
353
+ ? ErgoAddress.decode(address).ergoTree
354
+ : address.ergoTree
246
355
  );
247
356
 
248
357
  args.ergoTrees = uniq(some(args.ergoTrees) ? args.ergoTrees.concat(trees) : trees);
@@ -251,6 +360,35 @@ function buildGqlBoxQueryArgs(where: GraphQLBoxWhere) {
251
360
  return args;
252
361
  }
253
362
 
363
+ function buildGqlUnconfirmedTxQueryArgs(where: GraphQLConfirmedTransactionWhere) {
364
+ const addresses = uniq(
365
+ [
366
+ merge(where.addresses, where.address)?.map((address): string =>
367
+ typeof address === "string" ? address : address.encode()
368
+ ) ?? [],
369
+ merge(where.ergoTrees, where.ergoTree)?.map((tree) =>
370
+ ErgoAddress.fromErgoTree(tree).encode()
371
+ ) ?? []
372
+ ].flat()
373
+ );
374
+
375
+ return {
376
+ addresses: addresses.length ? addresses : undefined,
377
+ transactionIds: merge(where.transactionIds, where.transactionId),
378
+ skip: 0,
379
+ take: PAGE_SIZE
380
+ };
381
+ }
382
+
383
+ function buildGqlConfirmedTxQueryArgs(where: GraphQLConfirmedTransactionWhere) {
384
+ return {
385
+ ...buildGqlUnconfirmedTxQueryArgs(where),
386
+ headerId: where.headerId,
387
+ minHeight: where.minHeight,
388
+ onlyRelevantOutputs: where.onlyRelevantOutputs
389
+ };
390
+ }
391
+
254
392
  function merge<T>(array?: T[], el?: T) {
255
393
  if (isEmpty(array) && isUndefined(el)) return;
256
394
 
@@ -259,22 +397,87 @@ function merge<T>(array?: T[], el?: T) {
259
397
  return Array.from(set.values());
260
398
  }
261
399
 
262
- function hasMempool(data: AllBoxesResp | ConfBoxesResp | UnconfBoxesResp): data is UnconfBoxesResp {
263
- return !!(data as UnconfBoxesResp)?.mempool?.boxes;
400
+ function hasMempool(data: unknown): data is UnconfirmedBoxesResponse {
401
+ return !!(data as UnconfirmedBoxesResponse)?.mempool?.boxes;
402
+ }
403
+
404
+ function hasConfirmed(data: unknown): data is ConfirmedBoxesResponse {
405
+ return !!(data as ConfirmedBoxesResponse)?.boxes;
264
406
  }
265
407
 
266
- function hasConfirmed(data: AllBoxesResp | ConfBoxesResp | UnconfBoxesResp): data is ConfBoxesResp {
267
- return !!(data as ConfBoxesResp)?.boxes;
408
+ function mapConfirmedBox<T>(box: GQLBox, mapper: BiMapper<T>): ChainProviderBox<T> {
409
+ const mapped = mapBox(box, mapper) as ChainProviderBox<T>;
410
+ mapped.confirmed = true;
411
+ return mapped;
412
+ }
413
+
414
+ function mapUnconfirmedBox<T>(box: GQLBox, mapper: BiMapper<T>): ChainProviderBox<T> {
415
+ const mapped = mapBox(box, mapper) as ChainProviderBox<T>;
416
+ mapped.confirmed = false;
417
+ return mapped;
418
+ }
419
+
420
+ function mapBox<T>(
421
+ box: GQLBox | GQLUnconfirmedBox,
422
+ mapper: BiMapper<T>
423
+ ): Omit<ChainProviderBox<T>, "confirmed"> {
424
+ return {
425
+ boxId: box.boxId,
426
+ transactionId: box.transactionId,
427
+ value: mapper(box.value),
428
+ ergoTree: box.ergoTree,
429
+ assets: box.assets.map((t) => ({ tokenId: t.tokenId, amount: mapper(t.amount) })),
430
+ creationHeight: box.creationHeight,
431
+ additionalRegisters: box.additionalRegisters,
432
+ index: box.index
433
+ };
434
+ }
435
+
436
+ function mapUnconfirmedTransaction<T>(
437
+ tx: UnconfirmedTransaction,
438
+ mapper: BiMapper<T>
439
+ ): ChainProviderUnconfirmedTransaction<T> {
440
+ return {
441
+ transactionId: tx.transactionId,
442
+ timestamp: Number(tx.timestamp),
443
+ inputs: tx.inputs.map((i) => ({
444
+ spendingProof: {
445
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
446
+ extension: i.extension!,
447
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
448
+ proofBytes: i.proofBytes!
449
+ },
450
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
451
+ ...mapBox(i.box!, mapper)
452
+ })),
453
+ dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
454
+ outputs: tx.outputs.map((b) => mapBox(b, mapper)),
455
+ confirmed: false
456
+ };
268
457
  }
269
458
 
270
- function asConfirmed(confirmed: boolean) {
271
- return (box: Box): ChainProviderBox => ({
272
- ...box,
273
- value: BigInt(box.value),
274
- assets: box.assets.map((asset) => ({
275
- tokenId: asset.tokenId,
276
- amount: BigInt(asset.amount)
459
+ function mapConfirmedTransaction<T>(
460
+ tx: Transaction,
461
+ mapper: BiMapper<T>
462
+ ): ChainProviderConfirmedTransaction<T> {
463
+ return {
464
+ transactionId: tx.transactionId,
465
+ timestamp: Number(tx.timestamp),
466
+ inputs: tx.inputs.map((i) => ({
467
+ spendingProof: {
468
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
469
+ extension: i.extension!,
470
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
471
+ proofBytes: i.proofBytes!
472
+ },
473
+ // biome-ignore lint/style/noNonNullAssertion: bad type declarations at '@ergo-graphql/type'
474
+ ...mapBox(i.box!, mapper)
277
475
  })),
278
- confirmed
279
- });
476
+ dataInputs: tx.dataInputs.map((di) => ({ boxId: di.boxId })),
477
+ outputs: tx.outputs.map((b) => mapBox(b, mapper)),
478
+ height: tx.inclusionHeight,
479
+ headerId: tx.headerId,
480
+ index: tx.index,
481
+ confirmed: true
482
+ };
280
483
  }
@@ -1,12 +1,24 @@
1
1
  const B = [
2
- `query boxes($spent: Boolean! $boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int)`,
3
- `boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take`,
4
- `boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters beingSpent`
2
+ "$boxIds: [String!] $ergoTrees: [String!] $ergoTreeTemplateHash: String $tokenId: String $skip: Int $take: Int",
3
+ "boxIds: $boxIds ergoTrees: $ergoTrees ergoTreeTemplateHash: $ergoTreeTemplateHash tokenId: $tokenId skip: $skip take: $take",
4
+ "boxId transactionId index value creationHeight ergoTree assets { tokenId amount } additionalRegisters"
5
5
  ];
6
6
 
7
- export const CONF_BOXES_QUERY = `${B[0]} { boxes(spent: $spent ${B[1]}) { ${B[2]} } }`;
8
- export const UNCONF_BOXES_QUERY = `${B[0]} { mempool { boxes(${B[1]}) { ${B[2]} } } }`;
9
- export const ALL_BOXES_QUERY = `${B[0]} { boxes(spent: $spent ${B[1]}) { ${B[2]} } mempool { boxes(${B[1]}) { ${B[2]} } } }`;
10
- export const HEADERS_QUERY = `query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }`;
11
- export const CHECK_TX_MUTATION = `mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }`;
12
- export const SEND_TX_MUTATION = `mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }`;
7
+ export const CONF_BOXES_QUERY = `query boxes($spent: Boolean! ${B[0]}) { boxes(spent: $spent ${B[1]}) { ${B[2]} beingSpent } }`;
8
+ export const UNCONF_BOXES_QUERY = `query boxes(${B[0]}) { mempool { boxes(${B[1]}) { ${B[2]} beingSpent } } }`;
9
+ export 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 } } }`;
10
+
11
+ export const HEADERS_QUERY =
12
+ "query blockHeaders($take: Int) { blockHeaders(take: $take) {headerId timestamp version adProofsRoot stateRoot transactionsRoot nBits extensionHash powSolutions height difficulty parentId votes } }";
13
+ export const CHECK_TX_MUTATION =
14
+ "mutation checkTransaction($signedTransaction: SignedTransaction!) { checkTransaction(signedTransaction: $signedTransaction) }";
15
+ export const SEND_TX_MUTATION =
16
+ "mutation submitTransaction($signedTransaction: SignedTransaction!) { submitTransaction(signedTransaction: $signedTransaction) }";
17
+
18
+ const T = [
19
+ "$addresses: [String!], $transactionIds: [String!], $skip: Int, $take: Int",
20
+ "addresses: $addresses, transactionIds: $transactionIds, skip: $skip, take: $take",
21
+ `transactionId timestamp inputs { proofBytes extension index box { ${B[2]} } } dataInputs { boxId }`
22
+ ];
23
+ export const CONF_TX_QUERY = `query confirmedTransactions(${T[0]} $relevantOnly: Boolean) { transactions(${T[1]}) { ${T[2]} outputs(relevantOnly: $relevantOnly) { ${B[2]} } inclusionHeight headerId index } }`;
24
+ export const UNCONF_TX_QUERY = `query unconfirmedTransactions(${T[0]}) { mempool { transactions(${T[1]}) { ${T[2]} outputs { ${B[2]} } } } }`;
package/src/index.ts CHANGED
@@ -1 +1 @@
1
- export * from "./ergo-graphql";
1
+ export * from "./ergo-graphql/ergoGraphQLProvider";