@subsquid/solana-stream 0.1.3 → 0.2.0-2-0.3887d2

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.
Files changed (84) hide show
  1. package/lib/index.d.ts +2 -3
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.js +2 -3
  4. package/lib/index.js.map +1 -1
  5. package/lib/instruction.d.ts +2 -3
  6. package/lib/instruction.d.ts.map +1 -1
  7. package/lib/instruction.js +2 -2
  8. package/lib/instruction.js.map +1 -1
  9. package/lib/query.d.ts +46 -0
  10. package/lib/query.d.ts.map +1 -0
  11. package/lib/query.js +161 -0
  12. package/lib/query.js.map +1 -0
  13. package/lib/{archive/schema.d.ts → schema.d.ts} +30 -19
  14. package/lib/schema.d.ts.map +1 -0
  15. package/lib/{archive/schema.js → schema.js} +54 -38
  16. package/lib/schema.js.map +1 -0
  17. package/lib/source.d.ts +24 -101
  18. package/lib/source.d.ts.map +1 -1
  19. package/lib/source.js +67 -270
  20. package/lib/source.js.map +1 -1
  21. package/package.json +10 -15
  22. package/src/index.ts +2 -3
  23. package/src/instruction.ts +4 -9
  24. package/src/query.ts +192 -0
  25. package/src/{archive/schema.ts → schema.ts} +52 -34
  26. package/src/source.ts +94 -365
  27. package/README.md +0 -4
  28. package/lib/archive/schema.d.ts.map +0 -1
  29. package/lib/archive/schema.js.map +0 -1
  30. package/lib/archive/source.d.ts +0 -15
  31. package/lib/archive/source.d.ts.map +0 -1
  32. package/lib/archive/source.js +0 -98
  33. package/lib/archive/source.js.map +0 -1
  34. package/lib/data/fields.d.ts +0 -8
  35. package/lib/data/fields.d.ts.map +0 -1
  36. package/lib/data/fields.js +0 -46
  37. package/lib/data/fields.js.map +0 -1
  38. package/lib/data/model.d.ts +0 -79
  39. package/lib/data/model.d.ts.map +0 -1
  40. package/lib/data/model.js +0 -44
  41. package/lib/data/model.js.map +0 -1
  42. package/lib/data/partial.d.ts +0 -26
  43. package/lib/data/partial.d.ts.map +0 -1
  44. package/lib/data/partial.js +0 -3
  45. package/lib/data/partial.js.map +0 -1
  46. package/lib/data/request.d.ts +0 -106
  47. package/lib/data/request.d.ts.map +0 -1
  48. package/lib/data/request.js +0 -3
  49. package/lib/data/request.js.map +0 -1
  50. package/lib/data/type-util.d.ts +0 -20
  51. package/lib/data/type-util.d.ts.map +0 -1
  52. package/lib/data/type-util.js +0 -3
  53. package/lib/data/type-util.js.map +0 -1
  54. package/lib/rpc/client.d.ts +0 -17
  55. package/lib/rpc/client.d.ts.map +0 -1
  56. package/lib/rpc/client.js +0 -15
  57. package/lib/rpc/client.js.map +0 -1
  58. package/lib/rpc/filter.d.ts +0 -4
  59. package/lib/rpc/filter.d.ts.map +0 -1
  60. package/lib/rpc/filter.js +0 -351
  61. package/lib/rpc/filter.js.map +0 -1
  62. package/lib/rpc/mapping.d.ts +0 -5
  63. package/lib/rpc/mapping.d.ts.map +0 -1
  64. package/lib/rpc/mapping.js +0 -12
  65. package/lib/rpc/mapping.js.map +0 -1
  66. package/lib/rpc/project.d.ts +0 -5
  67. package/lib/rpc/project.d.ts.map +0 -1
  68. package/lib/rpc/project.js +0 -60
  69. package/lib/rpc/project.js.map +0 -1
  70. package/lib/rpc/source.d.ts +0 -15
  71. package/lib/rpc/source.d.ts.map +0 -1
  72. package/lib/rpc/source.js +0 -82
  73. package/lib/rpc/source.js.map +0 -1
  74. package/src/archive/source.ts +0 -105
  75. package/src/data/fields.ts +0 -50
  76. package/src/data/model.ts +0 -154
  77. package/src/data/partial.ts +0 -31
  78. package/src/data/request.ts +0 -140
  79. package/src/data/type-util.ts +0 -42
  80. package/src/rpc/client.ts +0 -26
  81. package/src/rpc/filter.ts +0 -362
  82. package/src/rpc/mapping.ts +0 -13
  83. package/src/rpc/project.ts +0 -61
  84. package/src/rpc/source.ts +0 -90
