@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.
- package/CHANGELOG.md +19 -0
- package/dist/index.d.mts +124 -33
- package/dist/index.d.ts +124 -33
- package/dist/index.js +254 -75
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +254 -75
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/ergo-graphql/ergoGraphQLProvider.ts +296 -93
- package/src/ergo-graphql/queries.ts +21 -9
- package/src/index.ts +1 -1
- package/src/types/blockchainProvider.ts +111 -18
- package/src/utils/_tests.ts +7 -7
- package/src/utils/graphql.test-d.ts +15 -7
- package/src/utils/graphql.ts +54 -40
- package/src/utils/networking.ts +84 -0
- package/src/ergo-graphql/index.ts +0 -1
- package/src/types/index.ts +0 -1
@@ -1,51 +1,66 @@
|
|
1
|
-
import {
|
2
|
-
Box,
|
3
|
-
QueryBoxesArgs
|
1
|
+
import type {
|
2
|
+
Box as GQLBox,
|
3
|
+
QueryBoxesArgs,
|
4
4
|
Header,
|
5
|
-
QueryBlockHeadersArgs
|
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
|
-
|
30
|
-
|
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
|
-
|
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<
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
type
|
67
|
-
type
|
68
|
-
type
|
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<
|
105
|
+
export class ErgoGraphQLProvider<I = bigint> implements IBlockchainProvider<I> {
|
74
106
|
#options: GraphQLThrowableOptions;
|
75
|
-
|
76
|
-
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
|
83
|
-
|
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
|
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.#
|
92
|
-
|
93
|
-
this.#
|
94
|
-
this.#
|
95
|
-
this.#
|
96
|
-
this.#
|
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:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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:
|
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
|
120
|
-
let
|
121
|
-
const isMempoolAware =
|
166
|
+
let inclChain = from !== "mempool";
|
167
|
+
let inclPool = from !== "blockchain";
|
168
|
+
const isMempoolAware = inclPool;
|
122
169
|
|
123
170
|
do {
|
124
|
-
const
|
171
|
+
const { data } = await this.#fetchBoxes(args, inclChain, inclPool);
|
172
|
+
let boxes: ChainProviderBox<I>[] = [];
|
125
173
|
|
126
|
-
|
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(
|
178
|
+
).map((b) => mapConfirmedBox(b, this.#biMapper));
|
134
179
|
|
135
180
|
boxes = boxes.concat(confirmedBoxes);
|
136
181
|
}
|
137
182
|
|
138
|
-
|
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
|
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
|
-
|
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
|
-
|
160
|
-
|
206
|
+
for (const box of boxes) returnedBoxIds.add(box.boxId);
|
161
207
|
yield boxes;
|
162
208
|
}
|
163
209
|
}
|
164
210
|
|
165
|
-
if (
|
166
|
-
} while (
|
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
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
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.#
|
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.#
|
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
|
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"
|
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:
|
263
|
-
return !!(data as
|
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
|
267
|
-
|
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
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
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
|
-
|
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
|
-
|
3
|
-
|
4
|
-
|
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 =
|
8
|
-
export const UNCONF_BOXES_QUERY =
|
9
|
-
export const ALL_BOXES_QUERY =
|
10
|
-
|
11
|
-
export const
|
12
|
-
|
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";
|