@subsquid/portal-client 0.3.2 → 0.4.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/lib/client.d.ts +40 -18
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +166 -188
- package/lib/client.js.map +1 -1
- package/lib/query/common/data.d.ts +21 -0
- package/lib/query/common/data.d.ts.map +1 -0
- package/lib/query/common/data.js +3 -0
- package/lib/query/common/data.js.map +1 -0
- package/lib/query/common/query.d.ts +7 -0
- package/lib/query/common/query.d.ts.map +1 -0
- package/lib/query/common/query.js +3 -0
- package/lib/query/common/query.js.map +1 -0
- package/lib/query/evm/data.d.ts +159 -0
- package/lib/query/evm/data.d.ts.map +1 -0
- package/lib/query/evm/data.js +3 -0
- package/lib/query/evm/data.js.map +1 -0
- package/lib/query/evm/fields.d.ts +50 -0
- package/lib/query/evm/fields.d.ts.map +1 -0
- package/lib/query/evm/fields.js +3 -0
- package/lib/query/evm/fields.js.map +1 -0
- package/lib/query/evm/index.d.ts +4 -0
- package/lib/query/evm/index.d.ts.map +1 -0
- package/lib/query/evm/index.js +7 -0
- package/lib/query/evm/index.js.map +1 -0
- package/lib/query/evm/query.d.ts +54 -0
- package/lib/query/evm/query.d.ts.map +1 -0
- package/lib/query/evm/query.js +3 -0
- package/lib/query/evm/query.js.map +1 -0
- package/lib/query/evm/schema.d.ts +322 -0
- package/lib/query/evm/schema.d.ts.map +1 -0
- package/lib/query/evm/schema.js +224 -0
- package/lib/query/evm/schema.js.map +1 -0
- package/lib/query/index.d.ts +576 -8
- package/lib/query/index.d.ts.map +1 -1
- package/lib/query/index.js +15 -24
- package/lib/query/index.js.map +1 -1
- package/lib/query/solana/data.d.ts +115 -0
- package/lib/query/solana/data.d.ts.map +1 -0
- package/lib/query/solana/data.js +3 -0
- package/lib/query/solana/data.js.map +1 -0
- package/lib/query/solana/fields.d.ts +31 -0
- package/lib/query/solana/fields.d.ts.map +1 -0
- package/lib/query/solana/fields.js +3 -0
- package/lib/query/solana/fields.js.map +1 -0
- package/lib/query/solana/index.d.ts +4 -0
- package/lib/query/solana/index.d.ts.map +1 -0
- package/lib/query/solana/index.js +7 -0
- package/lib/query/solana/index.js.map +1 -0
- package/lib/query/solana/query.d.ts +74 -0
- package/lib/query/solana/query.d.ts.map +1 -0
- package/lib/query/solana/query.js +3 -0
- package/lib/query/solana/query.js.map +1 -0
- package/lib/query/solana/schema.d.ts +160 -0
- package/lib/query/solana/schema.d.ts.map +1 -0
- package/lib/query/solana/schema.js +130 -0
- package/lib/query/solana/schema.js.map +1 -0
- package/lib/query/substrate/data.d.ts +98 -0
- package/lib/query/substrate/data.d.ts.map +1 -0
- package/lib/query/substrate/data.js +3 -0
- package/lib/query/substrate/data.js.map +1 -0
- package/lib/query/substrate/fields.d.ts +22 -0
- package/lib/query/substrate/fields.d.ts.map +1 -0
- package/lib/query/substrate/fields.js +3 -0
- package/lib/query/substrate/fields.js.map +1 -0
- package/lib/query/substrate/index.d.ts +4 -0
- package/lib/query/substrate/index.d.ts.map +1 -0
- package/lib/query/substrate/index.js +7 -0
- package/lib/query/substrate/index.js.map +1 -0
- package/lib/query/substrate/query.d.ts +50 -0
- package/lib/query/substrate/query.d.ts.map +1 -0
- package/lib/query/substrate/query.js +3 -0
- package/lib/query/substrate/query.js.map +1 -0
- package/lib/query/substrate/schema.d.ts +102 -0
- package/lib/query/substrate/schema.d.ts.map +1 -0
- package/lib/query/substrate/schema.js +88 -0
- package/lib/query/substrate/schema.js.map +1 -0
- package/lib/query/type-util.d.ts +13 -0
- package/lib/query/type-util.d.ts.map +1 -0
- package/lib/query/type-util.js +3 -0
- package/lib/query/type-util.js.map +1 -0
- package/lib/query/util.d.ts +5 -0
- package/lib/query/util.d.ts.map +1 -0
- package/lib/query/util.js +23 -0
- package/lib/query/util.js.map +1 -0
- package/lib/util.d.ts +19 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +57 -0
- package/lib/util.js.map +1 -0
- package/package.json +3 -3
- package/src/client.ts +231 -247
- package/src/query/common/data.ts +24 -0
- package/src/query/common/query.ts +6 -0
- package/src/query/evm/data.ts +182 -0
- package/src/query/evm/fields.ts +105 -0
- package/src/query/evm/index.ts +3 -0
- package/src/query/evm/query.ts +59 -0
- package/src/query/evm/schema.ts +277 -0
- package/src/query/index.ts +19 -36
- package/src/query/solana/data.ts +132 -0
- package/src/query/solana/fields.ts +42 -0
- package/src/query/solana/index.ts +3 -0
- package/src/query/solana/query.ts +89 -0
- package/src/query/solana/schema.ts +164 -0
- package/src/query/substrate/data.ts +101 -0
- package/src/query/substrate/fields.ts +30 -0
- package/src/query/substrate/index.ts +3 -0
- package/src/query/substrate/query.ts +60 -0
- package/src/query/substrate/schema.ts +114 -0
- package/src/query/type-util.ts +25 -0
- package/src/query/util.ts +23 -0
- package/src/util.ts +56 -0
- package/lib/query/common.d.ts +0 -56
- package/lib/query/common.d.ts.map +0 -1
- package/lib/query/common.js +0 -16
- package/lib/query/common.js.map +0 -1
- package/lib/query/evm.d.ts +0 -267
- package/lib/query/evm.d.ts.map +0 -1
- package/lib/query/evm.js +0 -245
- package/lib/query/evm.js.map +0 -1
- package/lib/query/solana.d.ts +0 -224
- package/lib/query/solana.d.ts.map +0 -1
- package/lib/query/solana.js +0 -121
- package/lib/query/solana.js.map +0 -1
- package/lib/query/substrate.d.ts +0 -173
- package/lib/query/substrate.d.ts.map +0 -1
- package/lib/query/substrate.js +0 -71
- package/lib/query/substrate.js.map +0 -1
- package/src/query/common.ts +0 -83
- package/src/query/evm.ts +0 -677
- package/src/query/solana.ts +0 -438
- package/src/query/substrate.ts +0 -288
package/lib/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpClient, HttpClientOptions } from '@subsquid/http-client';
|
|
2
|
-
import {
|
|
2
|
+
import { type AnyQuery, type GetQueryBlock } from './query';
|
|
3
3
|
export * from './query';
|
|
4
4
|
export interface PortalClientOptions {
|
|
5
5
|
/**
|
|
@@ -12,17 +12,17 @@ export interface PortalClientOptions {
|
|
|
12
12
|
http?: HttpClient | HttpClientOptions;
|
|
13
13
|
/**
|
|
14
14
|
* Minimum number of bytes to return.
|
|
15
|
-
* @
|
|
15
|
+
* @deprecated not used
|
|
16
16
|
*/
|
|
17
17
|
minBytes?: number;
|
|
18
18
|
/**
|
|
19
19
|
* Maximum number of bytes to return.
|
|
20
|
-
* @default
|
|
20
|
+
* @default 52_428_800 (50MB)
|
|
21
21
|
*/
|
|
22
22
|
maxBytes?: number;
|
|
23
23
|
/**
|
|
24
24
|
* Maximum time between stream data in milliseconds for return.
|
|
25
|
-
* @default
|
|
25
|
+
* @default 500
|
|
26
26
|
*/
|
|
27
27
|
maxIdleTime?: number;
|
|
28
28
|
/**
|
|
@@ -46,16 +46,34 @@ export interface PortalRequestOptions {
|
|
|
46
46
|
}
|
|
47
47
|
export interface PortalStreamOptions {
|
|
48
48
|
request?: Omit<PortalRequestOptions, 'abort'>;
|
|
49
|
-
minBytes?: number;
|
|
50
49
|
maxBytes?: number;
|
|
51
50
|
maxIdleTime?: number;
|
|
52
51
|
maxWaitTime?: number;
|
|
53
52
|
headPollInterval?: number;
|
|
54
53
|
}
|
|
54
|
+
export interface PortalStreamBaseResponse {
|
|
55
|
+
headNumber?: number;
|
|
56
|
+
finalizedHeadNumber?: number;
|
|
57
|
+
finalizedHeadHash?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface PortalStreamDataResponse extends PortalStreamBaseResponse {
|
|
60
|
+
type: 'data';
|
|
61
|
+
data: AsyncIterable<Uint8Array> | null;
|
|
62
|
+
}
|
|
63
|
+
export interface PortalStreamNoDataResponse extends PortalStreamBaseResponse {
|
|
64
|
+
type: 'no-data';
|
|
65
|
+
}
|
|
66
|
+
export interface PortalStreamForkResponse extends PortalStreamBaseResponse {
|
|
67
|
+
type: 'fork';
|
|
68
|
+
previousBlocks: BlockRef[];
|
|
69
|
+
}
|
|
70
|
+
export type PortalStreamResponse = PortalStreamDataResponse | PortalStreamNoDataResponse | PortalStreamForkResponse;
|
|
55
71
|
export type PortalStreamData<B> = {
|
|
56
72
|
blocks: B[];
|
|
57
|
-
finalizedHead?: BlockRef;
|
|
58
73
|
meta: {
|
|
74
|
+
finalizedHeadNumber?: number;
|
|
75
|
+
finalizedHeadHash?: string;
|
|
76
|
+
headNumber?: number;
|
|
59
77
|
bytes: number;
|
|
60
78
|
};
|
|
61
79
|
};
|
|
@@ -69,31 +87,35 @@ export declare class PortalClient {
|
|
|
69
87
|
private url;
|
|
70
88
|
private client;
|
|
71
89
|
private headPollInterval;
|
|
72
|
-
private minBytes;
|
|
73
90
|
private maxBytes;
|
|
74
91
|
private maxIdleTime;
|
|
75
92
|
private maxWaitTime;
|
|
76
93
|
constructor(options: PortalClientOptions);
|
|
77
94
|
private getDatasetUrl;
|
|
78
|
-
getHead(options?: PortalRequestOptions): Promise<BlockRef | undefined>;
|
|
95
|
+
getHead(options?: PortalRequestOptions, finalized?: boolean): Promise<BlockRef | undefined>;
|
|
79
96
|
getFinalizedHead(options?: PortalRequestOptions): Promise<BlockRef | undefined>;
|
|
80
97
|
/**
|
|
81
|
-
*
|
|
98
|
+
* Waits until the finalized head reaches or exceeds the specified block number.
|
|
99
|
+
* @param blockNumber - The block number to wait for finalization
|
|
100
|
+
* @param options - Request options including abort signal and poll interval
|
|
101
|
+
* @returns The finalized head once it reaches the target block number
|
|
82
102
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
103
|
+
waitForFinalization(blockNumber: number, options?: PortalRequestOptions & {
|
|
104
|
+
pollInterval?: number;
|
|
105
|
+
}): Promise<BlockRef>;
|
|
106
|
+
getStream<Q extends AnyQuery>(query: Q, options?: PortalStreamOptions, finalized?: boolean): PortalStream<GetQueryBlock<Q>>;
|
|
107
|
+
getFinalizedStream<Q extends AnyQuery>(query: Q, options?: PortalStreamOptions): PortalStream<GetQueryBlock<Q>>;
|
|
88
108
|
private getStreamOptions;
|
|
89
109
|
private getStreamRequest;
|
|
90
110
|
private request;
|
|
91
111
|
}
|
|
92
112
|
export declare class ForkException extends Error {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
constructor(
|
|
113
|
+
blockNumber: number;
|
|
114
|
+
parentBlockHash: string;
|
|
115
|
+
previousBlocks: BlockRef[];
|
|
116
|
+
constructor(blockNumber: number, parentBlockHash: string, previousBlocks: BlockRef[]);
|
|
117
|
+
get name(): string;
|
|
118
|
+
get isSubsquidForkException(): true;
|
|
97
119
|
}
|
|
98
120
|
export declare function isForkException(err: unknown): err is ForkException;
|
|
99
121
|
//# sourceMappingURL=client.d.ts.map
|
package/lib/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAE,iBAAiB,EAA0C,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/lib/client.js
CHANGED
|
@@ -18,8 +18,9 @@ exports.ForkException = exports.PortalClient = void 0;
|
|
|
18
18
|
exports.isForkException = isForkException;
|
|
19
19
|
const http_client_1 = require("@subsquid/http-client");
|
|
20
20
|
const util_internal_1 = require("@subsquid/util-internal");
|
|
21
|
-
const query_1 = require("./query");
|
|
22
21
|
const util_internal_validation_1 = require("@subsquid/util-internal-validation");
|
|
22
|
+
const util_1 = require("./util");
|
|
23
|
+
const query_1 = require("./query");
|
|
23
24
|
__exportStar(require("./query"), exports);
|
|
24
25
|
const USER_AGENT = `@subsquid/portal-client (https://sqd.ai)`;
|
|
25
26
|
class PortalClient {
|
|
@@ -27,9 +28,8 @@ class PortalClient {
|
|
|
27
28
|
this.url = new URL(options.url);
|
|
28
29
|
this.client = options.http instanceof http_client_1.HttpClient ? options.http : new http_client_1.HttpClient(options.http);
|
|
29
30
|
this.headPollInterval = options.headPollInterval ?? 0;
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
this.maxIdleTime = options.maxIdleTime ?? 300;
|
|
31
|
+
this.maxBytes = options.maxBytes ?? 50 * 1024 * 1024;
|
|
32
|
+
this.maxIdleTime = options.maxIdleTime ?? 500;
|
|
33
33
|
this.maxWaitTime = options.maxWaitTime ?? 5000;
|
|
34
34
|
}
|
|
35
35
|
getDatasetUrl(path) {
|
|
@@ -42,69 +42,40 @@ class PortalClient {
|
|
|
42
42
|
}
|
|
43
43
|
return u.toString();
|
|
44
44
|
}
|
|
45
|
-
async getHead(options) {
|
|
46
|
-
const res = await this.request('GET', this.getDatasetUrl('head'), options);
|
|
45
|
+
async getHead(options, finalized) {
|
|
46
|
+
const res = await this.request('GET', this.getDatasetUrl(!finalized ? 'head' : 'finalized-head'), options);
|
|
47
47
|
return res.body ?? undefined;
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return res.body ?? undefined;
|
|
49
|
+
getFinalizedHead(options) {
|
|
50
|
+
return this.getHead(options, true);
|
|
52
51
|
}
|
|
53
52
|
/**
|
|
54
|
-
*
|
|
53
|
+
* Waits until the finalized head reaches or exceeds the specified block number.
|
|
54
|
+
* @param blockNumber - The block number to wait for finalization
|
|
55
|
+
* @param options - Request options including abort signal and poll interval
|
|
56
|
+
* @returns The finalized head once it reaches the target block number
|
|
55
57
|
*/
|
|
56
|
-
async
|
|
57
|
-
let {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
})
|
|
67
|
-
.catch((0, util_internal_1.withErrorContext)({
|
|
68
|
-
archiveQuery: query,
|
|
69
|
-
}))
|
|
70
|
-
.then((res) => {
|
|
71
|
-
let blocks = res.body
|
|
72
|
-
.toString('utf8')
|
|
73
|
-
.trimEnd()
|
|
74
|
-
.split('\n')
|
|
75
|
-
.map((line) => JSON.parse(line));
|
|
76
|
-
return blocks;
|
|
77
|
-
});
|
|
58
|
+
async waitForFinalization(blockNumber, options) {
|
|
59
|
+
let { pollInterval = this.headPollInterval || 1000, ...requestOptions } = options ?? {};
|
|
60
|
+
while (true) {
|
|
61
|
+
options?.abort?.throwIfAborted();
|
|
62
|
+
let head = await this.getFinalizedHead(requestOptions);
|
|
63
|
+
if (head && head.number >= blockNumber) {
|
|
64
|
+
return head;
|
|
65
|
+
}
|
|
66
|
+
await (0, util_internal_1.wait)(pollInterval, options?.abort);
|
|
67
|
+
}
|
|
78
68
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return this.request('POST', this.getDatasetUrl(`stream`), {
|
|
82
|
-
...options,
|
|
83
|
-
json: query,
|
|
84
|
-
})
|
|
85
|
-
.catch((0, util_internal_1.withErrorContext)({
|
|
86
|
-
archiveQuery: query,
|
|
87
|
-
}))
|
|
88
|
-
.then((res) => {
|
|
89
|
-
let blocks = res.body
|
|
90
|
-
.toString('utf8')
|
|
91
|
-
.trimEnd()
|
|
92
|
-
.split('\n')
|
|
93
|
-
.map((line) => JSON.parse(line));
|
|
94
|
-
return blocks;
|
|
95
|
-
});
|
|
69
|
+
getStream(query, options, finalized) {
|
|
70
|
+
return createPortalStream(query, this.getStreamOptions(options), async (q, o) => this.getStreamRequest(!finalized ? 'stream' : 'finalized-stream', q, o));
|
|
96
71
|
}
|
|
97
72
|
getFinalizedStream(query, options) {
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
getStream(query, options) {
|
|
101
|
-
return createPortalStream(query, this.getStreamOptions(options), async (q, o) => this.getStreamRequest('stream', q, o));
|
|
73
|
+
return this.getStream(query, options, true);
|
|
102
74
|
}
|
|
103
75
|
getStreamOptions(options) {
|
|
104
|
-
let { headPollInterval = this.headPollInterval,
|
|
76
|
+
let { headPollInterval = this.headPollInterval, maxBytes = this.maxBytes, maxIdleTime = this.maxIdleTime, maxWaitTime = this.maxWaitTime, request = {}, } = options ?? {};
|
|
105
77
|
return {
|
|
106
78
|
headPollInterval,
|
|
107
|
-
minBytes,
|
|
108
79
|
maxBytes,
|
|
109
80
|
maxIdleTime,
|
|
110
81
|
maxWaitTime,
|
|
@@ -120,28 +91,29 @@ class PortalClient {
|
|
|
120
91
|
}).catch((0, util_internal_1.withErrorContext)({
|
|
121
92
|
query: query,
|
|
122
93
|
}));
|
|
94
|
+
let headers = getPortalStreamHeaders(res.headers);
|
|
123
95
|
switch (res.status) {
|
|
124
96
|
case 200:
|
|
125
|
-
let finalizedHead = getFinalizedHeadHeader(res.headers);
|
|
126
|
-
let stream = res.body ? splitLines(res.body) : undefined;
|
|
127
97
|
return {
|
|
128
|
-
|
|
129
|
-
|
|
98
|
+
...headers,
|
|
99
|
+
type: 'data',
|
|
100
|
+
data: res.body ?? null,
|
|
130
101
|
};
|
|
131
102
|
case 204:
|
|
132
103
|
return {
|
|
133
|
-
|
|
104
|
+
...headers,
|
|
105
|
+
type: 'no-data',
|
|
134
106
|
};
|
|
135
107
|
default:
|
|
136
108
|
throw (0, util_internal_1.unexpectedCase)(res.status);
|
|
137
109
|
}
|
|
138
110
|
}
|
|
139
111
|
catch (e) {
|
|
140
|
-
if (isForkHttpError(e)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
112
|
+
if (isForkHttpError(e)) {
|
|
113
|
+
return {
|
|
114
|
+
type: 'fork',
|
|
115
|
+
previousBlocks: e.response.body.previousBlocks,
|
|
116
|
+
};
|
|
145
117
|
}
|
|
146
118
|
throw (0, util_internal_1.addErrorContext)(e, {
|
|
147
119
|
query,
|
|
@@ -171,35 +143,35 @@ function isForkHttpError(err) {
|
|
|
171
143
|
function createPortalStream(query, options, requestStream) {
|
|
172
144
|
let { headPollInterval, request, ...bufferOptions } = options;
|
|
173
145
|
let buffer = new PortalStreamBuffer(bufferOptions);
|
|
174
|
-
let schema = (0, query_1.
|
|
175
|
-
let { fromBlock = 0, toBlock, parentBlockHash } =
|
|
146
|
+
let [normalizedQuery, schema] = (0, query_1.getQuery)(query);
|
|
147
|
+
let { fromBlock = 0, toBlock, parentBlockHash } = normalizedQuery;
|
|
176
148
|
const ingest = async () => {
|
|
177
149
|
while (!buffer.signal.aborted) {
|
|
178
150
|
if (toBlock != null && fromBlock > toBlock)
|
|
179
151
|
break;
|
|
180
152
|
let res = await requestStream({
|
|
181
|
-
...
|
|
153
|
+
...normalizedQuery,
|
|
182
154
|
fromBlock,
|
|
183
155
|
parentBlockHash,
|
|
184
156
|
}, {
|
|
185
157
|
...request,
|
|
186
158
|
abort: buffer.signal,
|
|
187
159
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
160
|
+
if (res.type === 'fork') {
|
|
161
|
+
throw new ForkException(fromBlock, parentBlockHash, res.previousBlocks);
|
|
162
|
+
}
|
|
163
|
+
buffer.updateHead(res);
|
|
164
|
+
if (res.type === 'no-data') {
|
|
192
165
|
buffer.flush();
|
|
193
166
|
if (headPollInterval > 0) {
|
|
194
167
|
await (0, util_internal_1.wait)(headPollInterval, buffer.signal);
|
|
195
168
|
}
|
|
196
169
|
continue;
|
|
197
170
|
}
|
|
198
|
-
|
|
199
|
-
if (res.stream == null)
|
|
171
|
+
if (!res.data)
|
|
200
172
|
break;
|
|
201
173
|
try {
|
|
202
|
-
for await (let data of res.
|
|
174
|
+
for await (let data of splitLines(res.data)) {
|
|
203
175
|
buffer.signal.throwIfAborted();
|
|
204
176
|
let blocks = [];
|
|
205
177
|
let bytes = 0;
|
|
@@ -210,8 +182,9 @@ function createPortalStream(query, options, requestStream) {
|
|
|
210
182
|
fromBlock = block.header.number + 1;
|
|
211
183
|
parentBlockHash = block.header.hash;
|
|
212
184
|
}
|
|
213
|
-
await buffer.put(
|
|
185
|
+
await buffer.put(blocks, bytes);
|
|
214
186
|
}
|
|
187
|
+
buffer.flush();
|
|
215
188
|
}
|
|
216
189
|
catch (err) {
|
|
217
190
|
if (buffer.signal.aborted)
|
|
@@ -221,141 +194,139 @@ function createPortalStream(query, options, requestStream) {
|
|
|
221
194
|
}
|
|
222
195
|
}
|
|
223
196
|
}
|
|
197
|
+
buffer.flush();
|
|
224
198
|
};
|
|
225
199
|
ingest().then(() => buffer.close(), (err) => buffer.fail(err));
|
|
226
|
-
return buffer
|
|
200
|
+
return buffer;
|
|
227
201
|
}
|
|
228
202
|
class PortalStreamBuffer {
|
|
229
203
|
get signal() {
|
|
230
204
|
return this.abortController.signal;
|
|
231
205
|
}
|
|
232
206
|
constructor(options) {
|
|
233
|
-
this.
|
|
234
|
-
this.
|
|
235
|
-
this.
|
|
236
|
-
this.
|
|
207
|
+
this.blocks = [];
|
|
208
|
+
this.bytes = 0;
|
|
209
|
+
this.headUpdated = false;
|
|
210
|
+
this.state = 'open';
|
|
211
|
+
this.waitTimeouted = false;
|
|
212
|
+
this.putMutex = new util_1.Semaphore(false);
|
|
213
|
+
this.takeMutex = new util_1.Semaphore(true);
|
|
237
214
|
this.abortController = new AbortController();
|
|
238
|
-
this.
|
|
239
|
-
this.
|
|
240
|
-
this.
|
|
241
|
-
this.maxIdleTime = options.maxIdleTime;
|
|
215
|
+
this.maxBytes = options.maxBytes;
|
|
216
|
+
this.idleTimer = new util_1.Timer(options.maxIdleTime, () => this.flush());
|
|
217
|
+
this.waitTimer = new util_1.Timer(options.maxWaitTime, () => (this.waitTimeouted = true));
|
|
242
218
|
}
|
|
243
219
|
async take() {
|
|
244
|
-
if (this.
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
await Promise.all([this.readyFuture.promise(), this.putFuture.promise()]);
|
|
248
|
-
if (this.state === 'failed') {
|
|
249
|
-
throw this.error;
|
|
250
|
-
}
|
|
251
|
-
let result = this.buffer;
|
|
252
|
-
this.buffer = undefined;
|
|
253
|
-
if (this.state === 'closed') {
|
|
254
|
-
return result;
|
|
255
|
-
}
|
|
256
|
-
if (result == null) {
|
|
257
|
-
throw new Error('Buffer is empty');
|
|
220
|
+
if (this.isTerminated()) {
|
|
221
|
+
return this.collect();
|
|
258
222
|
}
|
|
259
|
-
this.
|
|
260
|
-
this.
|
|
261
|
-
this.
|
|
262
|
-
|
|
263
|
-
this.
|
|
223
|
+
this.waitTimer.start();
|
|
224
|
+
await this.putMutex.wait();
|
|
225
|
+
this.waitTimer.stop();
|
|
226
|
+
let result = this.collect();
|
|
227
|
+
this.putMutex.unready();
|
|
228
|
+
this.takeMutex.ready();
|
|
229
|
+
this.waitTimeouted = false;
|
|
264
230
|
return result;
|
|
265
231
|
}
|
|
266
|
-
|
|
267
|
-
|
|
232
|
+
updateHead(head) {
|
|
233
|
+
this.headNumber = head.headNumber;
|
|
234
|
+
this.finalizedHeadNumber = head.finalizedHeadNumber;
|
|
235
|
+
this.finalizedHeadHash = head.finalizedHeadHash;
|
|
236
|
+
this.headUpdated = true;
|
|
237
|
+
}
|
|
238
|
+
async put(blocks, bytes) {
|
|
239
|
+
if (this.isTerminated()) {
|
|
268
240
|
throw new Error('Buffer is closed');
|
|
269
241
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.buffer = { blocks: [], meta: { bytes: 0 } };
|
|
276
|
-
}
|
|
277
|
-
this.buffer.blocks.push(...data.blocks);
|
|
278
|
-
this.buffer.finalizedHead = data.finalizedHead;
|
|
279
|
-
this.buffer.meta.bytes += data.meta.bytes;
|
|
280
|
-
this.putFuture.resolve();
|
|
281
|
-
if (this.buffer.meta.bytes >= this.minBytes) {
|
|
282
|
-
this._ready('minBytes');
|
|
242
|
+
this.idleTimer.stop();
|
|
243
|
+
this.blocks.push(...blocks);
|
|
244
|
+
this.bytes += bytes;
|
|
245
|
+
if (this.waitTimeouted || this.bytes >= this.maxBytes) {
|
|
246
|
+
this.flush();
|
|
283
247
|
}
|
|
284
|
-
if (this.
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (this.state === 'pending') {
|
|
288
|
-
this.idleTimeout = setTimeout(() => this._ready('idle'), this.maxIdleTime);
|
|
248
|
+
if (this.bytes >= this.maxBytes) {
|
|
249
|
+
this.takeMutex.unready();
|
|
250
|
+
await this.takeMutex.wait();
|
|
289
251
|
}
|
|
252
|
+
this.idleTimer.start();
|
|
290
253
|
}
|
|
291
254
|
flush() {
|
|
292
|
-
if (this.
|
|
255
|
+
if (!this.hasData())
|
|
293
256
|
return;
|
|
294
|
-
this.
|
|
257
|
+
this.stopTimers();
|
|
258
|
+
this.putMutex.ready();
|
|
295
259
|
}
|
|
296
260
|
close() {
|
|
297
|
-
if (this.
|
|
261
|
+
if (this.isTerminated())
|
|
298
262
|
return;
|
|
299
263
|
this.state = 'closed';
|
|
300
|
-
this.
|
|
264
|
+
this.stopTimers();
|
|
265
|
+
this.putMutex.ready();
|
|
266
|
+
this.takeMutex.reject(new Error('Buffer closed'));
|
|
267
|
+
this.abortController.abort();
|
|
301
268
|
}
|
|
302
269
|
fail(err) {
|
|
303
|
-
if (this.
|
|
270
|
+
if (this.isTerminated())
|
|
304
271
|
return;
|
|
305
272
|
this.state = 'failed';
|
|
306
273
|
this.error = err;
|
|
307
|
-
this.
|
|
274
|
+
this.stopTimers();
|
|
275
|
+
this.putMutex.ready();
|
|
276
|
+
this.takeMutex.reject(new Error('Buffer closed'));
|
|
277
|
+
this.abortController.abort();
|
|
308
278
|
}
|
|
309
|
-
|
|
279
|
+
[Symbol.asyncIterator]() {
|
|
310
280
|
return {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.fail(error);
|
|
326
|
-
throw error;
|
|
327
|
-
},
|
|
328
|
-
};
|
|
281
|
+
next: async () => {
|
|
282
|
+
let value = await this.take();
|
|
283
|
+
if (value == null) {
|
|
284
|
+
return { done: true, value: undefined };
|
|
285
|
+
}
|
|
286
|
+
return { done: false, value };
|
|
287
|
+
},
|
|
288
|
+
return: async () => {
|
|
289
|
+
this.close();
|
|
290
|
+
return { done: true, value: undefined };
|
|
291
|
+
},
|
|
292
|
+
throw: async (error) => {
|
|
293
|
+
this.fail(error);
|
|
294
|
+
throw error;
|
|
329
295
|
},
|
|
330
296
|
};
|
|
331
297
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
this.state = 'ready';
|
|
335
|
-
this.readyFuture.resolve();
|
|
336
|
-
}
|
|
337
|
-
if (this.idleTimeout != null) {
|
|
338
|
-
clearTimeout(this.idleTimeout);
|
|
339
|
-
this.idleTimeout = undefined;
|
|
340
|
-
}
|
|
341
|
-
if (this.waitTimeout != null) {
|
|
342
|
-
clearTimeout(this.waitTimeout);
|
|
343
|
-
this.waitTimeout = undefined;
|
|
344
|
-
}
|
|
298
|
+
hasData() {
|
|
299
|
+
return this.blocks.length > 0 || this.headUpdated;
|
|
345
300
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
301
|
+
isTerminated() {
|
|
302
|
+
return this.state !== 'open';
|
|
303
|
+
}
|
|
304
|
+
isFailed() {
|
|
305
|
+
return this.state === 'failed';
|
|
306
|
+
}
|
|
307
|
+
collect() {
|
|
308
|
+
if (!this.hasData()) {
|
|
309
|
+
if (this.isFailed())
|
|
310
|
+
throw this.error;
|
|
311
|
+
return undefined;
|
|
354
312
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
313
|
+
let result = {
|
|
314
|
+
blocks: this.blocks,
|
|
315
|
+
meta: {
|
|
316
|
+
bytes: this.bytes,
|
|
317
|
+
headNumber: this.headNumber,
|
|
318
|
+
finalizedHeadNumber: this.finalizedHeadNumber,
|
|
319
|
+
finalizedHeadHash: this.finalizedHeadHash,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
this.blocks = [];
|
|
323
|
+
this.bytes = 0;
|
|
324
|
+
this.headUpdated = false;
|
|
325
|
+
return result;
|
|
326
|
+
}
|
|
327
|
+
stopTimers() {
|
|
328
|
+
this.idleTimer.stop();
|
|
329
|
+
this.waitTimer.stop();
|
|
359
330
|
}
|
|
360
331
|
}
|
|
361
332
|
async function* splitLines(chunks) {
|
|
@@ -402,12 +373,19 @@ class LineSplitter {
|
|
|
402
373
|
}
|
|
403
374
|
}
|
|
404
375
|
class ForkException extends Error {
|
|
405
|
-
constructor(
|
|
406
|
-
let
|
|
407
|
-
super(`expected ${
|
|
376
|
+
constructor(blockNumber, parentBlockHash, previousBlocks) {
|
|
377
|
+
let base = (0, util_internal_1.last)(previousBlocks);
|
|
378
|
+
super(`expected block ${blockNumber} to have parent ${base.number}#${parentBlockHash}, ` +
|
|
379
|
+
`but got ${base.number}#${base.hash} as a parent instead`);
|
|
380
|
+
this.blockNumber = blockNumber;
|
|
381
|
+
this.parentBlockHash = parentBlockHash;
|
|
408
382
|
this.previousBlocks = previousBlocks;
|
|
409
|
-
|
|
410
|
-
|
|
383
|
+
}
|
|
384
|
+
get name() {
|
|
385
|
+
return 'ForkException';
|
|
386
|
+
}
|
|
387
|
+
get isSubsquidForkException() {
|
|
388
|
+
return true;
|
|
411
389
|
}
|
|
412
390
|
}
|
|
413
391
|
exports.ForkException = ForkException;
|
|
@@ -418,15 +396,15 @@ function isForkException(err) {
|
|
|
418
396
|
return true;
|
|
419
397
|
return false;
|
|
420
398
|
}
|
|
421
|
-
function
|
|
422
|
-
let finalizedHeadHash = headers.get('
|
|
423
|
-
let finalizedHeadNumber = headers.get('
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
399
|
+
function getPortalStreamHeaders(headers) {
|
|
400
|
+
let finalizedHeadHash = headers.get('x-sqd-finalized-head-hash');
|
|
401
|
+
let finalizedHeadNumber = headers.get('x-sqd-finalized-head-number');
|
|
402
|
+
let headNumber = headers.get('x-sqd-head-number');
|
|
403
|
+
return {
|
|
404
|
+
headNumber: headNumber ? parseInt(headNumber) : undefined,
|
|
405
|
+
finalizedHeadNumber: finalizedHeadNumber ? parseInt(finalizedHeadNumber) : undefined,
|
|
406
|
+
finalizedHeadHash: finalizedHeadHash ?? undefined,
|
|
407
|
+
};
|
|
430
408
|
}
|
|
431
409
|
function isStreamAbortedError(err) {
|
|
432
410
|
if (!(err instanceof Error))
|