package/src/source.ts CHANGED
@@ -1,392 +1,121 @@
1
- import {HttpAgent, HttpClient} from '@subsquid/http-client'
2
- import {BlockInfo} from '@subsquid/solana-rpc'
3
- import {Base58Bytes} from '@subsquid/solana-rpc-data'
4
- import {addErrorContext, def, last} from '@subsquid/util-internal'
5
- import {ArchiveClient} from '@subsquid/util-internal-archive-client'
6
- import {getOrGenerateSquidId} from '@subsquid/util-internal-processor-tools'
1
+ import {applyRangeBound, mergeRangeRequests, Range, RangeRequest} from '@subsquid/util-internal-range'
2
+ import {PortalClient, PortalStreamData} from '@subsquid/portal-client'
3
+ import {cast} from '@subsquid/util-internal-validation'
7
4
  import {
8
- applyRangeBound,
9
- FiniteRange,
10
- getSize,
11
- mergeRangeRequests,
12
- Range,
13
- RangeRequest,
14
- RangeRequestList
15
- } from '@subsquid/util-internal-range'
16
- import assert from 'assert'
17
- import {SolanaArchive} from './archive/source'
18
- import {getFields} from './data/fields'
19
- import {Block, BlockHeader, FieldSelection} from './data/model'
20
- import {PartialBlock} from './data/partial'
21
- import {
22
- BalanceRequest,
5
+ BlockData,
23
6
  DataRequest,
24
- InstructionRequest,
25
- LogRequest,
26
- RewardRequest,
27
- TokenBalanceRequest,
28
- TransactionRequest
29
- } from './data/request'
30
- import {SolanaRpcClient} from './rpc/client'
31
- import {RpcDataSource} from './rpc/source'
32
-
33
-
34
- export interface GatewaySettings {
35
- /**
36
- * Subsquid Network Gateway url
37
- */
38
- url: string
39
- /**
40
- * Request timeout in ms
41
- */
42
- requestTimeout?: number
43
- }
44
-
45
-
46
- export interface RpcSettings {
47
- /**
48
- * RPC client
49
- */
50
- client: SolanaRpcClient
51
- /**
52
- * `getBlock` batch call size.
53
- *
54
- * Default is `5`.
55
- */
56
- strideSize?: number
57
- /**
58
- * Maximum number of concurrent `getBlock` batch calls.
59
- *
60
- * Default is `10`
61
- */
62
- strideConcurrency?: number
63
- /**
64
- * Minimum distance from finalized head below which concurrent
65
- * fetch procedure is allowed.
66
- *
67
- * Default is `50` blocks.
68
- *
69
- * Concurrent fetch procedure can perform multiple `getBlock` batch calls simultaneously and is faster,
70
- * but assumes consistent behaviour of RPC endpoint.
71
- *
72
- * The latter might not be the case due to load balancing,
73
- * when one request is sent to node `A` with head slot `X` and
74
- * another to node `B` with head slot `X - 10`.
75
- */
76
- concurrentFetchThreshold?: number
7
+ SolanaQueryOptions,
8
+ FieldSelection,
9
+ mergeDataRequests,
10
+ mergeSelection,
11
+ Response,
12
+ } from './query'
13
+ import type {MergeSelection} from '@subsquid/util-internal'
14
+ import {DataSource, DataSourceStream, DataSourceStreamData} from '@subsquid/data-source'
15
+ import {getDataSchema} from './schema'
16
+
17
+ export interface SolanaPortalDataSourceOptions<Q extends SolanaQueryOptions> {
18
+ portal: string | PortalClient
19
+ query: Q
77
20
  }
