@subsquid/portal-client 0.3.2 → 0.5.0-portal-api.f9b61c
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 +170 -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 +5 -5
- package/src/client.ts +234 -245
- 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,143 @@ 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;
|
|
220
|
+
if (this.isTerminated()) {
|
|
221
|
+
return this.collect();
|
|
250
222
|
}
|
|
251
|
-
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
259
|
-
this.takeFuture.resolve();
|
|
260
|
-
this.readyFuture = (0, util_internal_1.createFuture)();
|
|
261
|
-
this.putFuture = (0, util_internal_1.createFuture)();
|
|
262
|
-
this.takeFuture = (0, util_internal_1.createFuture)();
|
|
263
|
-
this.state = 'pending';
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
this.
|
|
273
|
-
|
|
274
|
-
if (this.buffer == null) {
|
|
275
|
-
this.buffer = { blocks: [], meta: { bytes: 0 } };
|
|
232
|
+
updateHead(head) {
|
|
233
|
+
this.headNumber = head.headNumber;
|
|
234
|
+
this.headUpdated = true;
|
|
235
|
+
if (head.finalizedHeadNumber == null)
|
|
236
|
+
return;
|
|
237
|
+
if (this.finalizedHeadNumber == null || head.finalizedHeadNumber > this.finalizedHeadNumber) {
|
|
238
|
+
this.finalizedHeadNumber = head.finalizedHeadNumber;
|
|
239
|
+
this.finalizedHeadHash = head.finalizedHeadHash;
|
|
276
240
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.
|
|
280
|
-
|
|
281
|
-
if (this.buffer.meta.bytes >= this.minBytes) {
|
|
282
|
-
this._ready('minBytes');
|
|
241
|
+
}
|
|
242
|
+
async put(blocks, bytes) {
|
|
243
|
+
if (this.isTerminated()) {
|
|
244
|
+
throw new Error('Buffer is closed');
|
|
283
245
|
}
|
|
284
|
-
|
|
285
|
-
|
|
246
|
+
this.idleTimer.stop();
|
|
247
|
+
this.blocks.push(...blocks);
|
|
248
|
+
this.bytes += bytes;
|
|
249
|
+
if (this.waitTimeouted || this.bytes >= this.maxBytes) {
|
|
250
|
+
this.flush();
|
|
286
251
|
}
|
|
287
|
-
if (this.
|
|
288
|
-
this.
|
|
252
|
+
if (this.bytes >= this.maxBytes) {
|
|
253
|
+
this.takeMutex.unready();
|
|
254
|
+
await this.takeMutex.wait();
|
|
289
255
|
}
|
|
256
|
+
this.idleTimer.start();
|
|
290
257
|
}
|
|
291
258
|
flush() {
|
|
292
|
-
if (this.
|
|
259
|
+
if (!this.hasData())
|
|
293
260
|
return;
|
|
294
|
-
this.
|
|
261
|
+
this.stopTimers();
|
|
262
|
+
this.putMutex.ready();
|
|
295
263
|
}
|
|
296
264
|
close() {
|
|
297
|
-
if (this.
|
|
265
|
+
if (this.isTerminated())
|
|
298
266
|
return;
|
|
299
267
|
this.state = 'closed';
|
|
300
|
-
this.
|
|
268
|
+
this.stopTimers();
|
|
269
|
+
this.putMutex.ready();
|
|
270
|
+
this.takeMutex.reject(new Error('Buffer closed'));
|
|
271
|
+
this.abortController.abort();
|
|
301
272
|
}
|
|
302
273
|
fail(err) {
|
|
303
|
-
if (this.
|
|
274
|
+
if (this.isTerminated())
|
|
304
275
|
return;
|
|
305
276
|
this.state = 'failed';
|
|
306
277
|
this.error = err;
|
|
307
|
-
this.
|
|
278
|
+
this.stopTimers();
|
|
279
|
+
this.putMutex.ready();
|
|
280
|
+
this.takeMutex.reject(new Error('Buffer closed'));
|
|
281
|
+
this.abortController.abort();
|
|
308
282
|
}
|
|
309
|
-
|
|
283
|
+
[Symbol.asyncIterator]() {
|
|
310
284
|
return {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
this.fail(error);
|
|
326
|
-
throw error;
|
|
327
|
-
},
|
|
328
|
-
};
|
|
285
|
+
next: async () => {
|
|
286
|
+
let value = await this.take();
|
|
287
|
+
if (value == null) {
|
|
288
|
+
return { done: true, value: undefined };
|
|
289
|
+
}
|
|
290
|
+
return { done: false, value };
|
|
291
|
+
},
|
|
292
|
+
return: async () => {
|
|
293
|
+
this.close();
|
|
294
|
+
return { done: true, value: undefined };
|
|
295
|
+
},
|
|
296
|
+
throw: async (error) => {
|
|
297
|
+
this.fail(error);
|
|
298
|
+
throw error;
|
|
329
299
|
},
|
|
330
300
|
};
|
|
331
301
|
}
|
|
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
|
-
}
|
|
302
|
+
hasData() {
|
|
303
|
+
return this.blocks.length > 0 || this.headUpdated;
|
|
345
304
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
305
|
+
isTerminated() {
|
|
306
|
+
return this.state !== 'open';
|
|
307
|
+
}
|
|
308
|
+
isFailed() {
|
|
309
|
+
return this.state === 'failed';
|
|
310
|
+
}
|
|
311
|
+
collect() {
|
|
312
|
+
if (!this.hasData()) {
|
|
313
|
+
if (this.isFailed())
|
|
314
|
+
throw this.error;
|
|
315
|
+
return undefined;
|
|
354
316
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
317
|
+
let result = {
|
|
318
|
+
blocks: this.blocks,
|
|
319
|
+
meta: {
|
|
320
|
+
bytes: this.bytes,
|
|
321
|
+
headNumber: this.headNumber,
|
|
322
|
+
finalizedHeadNumber: this.finalizedHeadNumber,
|
|
323
|
+
finalizedHeadHash: this.finalizedHeadHash,
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
this.blocks = [];
|
|
327
|
+
this.bytes = 0;
|
|
328
|
+
this.headUpdated = false;
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
stopTimers() {
|
|
332
|
+
this.idleTimer.stop();
|
|
333
|
+
this.waitTimer.stop();
|
|
359
334
|
}
|
|
360
335
|
}
|
|
361
336
|
async function* splitLines(chunks) {
|
|
@@ -402,12 +377,19 @@ class LineSplitter {
|
|
|
402
377
|
}
|
|
403
378
|
}
|
|
404
379
|
class ForkException extends Error {
|
|
405
|
-
constructor(
|
|
406
|
-
let
|
|
407
|
-
super(`expected ${
|
|
380
|
+
constructor(blockNumber, parentBlockHash, previousBlocks) {
|
|
381
|
+
let base = (0, util_internal_1.last)(previousBlocks);
|
|
382
|
+
super(`expected block ${blockNumber} to have parent ${base.number}#${parentBlockHash}, ` +
|
|
383
|
+
`but got ${base.number}#${base.hash} as a parent instead`);
|
|
384
|
+
this.blockNumber = blockNumber;
|
|
385
|
+
this.parentBlockHash = parentBlockHash;
|
|
408
386
|
this.previousBlocks = previousBlocks;
|
|
409
|
-
|
|
410
|
-
|
|
387
|
+
}
|
|
388
|
+
get name() {
|
|
389
|
+
return 'ForkException';
|
|
390
|
+
}
|
|
391
|
+
get isSubsquidForkException() {
|
|
392
|
+
return true;
|
|
411
393
|
}
|
|
412
394
|
}
|
|
413
395
|
exports.ForkException = ForkException;
|
|
@@ -418,15 +400,15 @@ function isForkException(err) {
|
|
|
418
400
|
return true;
|
|
419
401
|
return false;
|
|
420
402
|
}
|
|
421
|
-
function
|
|
422
|
-
let finalizedHeadHash = headers.get('
|
|
423
|
-
let finalizedHeadNumber = headers.get('
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
403
|
+
function getPortalStreamHeaders(headers) {
|
|
404
|
+
let finalizedHeadHash = headers.get('x-sqd-finalized-head-hash');
|
|
405
|
+
let finalizedHeadNumber = headers.get('x-sqd-finalized-head-number');
|
|
406
|
+
let headNumber = headers.get('x-sqd-head-number');
|
|
407
|
+
return {
|
|
408
|
+
headNumber: headNumber ? parseInt(headNumber) : undefined,
|
|
409
|
+
finalizedHeadNumber: finalizedHeadNumber ? parseInt(finalizedHeadNumber) : undefined,
|
|
410
|
+
finalizedHeadHash: finalizedHeadHash ?? undefined,
|
|
411
|
+
};
|
|
430
412
|
}
|
|
431
413
|
function isStreamAbortedError(err) {
|
|
432
414
|
if (!(err instanceof Error))
|