@subsquid/fuel-stream 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/archive/data-schema.d.ts +332 -0
- package/lib/archive/data-schema.d.ts.map +1 -0
- package/lib/archive/data-schema.js +293 -0
- package/lib/archive/data-schema.js.map +1 -0
- package/lib/archive/source.d.ts +14 -0
- package/lib/archive/source.d.ts.map +1 -0
- package/lib/archive/source.js +82 -0
- package/lib/archive/source.js.map +1 -0
- package/lib/data/data-partial.d.ts +20 -0
- package/lib/data/data-partial.d.ts.map +1 -0
- package/lib/data/data-partial.js +3 -0
- package/lib/data/data-partial.js.map +1 -0
- package/lib/data/data-request.d.ts +35 -0
- package/lib/data/data-request.d.ts.map +1 -0
- package/lib/data/data-request.js +3 -0
- package/lib/data/data-request.js.map +1 -0
- package/lib/data/model.d.ts +45 -0
- package/lib/data/model.d.ts.map +1 -0
- package/lib/data/model.js +19 -0
- package/lib/data/model.js.map +1 -0
- package/lib/data/util.d.ts +20 -0
- package/lib/data/util.d.ts.map +1 -0
- package/lib/data/util.js +3 -0
- package/lib/data/util.js.map +1 -0
- package/lib/fields.d.ts +6 -0
- package/lib/fields.d.ts.map +1 -0
- package/lib/fields.js +32 -0
- package/lib/fields.js.map +1 -0
- package/lib/filter.d.ts +6 -0
- package/lib/filter.d.ts.map +1 -0
- package/lib/filter.js +172 -0
- package/lib/filter.js.map +1 -0
- package/lib/graphql.d.ts +14 -0
- package/lib/graphql.d.ts.map +1 -0
- package/lib/graphql.js +40 -0
- package/lib/graphql.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +19 -0
- package/lib/index.js.map +1 -0
- package/lib/source.d.ts +118 -0
- package/lib/source.d.ts.map +1 -0
- package/lib/source.js +296 -0
- package/lib/source.js.map +1 -0
- package/package.json +34 -0
- package/src/archive/data-schema.ts +320 -0
- package/src/archive/source.ts +88 -0
- package/src/data/data-partial.ts +25 -0
- package/src/data/data-request.ts +44 -0
- package/src/data/model.ts +114 -0
- package/src/data/util.ts +42 -0
- package/src/fields.ts +35 -0
- package/src/filter.ts +229 -0
- package/src/graphql.ts +51 -0
- package/src/index.ts +2 -0
- package/src/source.ts +416 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import {weakMemo} from '@subsquid/util-internal'
|
|
2
|
+
import {
|
|
3
|
+
array,
|
|
4
|
+
BIG_NAT,
|
|
5
|
+
BOOLEAN,
|
|
6
|
+
BYTES,
|
|
7
|
+
NAT,
|
|
8
|
+
object,
|
|
9
|
+
option,
|
|
10
|
+
STRING,
|
|
11
|
+
taggedUnion,
|
|
12
|
+
oneOf,
|
|
13
|
+
constant
|
|
14
|
+
} from '@subsquid/util-internal-validation'
|
|
15
|
+
import {FieldSelection} from '../data/model'
|
|
16
|
+
import {Selector} from '../data/util'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export const getDataSchema = weakMemo((fields: FieldSelection) => {
|
|
20
|
+
let BlockHeader = object({
|
|
21
|
+
number: NAT,
|
|
22
|
+
hash: BYTES,
|
|
23
|
+
...project(fields.block, {
|
|
24
|
+
daHeight: BIG_NAT,
|
|
25
|
+
transactionsRoot: BYTES,
|
|
26
|
+
transactionsCount: BIG_NAT,
|
|
27
|
+
messageReceiptRoot: BYTES,
|
|
28
|
+
messageReceiptCount: BIG_NAT,
|
|
29
|
+
applicationHash: BYTES,
|
|
30
|
+
prevRoot: BYTES,
|
|
31
|
+
time: BIG_NAT,
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
let Transaction = object({
|
|
36
|
+
index: NAT,
|
|
37
|
+
...project(fields.transaction, {
|
|
38
|
+
bytecodeLength: option(BIG_NAT),
|
|
39
|
+
bytecodeWitnessIndex: option(NAT),
|
|
40
|
+
gasPrice: option(BIG_NAT),
|
|
41
|
+
hash: BYTES,
|
|
42
|
+
inputAssetIds: option(array(BYTES)),
|
|
43
|
+
policies: option(object({
|
|
44
|
+
gasPrice: option(BIG_NAT),
|
|
45
|
+
witnessLimit: option(BIG_NAT),
|
|
46
|
+
maturity: option(NAT),
|
|
47
|
+
maxFee: option(BIG_NAT)
|
|
48
|
+
})),
|
|
49
|
+
inputContract: option(object({
|
|
50
|
+
utxoId: BYTES,
|
|
51
|
+
balanceRoot: BYTES,
|
|
52
|
+
stateRoot: BYTES,
|
|
53
|
+
txPointer: STRING,
|
|
54
|
+
contract: BYTES
|
|
55
|
+
})),
|
|
56
|
+
inputContracts: option(array(BYTES)),
|
|
57
|
+
isCreate: BOOLEAN,
|
|
58
|
+
isMint: BOOLEAN,
|
|
59
|
+
isScript: BOOLEAN,
|
|
60
|
+
maturity: option(NAT),
|
|
61
|
+
mintAmount: option(BIG_NAT),
|
|
62
|
+
mintAssetId: option(BYTES),
|
|
63
|
+
outputContract: option(object({
|
|
64
|
+
inputIndex: NAT,
|
|
65
|
+
balanceRoot: BYTES,
|
|
66
|
+
stateRoot: BYTES
|
|
67
|
+
})),
|
|
68
|
+
rawPayload: option(BYTES),
|
|
69
|
+
receiptsRoot: option(BYTES),
|
|
70
|
+
salt: option(BYTES),
|
|
71
|
+
script: option(BYTES),
|
|
72
|
+
scriptData: option(BYTES),
|
|
73
|
+
scriptGasLimit: option(BIG_NAT),
|
|
74
|
+
storageSlots: option(array(BYTES)),
|
|
75
|
+
txPointer: option(STRING),
|
|
76
|
+
type: oneOf({
|
|
77
|
+
script: constant('Script'),
|
|
78
|
+
create: constant('Create'),
|
|
79
|
+
mint: constant('Mint'),
|
|
80
|
+
}),
|
|
81
|
+
witnesses: option(array(BYTES)),
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
let Receipt = object({
|
|
86
|
+
transactionIndex: NAT,
|
|
87
|
+
index: NAT,
|
|
88
|
+
...project(fields.receipt, {
|
|
89
|
+
amount: option(BIG_NAT),
|
|
90
|
+
assetId: option(BYTES),
|
|
91
|
+
contract: option(BYTES),
|
|
92
|
+
contractId: option(BYTES),
|
|
93
|
+
data: option(BYTES),
|
|
94
|
+
digest: option(BYTES),
|
|
95
|
+
gas: option(BIG_NAT),
|
|
96
|
+
gasUsed: option(BIG_NAT),
|
|
97
|
+
is: option(BIG_NAT),
|
|
98
|
+
len: option(BIG_NAT),
|
|
99
|
+
nonce: option(BYTES),
|
|
100
|
+
param1: option(BIG_NAT),
|
|
101
|
+
param2: option(BIG_NAT),
|
|
102
|
+
pc: option(BIG_NAT),
|
|
103
|
+
ptr: option(BIG_NAT),
|
|
104
|
+
ra: option(BIG_NAT),
|
|
105
|
+
rb: option(BIG_NAT),
|
|
106
|
+
rc: option(BIG_NAT),
|
|
107
|
+
rd: option(BIG_NAT),
|
|
108
|
+
reason: option(BIG_NAT),
|
|
109
|
+
receiptType: oneOf({
|
|
110
|
+
CALL: constant('CALL'),
|
|
111
|
+
RETURN: constant('RETURN'),
|
|
112
|
+
RETURN_DATA: constant('RETURN_DATA'),
|
|
113
|
+
PANIC: constant('PANIC'),
|
|
114
|
+
REVERT: constant('REVERT'),
|
|
115
|
+
LOG: constant('LOG'),
|
|
116
|
+
LOG_DATA: constant('LOG_DATA'),
|
|
117
|
+
TRANSFER: constant('TRANSFER'),
|
|
118
|
+
TRANSFER_OUT: constant('TRANSFER_OUT'),
|
|
119
|
+
SCRIPT_RESULT: constant('SCRIPT_RESULT'),
|
|
120
|
+
MESSAGE_OUT: constant('MESSAGE_OUT'),
|
|
121
|
+
MINT: constant('MINT'),
|
|
122
|
+
BURN: constant('BURN'),
|
|
123
|
+
}),
|
|
124
|
+
recipient: option(BYTES),
|
|
125
|
+
result: option(BIG_NAT),
|
|
126
|
+
sender: option(BYTES),
|
|
127
|
+
subId: option(BYTES),
|
|
128
|
+
to: option(BYTES),
|
|
129
|
+
toAddress: option(BYTES),
|
|
130
|
+
val: option(BIG_NAT),
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
let InputCoin = object({
|
|
135
|
+
transactionIndex: NAT,
|
|
136
|
+
index: NAT,
|
|
137
|
+
...project({
|
|
138
|
+
amount: fields.input?.coinAmount,
|
|
139
|
+
assetId: fields.input?.coinAssetId,
|
|
140
|
+
maturity: fields.input?.coinMaturity,
|
|
141
|
+
owner: fields.input?.coinOwner,
|
|
142
|
+
predicate: fields.input?.coinPredicate,
|
|
143
|
+
predicateData: fields.input?.coinPredicateData,
|
|
144
|
+
predicateGasUsed: fields.input?.coinPredicateGasUsed,
|
|
145
|
+
txPointer: fields.input?.coinTxPointer,
|
|
146
|
+
utxoId: fields.input?.coinUtxoId,
|
|
147
|
+
witnessIndex: fields.input?.coinWitnessIndex
|
|
148
|
+
}, {
|
|
149
|
+
utxoId: BYTES,
|
|
150
|
+
owner: BYTES,
|
|
151
|
+
amount: BIG_NAT,
|
|
152
|
+
assetId: BYTES,
|
|
153
|
+
txPointer: STRING,
|
|
154
|
+
witnessIndex: NAT,
|
|
155
|
+
maturity: NAT,
|
|
156
|
+
predicateGasUsed: BIG_NAT,
|
|
157
|
+
predicate: BYTES,
|
|
158
|
+
predicateData: BYTES,
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
let InputContract = object({
|
|
163
|
+
transactionIndex: NAT,
|
|
164
|
+
index: NAT,
|
|
165
|
+
...project({
|
|
166
|
+
utxoId: fields.input?.contractUtxoId,
|
|
167
|
+
balanceRoot: fields.input?.contractBalanceRoot,
|
|
168
|
+
contract: fields.input?.contractContract,
|
|
169
|
+
stateRoot: fields.input?.contractStateRoot,
|
|
170
|
+
txPointer: fields.input?.contractTxPointer
|
|
171
|
+
}, {
|
|
172
|
+
utxoId: BYTES,
|
|
173
|
+
balanceRoot: BYTES,
|
|
174
|
+
stateRoot: BYTES,
|
|
175
|
+
txPointer: STRING,
|
|
176
|
+
contract: BYTES,
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
let InputMessage = object({
|
|
181
|
+
transactionIndex: NAT,
|
|
182
|
+
index: NAT,
|
|
183
|
+
...project({
|
|
184
|
+
sender: fields.input?.messageSender,
|
|
185
|
+
amount: fields.input?.messageAmount,
|
|
186
|
+
data: fields.input?.messageData,
|
|
187
|
+
nonce: fields.input?.messageNonce,
|
|
188
|
+
predicate: fields.input?.messagePredicate,
|
|
189
|
+
predicateData: fields.input?.messagePredicateData,
|
|
190
|
+
predicateGasUsed: fields.input?.messagePredicateGasUsed,
|
|
191
|
+
recipient: fields.input?.messageRecipient,
|
|
192
|
+
witnessIndex: fields.input?.messageWitnessIndex
|
|
193
|
+
}, {
|
|
194
|
+
sender: BYTES,
|
|
195
|
+
recipient: BYTES,
|
|
196
|
+
amount: BIG_NAT,
|
|
197
|
+
nonce: BYTES,
|
|
198
|
+
witnessIndex: NAT,
|
|
199
|
+
predicateGasUsed: BIG_NAT,
|
|
200
|
+
data: BYTES,
|
|
201
|
+
predicate: BYTES,
|
|
202
|
+
predicateData: BYTES,
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
let Input = taggedUnion('type', {
|
|
207
|
+
InputCoin,
|
|
208
|
+
InputContract,
|
|
209
|
+
InputMessage
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
let CoinOutput = object({
|
|
213
|
+
transactionIndex: NAT,
|
|
214
|
+
index: NAT,
|
|
215
|
+
...project({
|
|
216
|
+
amount: fields.output?.coinAmount,
|
|
217
|
+
assetId: fields.output?.coinAssetId,
|
|
218
|
+
to: fields.output?.coinTo
|
|
219
|
+
}, {
|
|
220
|
+
to: BYTES,
|
|
221
|
+
amount: BIG_NAT,
|
|
222
|
+
assetId: BYTES
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
let ContractOutput = object({
|
|
227
|
+
transactionIndex: NAT,
|
|
228
|
+
index: NAT,
|
|
229
|
+
...project({
|
|
230
|
+
inputIndex: fields.output?.contractInputIndex,
|
|
231
|
+
balanceRoot: fields.output?.contractBalanceRoot,
|
|
232
|
+
stateRoot: fields.output?.contractStateRoot
|
|
233
|
+
}, {
|
|
234
|
+
inputIndex: NAT,
|
|
235
|
+
balanceRoot: BYTES,
|
|
236
|
+
stateRoot: BYTES
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
let ChangeOutput = object({
|
|
241
|
+
transactionIndex: NAT,
|
|
242
|
+
index: NAT,
|
|
243
|
+
...project({
|
|
244
|
+
amount: fields.output?.changeAmount,
|
|
245
|
+
assetId: fields.output?.changeAssetId,
|
|
246
|
+
to: fields.output?.changeTo
|
|
247
|
+
}, {
|
|
248
|
+
to: BYTES,
|
|
249
|
+
amount: BIG_NAT,
|
|
250
|
+
assetId: BYTES
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
let VariableOutput = object({
|
|
255
|
+
transactionIndex: NAT,
|
|
256
|
+
index: NAT,
|
|
257
|
+
...project({
|
|
258
|
+
to: fields.output?.variableTo,
|
|
259
|
+
amount: fields.output?.variableAmount,
|
|
260
|
+
assetId: fields.output?.variableAssetId
|
|
261
|
+
}, {
|
|
262
|
+
to: BYTES,
|
|
263
|
+
amount: BIG_NAT,
|
|
264
|
+
assetId: BYTES
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
let ContractCreated = object({
|
|
269
|
+
transactionIndex: NAT,
|
|
270
|
+
index: NAT,
|
|
271
|
+
...project({
|
|
272
|
+
contract: fields.output?.contractCreatedContract,
|
|
273
|
+
stateRoot: fields.output?.contractCreatedStateRoot
|
|
274
|
+
}, {
|
|
275
|
+
contract: object({
|
|
276
|
+
id: BYTES,
|
|
277
|
+
bytecode: BYTES,
|
|
278
|
+
salt: BYTES
|
|
279
|
+
}),
|
|
280
|
+
stateRoot: BYTES
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
let Ouput = taggedUnion('type', {
|
|
285
|
+
CoinOutput,
|
|
286
|
+
ContractOutput,
|
|
287
|
+
ChangeOutput,
|
|
288
|
+
VariableOutput,
|
|
289
|
+
ContractCreated
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
return object({
|
|
293
|
+
header: BlockHeader,
|
|
294
|
+
transactions: option(array(Transaction)),
|
|
295
|
+
receipts: option(array(Receipt)),
|
|
296
|
+
inputs: option(array(Input)),
|
|
297
|
+
outputs: option(array(Ouput)),
|
|
298
|
+
})
|
|
299
|
+
})
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
function project<T>(fields: Selector<keyof T> | undefined, obj: T): Partial<T> {
|
|
303
|
+
if (fields == null) return {}
|
|
304
|
+
let result: Partial<T> = {}
|
|
305
|
+
let key: keyof T
|
|
306
|
+
for (key in obj) {
|
|
307
|
+
if (fields[key]) {
|
|
308
|
+
result[key] = obj[key]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return result
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
export function isEmpty(obj: object): boolean {
|
|
316
|
+
for (let _ in obj) {
|
|
317
|
+
return false
|
|
318
|
+
}
|
|
319
|
+
return true
|
|
320
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {BlockHeader} from '@subsquid/fuel-normalization'
|
|
2
|
+
import {assertNotNull} from '@subsquid/util-internal'
|
|
3
|
+
import {ArchiveClient} from '@subsquid/util-internal-archive-client'
|
|
4
|
+
import {archiveIngest} from '@subsquid/util-internal-ingest-tools'
|
|
5
|
+
import {getRequestAt, mapRangeRequestList, RangeRequestList} from '@subsquid/util-internal-range'
|
|
6
|
+
import {array, cast} from '@subsquid/util-internal-validation'
|
|
7
|
+
import assert from 'assert'
|
|
8
|
+
import {DataRequest} from '../data/data-request'
|
|
9
|
+
import {getDataSchema} from './data-schema'
|
|
10
|
+
import {PartialBlock} from '../data/data-partial'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export class FuelGateway {
|
|
14
|
+
constructor(private client: ArchiveClient) {}
|
|
15
|
+
|
|
16
|
+
getFinalizedHeight(): Promise<number> {
|
|
17
|
+
return this.client.getHeight()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async getBlockHash(height: number): Promise<string | undefined> {
|
|
21
|
+
let blocks = await this.client.query({
|
|
22
|
+
fromBlock: height,
|
|
23
|
+
toBlock: height,
|
|
24
|
+
includeAllBlocks: true
|
|
25
|
+
})
|
|
26
|
+
assert(blocks.length == 1)
|
|
27
|
+
return blocks[0].header.hash
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getBlockHeader(height: number): Promise<BlockHeader> {
|
|
31
|
+
let blocks = await this.client.query({
|
|
32
|
+
type: 'fuel',
|
|
33
|
+
fromBlock: height,
|
|
34
|
+
toBlock: height,
|
|
35
|
+
includeAllBlocks: true,
|
|
36
|
+
fields: {
|
|
37
|
+
block: {
|
|
38
|
+
daHeight: true,
|
|
39
|
+
transactionsRoot: true,
|
|
40
|
+
transactionsCount: true,
|
|
41
|
+
messageReceiptRoot: true,
|
|
42
|
+
messageReceiptCount: true,
|
|
43
|
+
prevRoot: true,
|
|
44
|
+
time: true,
|
|
45
|
+
applicationHash: true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
assert(blocks.length == 1)
|
|
50
|
+
let {number, ...rest} = blocks[0].header
|
|
51
|
+
return {
|
|
52
|
+
height: number,
|
|
53
|
+
...rest
|
|
54
|
+
} as BlockHeader
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async *getBlockStream(requests: RangeRequestList<DataRequest>, stopOnHead?: boolean | undefined): AsyncIterable<PartialBlock[]> {
|
|
58
|
+
let archiveRequests = mapRangeRequestList(requests, req => {
|
|
59
|
+
let {fields, ...items} = req
|
|
60
|
+
return {
|
|
61
|
+
type: 'fuel',
|
|
62
|
+
fields,
|
|
63
|
+
...items
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
for await (let batch of archiveIngest({
|
|
68
|
+
client: this.client,
|
|
69
|
+
requests: archiveRequests,
|
|
70
|
+
stopOnHead
|
|
71
|
+
})) {
|
|
72
|
+
let req = getRequestAt(requests, batch.blocks[0].header.number)
|
|
73
|
+
|
|
74
|
+
let blocks = cast(
|
|
75
|
+
array(getDataSchema(assertNotNull(req?.fields))),
|
|
76
|
+
batch.blocks
|
|
77
|
+
).map(b => {
|
|
78
|
+
let {header: {number, ...hdr}, ...items} = b
|
|
79
|
+
return {
|
|
80
|
+
header: {height: number, ...hdr},
|
|
81
|
+
...items
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
yield blocks
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type * as data from '@subsquid/fuel-data/lib/data'
|
|
2
|
+
import type {MakePartial} from './util'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export type BlockRequiredFields = 'height' | 'hash'
|
|
6
|
+
export type TransactionRequiredFields = 'index'
|
|
7
|
+
export type ReceiptRequiredFields = 'transactionIndex' | 'index'
|
|
8
|
+
export type InputRequiredFields = 'transactionIndex' | 'index' | 'type'
|
|
9
|
+
export type OutputRequiredFields = 'transactionIndex' | 'index' | 'type'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export type PartialBlockHeader = MakePartial<data.BlockHeader, BlockRequiredFields>
|
|
13
|
+
export type PartialTransaction = MakePartial<data.Transaction, TransactionRequiredFields>
|
|
14
|
+
export type PartialReceipt = MakePartial<data.Receipt, ReceiptRequiredFields>
|
|
15
|
+
export type PartialInput = MakePartial<data.TransactionInput, InputRequiredFields>
|
|
16
|
+
export type PartialOutput = MakePartial<data.TransactionOutput, OutputRequiredFields>
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export interface PartialBlock {
|
|
20
|
+
header: PartialBlockHeader
|
|
21
|
+
transactions?: PartialTransaction[]
|
|
22
|
+
receipts?: PartialReceipt[]
|
|
23
|
+
inputs?: PartialInput[]
|
|
24
|
+
outputs?: PartialOutput[]
|
|
25
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {ReceiptType, TransactionType, InputType, OutputType} from '@subsquid/fuel-data/lib/data'
|
|
2
|
+
import {FieldSelection, Bytes} from './model'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export interface DataRequest {
|
|
6
|
+
fields?: FieldSelection
|
|
7
|
+
includeAllBlocks?: boolean
|
|
8
|
+
transactions?: TransactionRequest[]
|
|
9
|
+
receipts?: ReceiptRequest[]
|
|
10
|
+
inputs?: InputRequest[]
|
|
11
|
+
outputs?: OutputRequest[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export interface TransactionRequest {
|
|
16
|
+
type?: TransactionType[]
|
|
17
|
+
receipts?: boolean
|
|
18
|
+
inputs?: boolean
|
|
19
|
+
outputs?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export interface ReceiptRequest {
|
|
24
|
+
type?: ReceiptType[]
|
|
25
|
+
logDataContract?: Bytes[]
|
|
26
|
+
transaction?: boolean
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
export interface InputRequest {
|
|
31
|
+
type?: InputType[]
|
|
32
|
+
coinOwner?: Bytes[]
|
|
33
|
+
coinAssetId?: Bytes[]
|
|
34
|
+
contractContract?: Bytes[]
|
|
35
|
+
messageSender?: Bytes[]
|
|
36
|
+
messageRecipient?: Bytes[]
|
|
37
|
+
transaction?: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export interface OutputRequest {
|
|
42
|
+
type?: OutputType[]
|
|
43
|
+
transaction?: boolean
|
|
44
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type * as data from '@subsquid/fuel-data/lib/data'
|
|
2
|
+
import type {
|
|
3
|
+
BlockRequiredFields,
|
|
4
|
+
ReceiptRequiredFields,
|
|
5
|
+
InputRequiredFields,
|
|
6
|
+
OutputRequiredFields,
|
|
7
|
+
TransactionRequiredFields
|
|
8
|
+
} from './data-partial'
|
|
9
|
+
import type {GetFields, Select, Selector, Simplify} from './util'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Hex encoded binary string
|
|
14
|
+
*/
|
|
15
|
+
export type Bytes = string
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
type AddPrefix<Prefix extends string, S extends string> = `${Prefix}${Capitalize<S>}`
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export interface FieldSelection {
|
|
22
|
+
block?: Selector<Exclude<keyof data.BlockHeader, BlockRequiredFields>>
|
|
23
|
+
transaction?: Selector<Exclude<keyof data.Transaction, TransactionRequiredFields>>
|
|
24
|
+
receipt?: Selector<Exclude<keyof data.Receipt, ReceiptRequiredFields>>
|
|
25
|
+
input?: Selector<
|
|
26
|
+
AddPrefix<'coin', Exclude<keyof data.InputCoin, InputRequiredFields>> |
|
|
27
|
+
AddPrefix<'contract', Exclude<keyof data.InputContract, InputRequiredFields>> |
|
|
28
|
+
AddPrefix<'message', Exclude<keyof data.InputMessage, InputRequiredFields>>
|
|
29
|
+
>
|
|
30
|
+
output?: Selector<
|
|
31
|
+
AddPrefix<'coin', Exclude<keyof data.CoinOutput, OutputRequiredFields>> |
|
|
32
|
+
AddPrefix<'contract', Exclude<keyof data.ContractOutput, OutputRequiredFields>> |
|
|
33
|
+
AddPrefix<'change', Exclude<keyof data.ChangeOutput, OutputRequiredFields>> |
|
|
34
|
+
AddPrefix<'variable', Exclude<keyof data.VariableOutput, OutputRequiredFields>> |
|
|
35
|
+
AddPrefix<'contractCreated', Exclude<keyof data.ContractCreated, OutputRequiredFields>>
|
|
36
|
+
>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export const DEFAULT_FIELDS = {
|
|
41
|
+
block: {
|
|
42
|
+
time: true
|
|
43
|
+
},
|
|
44
|
+
transaction: {
|
|
45
|
+
hash: true,
|
|
46
|
+
type: true,
|
|
47
|
+
status: true
|
|
48
|
+
},
|
|
49
|
+
receipt: {
|
|
50
|
+
receiptType: true
|
|
51
|
+
},
|
|
52
|
+
input: {},
|
|
53
|
+
output: {},
|
|
54
|
+
} as const
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
type Item<
|
|
58
|
+
Data,
|
|
59
|
+
RequiredFields extends keyof Data,
|
|
60
|
+
F extends FieldSelection,
|
|
61
|
+
K extends keyof FieldSelection
|
|
62
|
+
> = Simplify<
|
|
63
|
+
Pick<Data, RequiredFields> &
|
|
64
|
+
Select<Data, GetFields<FieldSelection, typeof DEFAULT_FIELDS, F, K>>
|
|
65
|
+
>
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
export type BlockHeader<F extends FieldSelection = {}> = Item<
|
|
69
|
+
data.BlockHeader,
|
|
70
|
+
BlockRequiredFields,
|
|
71
|
+
F,
|
|
72
|
+
'block'
|
|
73
|
+
>
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
export type Transaction<F extends FieldSelection = {}> = Item<
|
|
77
|
+
data.Transaction,
|
|
78
|
+
TransactionRequiredFields,
|
|
79
|
+
F,
|
|
80
|
+
'transaction'
|
|
81
|
+
>
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
export type Receipt<F extends FieldSelection = {}> = Item<
|
|
85
|
+
data.Receipt,
|
|
86
|
+
ReceiptRequiredFields,
|
|
87
|
+
F,
|
|
88
|
+
'receipt'
|
|
89
|
+
>
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
export type Input<F extends FieldSelection = {}> = Item<
|
|
93
|
+
data.TransactionInput,
|
|
94
|
+
InputRequiredFields,
|
|
95
|
+
F,
|
|
96
|
+
'input'
|
|
97
|
+
>
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
export type Output<F extends FieldSelection = {}> = Item<
|
|
101
|
+
data.TransactionOutput,
|
|
102
|
+
OutputRequiredFields,
|
|
103
|
+
F,
|
|
104
|
+
'output'
|
|
105
|
+
>
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
export interface Block<F extends FieldSelection = {}> {
|
|
109
|
+
header: BlockHeader<F>
|
|
110
|
+
transactions: Transaction<F>[]
|
|
111
|
+
receipts: Receipt<F>[]
|
|
112
|
+
inputs: Input<F>[]
|
|
113
|
+
outputs: Output<F>[]
|
|
114
|
+
}
|
package/src/data/util.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type Simplify<T> = {
|
|
2
|
+
[K in keyof T]: T[K]
|
|
3
|
+
} & {}
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export type ExcludeUndefined<T> = {
|
|
7
|
+
[K in keyof T as undefined extends T[K] ? never : K]: T[K]
|
|
8
|
+
} & {}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export type GetFields<
|
|
12
|
+
FieldSelectionType,
|
|
13
|
+
Defaults extends FieldSelectionType,
|
|
14
|
+
Selection extends FieldSelectionType,
|
|
15
|
+
K extends keyof FieldSelectionType
|
|
16
|
+
> = TrueFields<MergeDefault<Selection[K], Defaults[K]>>
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
type MergeDefault<T, D> = Simplify<
|
|
20
|
+
undefined extends T ? D : Omit<D, keyof ExcludeUndefined<T>> & ExcludeUndefined<T>
|
|
21
|
+
>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
type TrueFields<F> = keyof {
|
|
25
|
+
[K in keyof F as true extends F[K] ? K : never]: true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
export type Select<T, Fields> = T extends any ? Simplify<Pick<T, Extract<keyof T, Fields>>> : never
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
export type Selector<Fields extends string | number | symbol> = {
|
|
33
|
+
[P in Fields]?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export type MakePartial<T, Required extends keyof T> = Simplify<
|
|
38
|
+
Pick<T, Required> &
|
|
39
|
+
{
|
|
40
|
+
[K in keyof T as K extends Required ? never : K]+?: T[K]
|
|
41
|
+
}
|
|
42
|
+
>
|
package/src/fields.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {DEFAULT_FIELDS, FieldSelection} from './data/model'
|
|
2
|
+
import {Selector} from './data/util'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get effective set of selected fields.
|
|
7
|
+
*/
|
|
8
|
+
export function getFields(fields: FieldSelection | undefined): FieldSelection {
|
|
9
|
+
return {
|
|
10
|
+
block: merge(DEFAULT_FIELDS.block, fields?.block),
|
|
11
|
+
transaction: merge(DEFAULT_FIELDS.transaction, fields?.transaction),
|
|
12
|
+
receipt: merge(DEFAULT_FIELDS.receipt, fields?.receipt),
|
|
13
|
+
input: merge(DEFAULT_FIELDS.input, fields?.input),
|
|
14
|
+
output: merge(DEFAULT_FIELDS.output, fields?.output),
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
function merge<Keys extends string>(def: Selector<Keys>, requested: Selector<Keys> = {}): Selector<Keys> {
|
|
20
|
+
let fields: Selector<Keys> = {}
|
|
21
|
+
|
|
22
|
+
for (let key in def) {
|
|
23
|
+
if (requested[key] !== false) {
|
|
24
|
+
fields[key] = def[key]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for (let key in requested) {
|
|
29
|
+
if (requested[key]) {
|
|
30
|
+
fields[key] = true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return fields
|
|
35
|
+
}
|