78
21
 
22
+ export class SolanaPortalDataSource<
23
+ Q extends SolanaQueryOptions,
24
+ B extends BlockData<GetFields<Q['fields']>> = BlockData<GetFields<Q['fields']>>
25
+ > implements DataSource<B>
26
+ {
27
+ private portal: PortalClient
28
+ private fields: Q['fields']
29
+ private requests: RangeRequest<DataRequest>[]
79
30
 
80
- interface BlockRange {
81
- range?: Range
82
- }
83
-
84
-
85
- export class DataSourceBuilder<F extends FieldSelection = {}> {
86
- private requests: RangeRequest<DataRequest>[] = []
87
- private fields?: FieldSelection
88
- private blockRange?: Range
89
- private archive?: GatewaySettings
90
- private rpc?: RpcSettings
91
-
92
- /**
93
- * Set Subsquid Network Gateway endpoint (ex Archive).
94
- *
95
- * Subsquid Network allows to get data from finalized blocks up to
96
- * infinite times faster and more efficient than via regular RPC.
97
- *
98
- * @example
99
- * source.setGateway('https://v2.archive.subsquid.io/network/solana-mainnet')
100
- */
101
- setGateway(url: string | GatewaySettings): this {
102
- if (typeof url == 'string') {
103
- this.archive = {url}
104
- } else {
105
- this.archive = url
106
- }
107
- return this
108
- }
109
-
110
- /**
111
- * Set up RPC data ingestion
112
- */
113
- setRpc(settings?: RpcSettings): this {
114
- this.rpc = settings
115
- return this
116
- }
117
-
118
- /**
119
- * Limits the range of blocks to fetch.
120
- *
121
- * Note, that block heights should be used instead of slots.
122
- */
123
- setBlockRange(range?: Range): this {
124
- this.blockRange = range
125
- return this
126
- }
127
-
128
- /**
129
- * Configure a set of fetched fields
130
- */
131
- setFields<F extends FieldSelection>(fields: F): DataSourceBuilder<F> {
132
- this.fields = fields
133
- return this as any
134
- }
135
-
136
- private add(range: Range | undefined, request: DataRequest): void {
137
- this.requests.push({
138
- range: range || {from: 0},
139
- request
140
- })
141
- }
142
-
143
- /**
144
- * By default, blocks that doesn't contain requested items can be omitted.
145
- * This method modifies such behaviour to fetch all chain blocks.
146
- *
147
- * Optionally a range of blocks can be specified
148
- * for which the setting should be effective.
149
- */
150
- includeAllBlocks(range?: Range): this {
151
- this.add(range, {includeAllBlocks: true})
152
- return this
153
- }
154
-
155
- addTransaction(options: TransactionRequest & BlockRange): this {
156
- let {range, ...req} = options
157
- this.add(range, {
158
- transactions: [req]
159
- })
160
- return this
161
- }
162
-
163
- addInstruction(options: InstructionRequest & BlockRange): this {
164
- let {range, ...req} = options
165
- this.add(range, {
166
- instructions: [req]
167
- })
168
- return this
169
- }
170
-
171
- addLog(options: LogRequest & BlockRange): this {
172
- let {range, ...req} = options
173
- this.add(range, {
174
- logs: [req]
175
- })
176
- return this
177
- }
178
-
179
- addBalance(options: BalanceRequest & BlockRange): this {
180
- let {range, ...req} = options
181
- this.add(range, {
182
- balances: [req]
183
- })
184
- return this
31
+ constructor(options: SolanaPortalDataSourceOptions<Q>) {
32
+ this.portal = typeof options.portal === 'string' ? new PortalClient({url: options.portal}) : options.portal
33
+ this.fields = options.query.fields
34
+ this.requests = mergeRangeRequests(options.query.requests, mergeDataRequests)
185
35
  }
186
36
 
187
- addTokenBalance(options: TokenBalanceRequest & BlockRange): this {
188
- let {range, ...req} = options
189
- this.add(range, {
190
- tokenBalances: [req]
191
- })
192
- return this
37
+ getHeight(): Promise<number> {
38
+ return this.portal.getFinalizedHeight()
193
39
  }
194
40
 
195
- addReward(options: RewardRequest & BlockRange): this {
196
- let {range, ...req} = options
197
- this.add(range, {
198
- rewards: [req]
199
- })
200
- return this
41
+ getFinalizedHeight(): Promise<number> {
42
+ return this.portal.getFinalizedHeight()
201
43
  }
202
44
 
203
- private getRequests(): RangeRequestList<DataRequest> {
204
- function concat<T>(a?: T[], b?: T[]): T[] | undefined {
205
- let result: T[] = []
206
- if (a) {
207
- result.push(...a)
208
- }
209
- if (b) {
210
- result.push(...b)
211
- }
212
- return result.length == 0 ? undefined : result
213
- }
214
-
215
- let requests = mergeRangeRequests(this.requests, (a, b) => {
216
- return {
217
- includeAllBlocks: a.includeAllBlocks || b.includeAllBlocks,
218
- transactions: concat(a.transactions, b.transactions),
219
- instructions: concat(a.instructions, b.instructions),
220
- logs: concat(a.logs, b.logs),
221
- balances: concat(a.balances, b.balances),
222
- tokenBalances: concat(a.tokenBalances, b.tokenBalances),
223
- rewards: concat(a.rewards, b.rewards)
224
- }
225
- })
226
-
45
+ getBlockStream(range?: Range, stopOnHead?: boolean): DataSourceStream<B> {
227
46
  let fields = getFields(this.fields)
47
+ let requests = applyRangeBound(this.requests, range)
48
+
49
+ let {writable, readable} = new TransformStream<
50
+ PortalStreamData<BlockData<typeof fields>>,
51
+ DataSourceStreamData<B>
52
+ >({
53
+ transform: async (data, controller) => {
54
+ let blocks = data.map((b) => {
55
+ let block = mapBlock(b, fields)
56
+ Object.defineProperty(block, DataSource.blockRef, {
57
+ value: {hash: block.header.hash, number: block.header.number},
58
+ })
59
+ return block
60
+ })
61
+
62
+ Object.defineProperty(blocks, DataSource.finalizedHead, {
63
+ value: data[PortalClient.finalizedHead],
64
+ })
65
+
66
+ controller.enqueue(blocks as DataSourceStreamData<B>)
67
+ },
68
+ })
228
69
 
229
- requests = requests.map(({range, request}) => {
230
- return {
231
- range,
232
- request: {
70
+ const ingest = async () => {
71
+ for (let request of requests) {
72
+ let query = {
73
+ type: 'solana',
74
+ fromBlock: request.range.from,
75
+ toBlock: request.range.to,
233
76
  fields,
234
- ...request
77
+ ...request.request,
235
78
  }
236
- }
237
- })
238
-
239
- return applyRangeBound(requests, this.blockRange)
240
- }
241
-
242
- build(): DataSource<Block<F>> {
243
- return new SolanaDataSource(
244
- this.getRequests(),
245
- this.archive,
246
- this.rpc
247
- ) as DataSource<Block<F>>
248
- }
249
- }
250
-
251
-
252
- export interface DataSource<Block> {
253
- getFinalizedHeight(): Promise<number>
254
- getBlockHash(height: number): Promise<Base58Bytes | undefined>
255
- getBlocksCountInRange(range: FiniteRange): number
256
- getBlockStream(fromBlockHeight?: number): AsyncIterable<Block[]>
257
- }
258
-
259
-
260
- export type GetDataSourceBlock<T> = T extends DataSource<infer B> ? B : never
261
79
 
262
-
263
- class SolanaDataSource implements DataSource<PartialBlock> {
264
- private rpc?: RpcDataSource
265
- private isConsistent?: boolean
266
- private ranges: Range[]
267
-
268
- constructor(
269
- private requests: RangeRequestList<DataRequest>,
270
- private archiveSettings?: GatewaySettings,
271
- rpcSettings?: RpcSettings
272
- ) {
273
- assert(this.archiveSettings || rpcSettings, 'either archive or RPC should be provided')
274
- if (rpcSettings) {
275
- this.rpc = new RpcDataSource(rpcSettings)
276
- }
277
- this.ranges = this.requests.map(req => req.range)
278
- }
279
-
280
- getFinalizedHeight(): Promise<number> {
281
- if (this.rpc) {
282
- return this.rpc.getFinalizedHeight()
283
- } else {
284
- return this.createArchive().getFinalizedHeight()
285
- }
286
- }
287
-
288
- async getBlockHash(height: number): Promise<Base58Bytes | undefined> {
289
- await this.assertConsistency()
290
- if (this.archiveSettings == null) {
291
- assert(this.rpc)
292
- return this.rpc.getBlockHash(height)
293
- } else {
294
- let archive = this.createArchive()
295
- let head = await archive.getFinalizedHeight()
296
- if (head >= height) return archive.getBlockHash(height)
297
- if (this.rpc) return this.rpc.getBlockHash(height)
80
+ await this.portal.getFinalizedStream(query, {stopOnHead}).pipeTo(writable, {
81
+ preventClose: true,
82
+ })
83
+ }
298
84
  }
299
- }
300
85
 
301
- private async assertConsistency(): Promise<void> {
302
- if (this.isConsistent || this.archiveSettings == null || this.rpc == null) return
303
- let blocks = await this.performConsistencyCheck().catch(err => {
304
- throw addErrorContext(
305
- new Error(`Failed to check consistency between Subsquid Gateway and RPC endpoints`),
306
- {reason: err}
86
+ ingest()
87
+ .then(
88
+ () => writable.close(),
89
+ (reason) => writable.abort(reason)
307
90
  )
308
- })
309
- if (blocks == null) {
310
- this.isConsistent = true
311
- } else {
312
- throw addErrorContext(
313
- new Error(`Provided Subsquid Gateway and RPC endpoints don't agree on slot ${blocks.archiveBlock.slot}`),
314
- blocks
315
- )
316
- }
317
- }
318
-
319
- private async performConsistencyCheck(): Promise<{
320
- archiveBlock: BlockHeader
321
- rpcBlock: BlockInfo | null
322
- } | undefined> {
323
- let archive = this.createArchive()
324
- let height = await archive.getFinalizedHeight()
325
- let archiveBlock = await archive.getBlockHeader(height)
326
- let rpcBlock = await this.rpc!.getBlockInfo(archiveBlock.slot)
327
- if (rpcBlock?.blockhash === archiveBlock.hash && rpcBlock.blockHeight === archiveBlock.height) return
328
- return {archiveBlock, rpcBlock: rpcBlock || null}
329
- }
91
+ .catch(() => {})
330
92
 
331
- getBlocksCountInRange(range: FiniteRange): number {
332
- return getSize(this.ranges, range)
93
+ return readable
333
94
  }
95
+ }
334
96
 
335
- async *getBlockStream(fromBlockHeight?: number): AsyncIterable<PartialBlock[]> {
336
- await this.assertConsistency()
337
-
338
- let requests = fromBlockHeight == null
339
- ? this.requests
340
- : applyRangeBound(this.requests, {from: fromBlockHeight})
341
-
342
- if (requests.length == 0) return
343
-
344
- if (this.archiveSettings) {
345
- let agent = new HttpAgent({keepAlive: true})
346
- try {
347
- let archive = this.createArchive(agent)
348
- let height = await archive.getFinalizedHeight()
349
- let from = requests[0].range.from
350
- if (height > from || !this.rpc) {
351
- for await (let batch of archive.getBlockStream(requests, !!this.rpc)) {
352
- yield batch
353
- from = last(batch).header.height + 1
354
- }
355
- requests = applyRangeBound(requests, {from})
356
- }
357
- } finally {
358
- agent.close()
359
- }
360
- }
361
-
362
- if (requests.length == 0) return
97
+ export function mapBlock<F extends FieldSelection, B extends BlockData<F> = BlockData<F>>(
98
+ rawBlock: unknown,
99
+ fields: F
100
+ ): B {
101
+ let validator = getDataSchema(fields)
102
+ let block = cast(validator, rawBlock)
363
103
 
364
- assert(this.rpc)
104
+ return block as unknown as B
105
+ }
365
106
 
366
- yield* this.rpc.getBlockStream(requests)
367
- }
107
+ function getFields<T extends FieldSelection>(fields: T): GetFields<T> {
108
+ return mergeSelection(REQUIRED_FIELDS, fields)
109
+ }
368
110
 
369
- private createArchive(agent?: HttpAgent): SolanaArchive {
370
- assert(this.archiveSettings)
111
+ type GetFields<F extends FieldSelection> = MergeSelection<ReqiredFieldSelection, F>
371
112
 
372
- let http = new HttpClient({
373
- headers: {
374
- 'x-squid-id': this.getSquidId()
375
- },
376
- agent
377
- })
378
-
379
- return new SolanaArchive(
380
- new ArchiveClient({
381
- http,
382
- url: this.archiveSettings.url,
383
- queryTimeout: this.archiveSettings.requestTimeout,
384
- })
385
- )
386
- }
113
+ type ReqiredFieldSelection = typeof REQUIRED_FIELDS
387
114
 
388
- @def
389
- private getSquidId(): string {
390
- return getOrGenerateSquidId()
391
- }
392
- }
115
+ const REQUIRED_FIELDS = {
116
+ block: {
117
+ number: true,
118
+ hash: true,
119
+ parentHash: true,
120
+ },
121
+ } as const satisfies FieldSelection
package/README.md DELETED
@@ -1,4 +0,0 @@
1
- # @subsquid/solana-stream
2
-
3
- Solana block data source, that allows to request and fetch block data from both Subsquid Network
4
- and traditional RPC endpoint.
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/archive/schema.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAC,cAAc,EAAC,MAAM,eAAe,CAAA;AAG5C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmHxB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/archive/schema.ts"],"names":[],"mappings":"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"}
@@ -1,15 +0,0 @@
1
- import { BlockHeader } from '@subsquid/solana-normalization';
2
- import { Base58Bytes } from '@subsquid/solana-rpc-data';
3
- import { ArchiveClient } from '@subsquid/util-internal-archive-client';
4
- import { RangeRequestList } from '@subsquid/util-internal-range';
5
- import { PartialBlock } from '../data/partial';
6
- import { DataRequest } from '../data/request';
7
- export declare class SolanaArchive {
8
- private client;
9
- constructor(client: ArchiveClient);
10
- getFinalizedHeight(): Promise<number>;
11
- getBlockHash(height: number): Promise<Base58Bytes | undefined>;
12
- getBlockHeader(height: number): Promise<BlockHeader>;
13
- getBlockStream(requests: RangeRequestList<DataRequest>, stopOnHead?: boolean | undefined): AsyncIterable<PartialBlock[]>;
14
- }
15
- //# sourceMappingURL=source.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/archive/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAC,WAAW,EAAC,MAAM,2BAA2B,CAAA;AAErD,OAAO,EAAC,aAAa,EAAC,MAAM,wCAAwC,CAAA;AAEpE,OAAO,EAAoC,gBAAgB,EAAC,MAAM,+BAA+B,CAAA;AAGjG,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAA;AAI3C,qBAAa,aAAa;IACV,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAI/B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAW9D,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAuBnD,cAAc,CAAC,QAAQ,EAAE,gBAAgB,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC,YAAY,EAAE,CAAC;CAkDlI"}
@@ -1,98 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.SolanaArchive = void 0;
7
- const util_internal_1 = require("@subsquid/util-internal");
8
- const util_internal_ingest_tools_1 = require("@subsquid/util-internal-ingest-tools");
9
- const util_internal_range_1 = require("@subsquid/util-internal-range");
10
- const util_internal_validation_1 = require("@subsquid/util-internal-validation");
11
- const assert_1 = __importDefault(require("assert"));
12
- const schema_1 = require("./schema");
13
- class SolanaArchive {
14
- constructor(client) {
15
- this.client = client;
16
- }
17
- getFinalizedHeight() {
18
- return this.client.getHeight();
19
- }
20
- async getBlockHash(height) {
21
- let blocks = await this.client.query({
22
- type: 'solana',
23
- fromBlock: height,
24
- toBlock: height,
25
- includeAllBlocks: true
26
- });
27
- (0, assert_1.default)(blocks.length == 1);
28
- return blocks[0].header.hash;
29
- }
30
- async getBlockHeader(height) {
31
- let blocks = await this.client.query({
32
- type: 'solana',
33
- fromBlock: height,
34
- toBlock: height,
35
- includeAllBlocks: true,
36
- fields: {
37
- block: {
38
- slot: true,
39
- parentSlot: true,
40
- parentHash: true,
41
- timestamp: true
42
- }
43
- }
44
- });
45
- (0, assert_1.default)(blocks.length == 1);
46
- let { number, ...rest } = blocks[0].header;
47
- return {
48
- height: number,
49
- ...rest
50
- };
51
- }
52
- async *getBlockStream(requests, stopOnHead) {
53
- let archiveRequests = (0, util_internal_range_1.mapRangeRequestList)(requests, req => {
54
- let { fields, includeAllBlocks, ...items } = req;
55
- let archiveItems = {};
56
- let key;
57
- for (key in items) {
58
- archiveItems[key] = items[key]?.map(it => ({ ...it.where, ...it.include }));
59
- }
60
- return {
61
- type: 'solana',
62
- fields: {
63
- block: { parentHash: true, ...fields?.block },
64
- transaction: fields?.transaction,
65
- instruction: fields?.instruction,
66
- log: { instructionAddress: true, ...fields?.log },
67
- balance: fields?.balance,
68
- tokenBalance: fields?.tokenBalance,
69
- reward: fields?.reward
70
- },
71
- includeAllBlocks,
72
- ...archiveItems
73
- };
74
- });
75
- for await (let batch of (0, util_internal_ingest_tools_1.archiveIngest)({
76
- client: this.client,
77
- requests: archiveRequests,
78
- stopOnHead
79
- })) {
80
- let req = (0, util_internal_range_1.getRequestAt)(requests, batch.blocks[0].header.number);
81
- let blocks = (0, util_internal_validation_1.cast)((0, util_internal_validation_1.array)((0, schema_1.getDataSchema)((0, util_internal_1.assertNotNull)(req?.fields))), batch.blocks).map(b => {
82
- let { header: { number, ...hdr }, ...items } = b;
83
- return {
84
- header: { height: number, ...hdr },
85
- transactions: items.transactions || [],
86
- instructions: items.instructions || [],
87
- logs: items.logs || [],
88
- balances: items.balances || [],
89
- tokenBalances: items.tokenBalances || [],
90
- rewards: items.rewards || []
91
- };
92
- });
93
- yield blocks;
94
- }
95
- }
96
- }
97
- exports.SolanaArchive = SolanaArchive;
98
- //# sourceMappingURL=source.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/archive/source.ts"],"names":[],"mappings":";;;;;;AAEA,2DAAqD;AAErD,qFAAkE;AAClE,uEAAiG;AACjG,iFAA8D;AAC9D,oDAA2B;AAG3B,qCAAsC;AAGtC,MAAa,aAAa;IACtB,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,kBAAkB;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc;QAC7B,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YACjC,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,MAAM;YACf,gBAAgB,EAAE,IAAI;SACzB,CAAC,CAAA;QACF,IAAA,gBAAM,EAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;QAC1B,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;IAChC,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc;QAC/B,IAAI,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YACjC,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,MAAM;YACjB,OAAO,EAAE,MAAM;YACf,gBAAgB,EAAE,IAAI;YACtB,MAAM,EAAE;gBACJ,KAAK,EAAE;oBACH,IAAI,EAAE,IAAI;oBACV,UAAU,EAAE,IAAI;oBAChB,UAAU,EAAE,IAAI;oBAChB,SAAS,EAAE,IAAI;iBAClB;aACJ;SACJ,CAAC,CAAA;QACF,IAAA,gBAAM,EAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;QAC1B,IAAI,EAAC,MAAM,EAAE,GAAG,IAAI,EAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;QACxC,OAAO;YACH,MAAM,EAAE,MAAM;YACd,GAAG,IAAI;SACK,CAAA;IACpB,CAAC;IAED,KAAK,CAAC,CAAC,cAAc,CAAC,QAAuC,EAAE,UAAgC;QAC3F,IAAI,eAAe,GAAG,IAAA,yCAAmB,EAAC,QAAQ,EAAE,GAAG,CAAC,EAAE;YACtD,IAAI,EAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,KAAK,EAAC,GAAG,GAAG,CAAA;YAC9C,IAAI,YAAY,GAAQ,EAAE,CAAA;YAC1B,IAAI,GAAuB,CAAA;YAC3B,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;gBAChB,YAAY,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAC,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAC,CAAC,CAAC,CAAA;YAC7E,CAAC;YACD,OAAO;gBACH,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE;oBACJ,KAAK,EAAE,EAAC,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,KAAK,EAAC;oBAC3C,WAAW,EAAE,MAAM,EAAE,WAAW;oBAChC,WAAW,EAAE,MAAM,EAAE,WAAW;oBAChC,GAAG,EAAE,EAAC,kBAAkB,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,EAAC;oBAC/C,OAAO,EAAE,MAAM,EAAE,OAAO;oBACxB,YAAY,EAAE,MAAM,EAAE,YAAY;oBAClC,MAAM,EAAE,MAAM,EAAE,MAAM;iBACzB;gBACD,gBAAgB;gBAChB,GAAG,YAAY;aAClB,CAAA;QACL,CAAC,CAAC,CAAA;QAEF,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI,IAAA,0CAAa,EAAC;YAClC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,eAAe;YACzB,UAAU;SACb,CAAC,EAAE,CAAC;YACD,IAAI,GAAG,GAAG,IAAA,kCAAY,EAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAE/D,IAAI,MAAM,GAAG,IAAA,+BAAI,EACb,IAAA,gCAAK,EAAC,IAAA,sBAAa,EAAC,IAAA,6BAAa,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAChD,KAAK,CAAC,MAAM,CACf,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACN,IAAI,EAAC,MAAM,EAAE,EAAC,MAAM,EAAE,GAAG,GAAG,EAAC,EAAE,GAAG,KAAK,EAAC,GAAG,CAAC,CAAA;gBAC5C,OAAO;oBACH,MAAM,EAAE,EAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,EAAC;oBAChC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE;oBACtC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE;oBACtC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;oBACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE;oBAC9B,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,EAAE;oBACxC,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;iBAC/B,CAAA;YACL,CAAC,CAAC,CAAA;YAEF,MAAM,MAAM,CAAA;QAChB,CAAC;IACL,CAAC;CACJ;AA3FD,sCA2FC"}
@@ -1,8 +0,0 @@
1
- import { FieldSelection } from './model';
2
- import { Selector } from './type-util';
3
- /**
4
- * Get effective set of selected fields.
5
- */
6
- export declare function getFields(fields: FieldSelection | undefined): FieldSelection;
7
- export declare function project<T>(fields: Selector<keyof T> | undefined, obj: T): Partial<T>;
8
- //# sourceMappingURL=fields.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/data/fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAC,MAAM,SAAS,CAAA;AACtD,OAAO,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAA;AAGpC;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG,cAAc,CAU5E;AAsBD,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUpF"}