@secondlayer/sdk 3.3.1 → 3.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/README.md +101 -0
- package/dist/index.d.ts +270 -1
- package/dist/index.js +481 -1
- package/dist/index.js.map +11 -4
- package/dist/streams/index.d.ts +183 -0
- package/dist/streams/index.js +378 -0
- package/dist/streams/index.js.map +15 -0
- package/dist/subgraphs/index.d.ts +87 -0
- package/dist/subgraphs/index.js +108 -1
- package/dist/subgraphs/index.js.map +5 -4
- package/package.json +7 -3
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// src/streams/consumer.ts
|
|
2
|
+
async function defaultSleep(ms, signal) {
|
|
3
|
+
if (signal?.aborted)
|
|
4
|
+
return;
|
|
5
|
+
await new Promise((resolve) => {
|
|
6
|
+
const timeout = setTimeout(resolve, ms);
|
|
7
|
+
if (!signal)
|
|
8
|
+
return;
|
|
9
|
+
signal.addEventListener("abort", () => {
|
|
10
|
+
clearTimeout(timeout);
|
|
11
|
+
resolve();
|
|
12
|
+
}, { once: true });
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
async function consumeStreamsEvents(opts) {
|
|
16
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
17
|
+
const mode = opts.mode ?? "tail";
|
|
18
|
+
const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
|
|
19
|
+
const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
|
|
20
|
+
const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
|
|
21
|
+
let cursor = opts.fromCursor ?? null;
|
|
22
|
+
let pages = 0;
|
|
23
|
+
let emptyPolls = 0;
|
|
24
|
+
while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
|
|
25
|
+
const envelope = await opts.fetchEvents({
|
|
26
|
+
cursor,
|
|
27
|
+
limit: opts.batchSize,
|
|
28
|
+
types: opts.types
|
|
29
|
+
});
|
|
30
|
+
pages++;
|
|
31
|
+
const returnedCursor = await opts.onBatch(envelope.events, envelope);
|
|
32
|
+
const nextCursor = returnedCursor ?? envelope.next_cursor;
|
|
33
|
+
if (nextCursor && nextCursor !== cursor) {
|
|
34
|
+
cursor = nextCursor;
|
|
35
|
+
emptyPolls = 0;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (envelope.events.length === 0) {
|
|
39
|
+
emptyPolls++;
|
|
40
|
+
if (mode === "bounded") {
|
|
41
|
+
return { cursor, pages, emptyPolls };
|
|
42
|
+
}
|
|
43
|
+
await sleep(emptyBackoffMs, opts.signal);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
return { cursor, pages, emptyPolls };
|
|
47
|
+
}
|
|
48
|
+
return { cursor, pages, emptyPolls };
|
|
49
|
+
}
|
|
50
|
+
async function* streamStreamsEvents(opts) {
|
|
51
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
52
|
+
const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
|
|
53
|
+
const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
|
|
54
|
+
const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
|
|
55
|
+
let cursor = opts.fromCursor ?? null;
|
|
56
|
+
let pages = 0;
|
|
57
|
+
let emptyPolls = 0;
|
|
58
|
+
while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
|
|
59
|
+
const envelope = await opts.fetchEvents({
|
|
60
|
+
cursor,
|
|
61
|
+
limit: opts.batchSize,
|
|
62
|
+
types: opts.types
|
|
63
|
+
});
|
|
64
|
+
pages++;
|
|
65
|
+
for (const event of envelope.events) {
|
|
66
|
+
if (opts.signal?.aborted)
|
|
67
|
+
return;
|
|
68
|
+
yield event;
|
|
69
|
+
}
|
|
70
|
+
const nextCursor = envelope.next_cursor;
|
|
71
|
+
if (nextCursor && nextCursor !== cursor) {
|
|
72
|
+
cursor = nextCursor;
|
|
73
|
+
emptyPolls = 0;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
if (envelope.events.length === 0) {
|
|
77
|
+
emptyPolls++;
|
|
78
|
+
if (emptyPolls >= maxEmptyPolls || pages >= maxPages)
|
|
79
|
+
return;
|
|
80
|
+
await sleep(emptyBackoffMs, opts.signal);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/streams/errors.ts
|
|
88
|
+
class AuthError extends Error {
|
|
89
|
+
status = 401;
|
|
90
|
+
constructor(message = "API key invalid or expired.") {
|
|
91
|
+
super(message);
|
|
92
|
+
this.name = "AuthError";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
class RateLimitError extends Error {
|
|
97
|
+
retryAfter;
|
|
98
|
+
status = 429;
|
|
99
|
+
constructor(message = "Rate limited. Try again later.", retryAfter) {
|
|
100
|
+
super(message);
|
|
101
|
+
this.retryAfter = retryAfter;
|
|
102
|
+
this.name = "RateLimitError";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
class ValidationError extends Error {
|
|
107
|
+
status;
|
|
108
|
+
body;
|
|
109
|
+
constructor(message, status, body) {
|
|
110
|
+
super(message);
|
|
111
|
+
this.status = status;
|
|
112
|
+
this.body = body;
|
|
113
|
+
this.name = "ValidationError";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
class StreamsServerError extends Error {
|
|
118
|
+
status;
|
|
119
|
+
body;
|
|
120
|
+
constructor(message, status, body) {
|
|
121
|
+
super(message);
|
|
122
|
+
this.status = status;
|
|
123
|
+
this.body = body;
|
|
124
|
+
this.name = "StreamsServerError";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/streams/client.ts
|
|
129
|
+
var DEFAULT_STREAMS_BASE_URL = "https://api.secondlayer.tools";
|
|
130
|
+
function normalizeBaseUrl(baseUrl) {
|
|
131
|
+
return baseUrl.replace(/\/+$/, "");
|
|
132
|
+
}
|
|
133
|
+
function appendSearchParam(params, name, value) {
|
|
134
|
+
if (value === undefined || value === null)
|
|
135
|
+
return;
|
|
136
|
+
params.set(name, String(value));
|
|
137
|
+
}
|
|
138
|
+
async function responseBody(response) {
|
|
139
|
+
const text = await response.text();
|
|
140
|
+
if (text.length === 0)
|
|
141
|
+
return;
|
|
142
|
+
try {
|
|
143
|
+
return JSON.parse(text);
|
|
144
|
+
} catch {
|
|
145
|
+
return text;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function errorMessage(body, fallback) {
|
|
149
|
+
if (body && typeof body === "object") {
|
|
150
|
+
const record = body;
|
|
151
|
+
const message = record.error ?? record.message;
|
|
152
|
+
if (typeof message === "string" && message.length > 0)
|
|
153
|
+
return message;
|
|
154
|
+
}
|
|
155
|
+
if (typeof body === "string" && body.length > 0)
|
|
156
|
+
return body;
|
|
157
|
+
return fallback;
|
|
158
|
+
}
|
|
159
|
+
async function mapStreamsError(response) {
|
|
160
|
+
const body = await responseBody(response);
|
|
161
|
+
if (response.status === 401) {
|
|
162
|
+
throw new AuthError(errorMessage(body, "API key invalid or expired."));
|
|
163
|
+
}
|
|
164
|
+
if (response.status === 429) {
|
|
165
|
+
const retryAfter = response.headers.get("Retry-After") ?? undefined;
|
|
166
|
+
throw new RateLimitError(errorMessage(body, "Rate limited. Try again later."), retryAfter);
|
|
167
|
+
}
|
|
168
|
+
if (response.status >= 500) {
|
|
169
|
+
throw new StreamsServerError(errorMessage(body, `Streams server returned ${response.status}.`), response.status, body);
|
|
170
|
+
}
|
|
171
|
+
throw new ValidationError(errorMessage(body, `Streams request returned ${response.status}.`), response.status, body);
|
|
172
|
+
}
|
|
173
|
+
function createStreamsClient(options) {
|
|
174
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_STREAMS_BASE_URL);
|
|
175
|
+
const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
|
|
176
|
+
async function request(path) {
|
|
177
|
+
const response = await fetchImpl(`${baseUrl}${path}`, {
|
|
178
|
+
headers: { Authorization: `Bearer ${options.apiKey}` }
|
|
179
|
+
});
|
|
180
|
+
if (!response.ok)
|
|
181
|
+
await mapStreamsError(response);
|
|
182
|
+
return await response.json();
|
|
183
|
+
}
|
|
184
|
+
const fetchEvents = async ({
|
|
185
|
+
cursor,
|
|
186
|
+
limit,
|
|
187
|
+
types
|
|
188
|
+
}) => {
|
|
189
|
+
return listEvents({ cursor, limit, types });
|
|
190
|
+
};
|
|
191
|
+
async function listEvents(params = {}) {
|
|
192
|
+
const searchParams = new URLSearchParams;
|
|
193
|
+
appendSearchParam(searchParams, "cursor", params.cursor);
|
|
194
|
+
appendSearchParam(searchParams, "from_height", params.fromHeight);
|
|
195
|
+
appendSearchParam(searchParams, "to_height", params.toHeight);
|
|
196
|
+
appendSearchParam(searchParams, "limit", params.limit);
|
|
197
|
+
if (params.types?.length) {
|
|
198
|
+
searchParams.set("types", params.types.join(","));
|
|
199
|
+
}
|
|
200
|
+
const query = searchParams.toString();
|
|
201
|
+
return request(`/v1/streams/events${query ? `?${query}` : ""}`);
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
events: {
|
|
205
|
+
list: listEvents,
|
|
206
|
+
consume(params) {
|
|
207
|
+
return consumeStreamsEvents({
|
|
208
|
+
fromCursor: params.fromCursor,
|
|
209
|
+
mode: params.mode,
|
|
210
|
+
types: params.types,
|
|
211
|
+
batchSize: params.batchSize ?? 100,
|
|
212
|
+
fetchEvents,
|
|
213
|
+
onBatch: params.onBatch,
|
|
214
|
+
emptyBackoffMs: params.emptyBackoffMs,
|
|
215
|
+
maxPages: params.maxPages,
|
|
216
|
+
maxEmptyPolls: params.maxEmptyPolls,
|
|
217
|
+
signal: params.signal
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
stream(params = {}) {
|
|
221
|
+
return streamStreamsEvents({
|
|
222
|
+
fromCursor: params.fromCursor,
|
|
223
|
+
types: params.types,
|
|
224
|
+
batchSize: params.batchSize ?? 100,
|
|
225
|
+
emptyBackoffMs: params.emptyBackoffMs,
|
|
226
|
+
maxPages: params.maxPages,
|
|
227
|
+
maxEmptyPolls: params.maxEmptyPolls,
|
|
228
|
+
signal: params.signal,
|
|
229
|
+
fetchEvents
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
tip() {
|
|
234
|
+
return request("/v1/streams/tip");
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// src/streams/ft-transfer.ts
|
|
239
|
+
function requireString(payload, field) {
|
|
240
|
+
const value = payload[field];
|
|
241
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
242
|
+
throw new Error(`ft_transfer payload missing ${field}`);
|
|
243
|
+
}
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
246
|
+
function parseAssetIdentifier(assetIdentifier) {
|
|
247
|
+
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
248
|
+
if (!contractId) {
|
|
249
|
+
throw new Error("ft_transfer payload has malformed asset_identifier");
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
contract_id: contractId,
|
|
253
|
+
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function isFtTransfer(event) {
|
|
257
|
+
return event.event_type === "ft_transfer";
|
|
258
|
+
}
|
|
259
|
+
function decodeFtTransfer(event) {
|
|
260
|
+
if (!isFtTransfer(event)) {
|
|
261
|
+
throw new Error(`Expected ft_transfer event, got ${event.event_type}`);
|
|
262
|
+
}
|
|
263
|
+
const payload = event.payload;
|
|
264
|
+
const assetIdentifier = requireString(payload, "asset_identifier");
|
|
265
|
+
const sender = requireString(payload, "sender");
|
|
266
|
+
const recipient = requireString(payload, "recipient");
|
|
267
|
+
const amount = requireString(payload, "amount");
|
|
268
|
+
if (!/^(0|[1-9]\d*)$/.test(amount)) {
|
|
269
|
+
throw new Error("ft_transfer payload has malformed amount");
|
|
270
|
+
}
|
|
271
|
+
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier);
|
|
272
|
+
return {
|
|
273
|
+
cursor: event.cursor,
|
|
274
|
+
block_height: event.block_height,
|
|
275
|
+
tx_id: event.tx_id,
|
|
276
|
+
tx_index: event.tx_index,
|
|
277
|
+
event_index: event.event_index,
|
|
278
|
+
event_type: event.event_type,
|
|
279
|
+
decoded_payload: {
|
|
280
|
+
asset_identifier: assetIdentifier,
|
|
281
|
+
contract_id: event.contract_id ?? contract_id,
|
|
282
|
+
token_name,
|
|
283
|
+
sender,
|
|
284
|
+
recipient,
|
|
285
|
+
amount
|
|
286
|
+
},
|
|
287
|
+
source_cursor: event.cursor
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// src/streams/nft-transfer.ts
|
|
291
|
+
function requireString2(payload, field) {
|
|
292
|
+
const value = payload[field];
|
|
293
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
294
|
+
throw new Error(`nft_transfer payload missing ${field}`);
|
|
295
|
+
}
|
|
296
|
+
return value;
|
|
297
|
+
}
|
|
298
|
+
function requireHexValue(payload) {
|
|
299
|
+
const value = payload.value;
|
|
300
|
+
const hex = typeof value === "string" ? value : value && typeof value === "object" && typeof value.hex === "string" ? value.hex : null;
|
|
301
|
+
if (!hex) {
|
|
302
|
+
throw new Error("nft_transfer payload missing value");
|
|
303
|
+
}
|
|
304
|
+
if (!/^0x[0-9a-fA-F]*$/.test(hex)) {
|
|
305
|
+
throw new Error("nft_transfer payload has malformed value");
|
|
306
|
+
}
|
|
307
|
+
return hex;
|
|
308
|
+
}
|
|
309
|
+
function parseAssetIdentifier2(assetIdentifier) {
|
|
310
|
+
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
311
|
+
if (!contractId) {
|
|
312
|
+
throw new Error("nft_transfer payload has malformed asset_identifier");
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
contract_id: contractId,
|
|
316
|
+
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function isNftTransfer(event) {
|
|
320
|
+
return event.event_type === "nft_transfer";
|
|
321
|
+
}
|
|
322
|
+
function decodeNftTransfer(event) {
|
|
323
|
+
if (!isNftTransfer(event)) {
|
|
324
|
+
throw new Error(`Expected nft_transfer event, got ${event.event_type}`);
|
|
325
|
+
}
|
|
326
|
+
const payload = event.payload;
|
|
327
|
+
const assetIdentifier = requireString2(payload, "asset_identifier");
|
|
328
|
+
const sender = requireString2(payload, "sender");
|
|
329
|
+
const recipient = requireString2(payload, "recipient");
|
|
330
|
+
const value = requireHexValue(payload);
|
|
331
|
+
const { contract_id, token_name } = parseAssetIdentifier2(assetIdentifier);
|
|
332
|
+
return {
|
|
333
|
+
cursor: event.cursor,
|
|
334
|
+
block_height: event.block_height,
|
|
335
|
+
tx_id: event.tx_id,
|
|
336
|
+
tx_index: event.tx_index,
|
|
337
|
+
event_index: event.event_index,
|
|
338
|
+
event_type: event.event_type,
|
|
339
|
+
decoded_payload: {
|
|
340
|
+
asset_identifier: assetIdentifier,
|
|
341
|
+
contract_id: event.contract_id ?? contract_id,
|
|
342
|
+
token_name,
|
|
343
|
+
sender,
|
|
344
|
+
recipient,
|
|
345
|
+
value
|
|
346
|
+
},
|
|
347
|
+
source_cursor: event.cursor
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
// src/streams/types.ts
|
|
351
|
+
var STREAMS_EVENT_TYPES = [
|
|
352
|
+
"stx_transfer",
|
|
353
|
+
"stx_mint",
|
|
354
|
+
"stx_burn",
|
|
355
|
+
"stx_lock",
|
|
356
|
+
"ft_transfer",
|
|
357
|
+
"ft_mint",
|
|
358
|
+
"ft_burn",
|
|
359
|
+
"nft_transfer",
|
|
360
|
+
"nft_mint",
|
|
361
|
+
"nft_burn",
|
|
362
|
+
"print"
|
|
363
|
+
];
|
|
364
|
+
export {
|
|
365
|
+
isNftTransfer,
|
|
366
|
+
isFtTransfer,
|
|
367
|
+
decodeNftTransfer,
|
|
368
|
+
decodeFtTransfer,
|
|
369
|
+
createStreamsClient,
|
|
370
|
+
ValidationError,
|
|
371
|
+
StreamsServerError,
|
|
372
|
+
STREAMS_EVENT_TYPES,
|
|
373
|
+
RateLimitError,
|
|
374
|
+
AuthError
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
//# debugId=1F9A85058EBF8AD064756E2164756E21
|
|
378
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/streams/consumer.ts", "../src/streams/errors.ts", "../src/streams/client.ts", "../src/streams/ft-transfer.ts", "../src/streams/nft-transfer.ts", "../src/streams/types.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type {\n\tStreamsEvent,\n\tStreamsEventsEnvelope,\n\tStreamsEventType,\n} from \"./types.ts\";\n\ntype StreamsEventsFetchParams = {\n\tcursor?: string | null;\n\tlimit: number;\n\ttypes?: readonly StreamsEventType[];\n};\n\nexport type StreamsEventsFetcher = (\n\tparams: StreamsEventsFetchParams,\n) => Promise<StreamsEventsEnvelope>;\n\nexport type Sleep = (ms: number, signal?: AbortSignal) => Promise<void>;\n\nexport async function defaultSleep(ms: number, signal?: AbortSignal): Promise<void> {\n\tif (signal?.aborted) return;\n\n\tawait new Promise<void>((resolve) => {\n\t\tconst timeout = setTimeout(resolve, ms);\n\t\tif (!signal) return;\n\t\tsignal.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\tresolve();\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n\nexport async function consumeStreamsEvents(opts: {\n\tfromCursor?: string | null;\n\tmode?: \"tail\" | \"bounded\";\n\tbatchSize: number;\n\ttypes?: readonly StreamsEventType[];\n\tfetchEvents: StreamsEventsFetcher;\n\tonBatch: (\n\t\tevents: StreamsEvent[],\n\t\tenvelope: StreamsEventsEnvelope,\n\t) => Promise<string | null | undefined> | string | null | undefined;\n\tsleep?: Sleep;\n\temptyBackoffMs?: number;\n\tmaxPages?: number;\n\tmaxEmptyPolls?: number;\n\tsignal?: AbortSignal;\n}): Promise<{ cursor: string | null; pages: number; emptyPolls: number }> {\n\tconst sleep = opts.sleep ?? defaultSleep;\n\tconst mode = opts.mode ?? \"tail\";\n\tconst emptyBackoffMs = opts.emptyBackoffMs ?? 500;\n\tconst maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;\n\tconst maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;\n\tlet cursor = opts.fromCursor ?? null;\n\tlet pages = 0;\n\tlet emptyPolls = 0;\n\n\twhile (\n\t\tpages < maxPages &&\n\t\temptyPolls < maxEmptyPolls &&\n\t\t!opts.signal?.aborted\n\t) {\n\t\tconst envelope = await opts.fetchEvents({\n\t\t\tcursor,\n\t\t\tlimit: opts.batchSize,\n\t\t\ttypes: opts.types,\n\t\t});\n\t\tpages++;\n\n\t\tconst returnedCursor = await opts.onBatch(envelope.events, envelope);\n\t\tconst nextCursor = returnedCursor ?? envelope.next_cursor;\n\n\t\tif (nextCursor && nextCursor !== cursor) {\n\t\t\tcursor = nextCursor;\n\t\t\temptyPolls = 0;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (envelope.events.length === 0) {\n\t\t\temptyPolls++;\n\t\t\tif (mode === \"bounded\") {\n\t\t\t\treturn { cursor, pages, emptyPolls };\n\t\t\t}\n\t\t\tawait sleep(emptyBackoffMs, opts.signal);\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn { cursor, pages, emptyPolls };\n\t}\n\n\treturn { cursor, pages, emptyPolls };\n}\n\nexport async function* streamStreamsEvents(opts: {\n\tfromCursor?: string | null;\n\tbatchSize: number;\n\ttypes?: readonly StreamsEventType[];\n\tfetchEvents: StreamsEventsFetcher;\n\tsleep?: Sleep;\n\temptyBackoffMs?: number;\n\tmaxPages?: number;\n\tmaxEmptyPolls?: number;\n\tsignal?: AbortSignal;\n}): AsyncGenerator<StreamsEvent> {\n\tconst sleep = opts.sleep ?? defaultSleep;\n\tconst emptyBackoffMs = opts.emptyBackoffMs ?? 500;\n\tconst maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;\n\tconst maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;\n\tlet cursor = opts.fromCursor ?? null;\n\tlet pages = 0;\n\tlet emptyPolls = 0;\n\n\twhile (\n\t\tpages < maxPages &&\n\t\temptyPolls < maxEmptyPolls &&\n\t\t!opts.signal?.aborted\n\t) {\n\t\tconst envelope = await opts.fetchEvents({\n\t\t\tcursor,\n\t\t\tlimit: opts.batchSize,\n\t\t\ttypes: opts.types,\n\t\t});\n\t\tpages++;\n\n\t\tfor (const event of envelope.events) {\n\t\t\tif (opts.signal?.aborted) return;\n\t\t\tyield event;\n\t\t}\n\n\t\tconst nextCursor = envelope.next_cursor;\n\t\tif (nextCursor && nextCursor !== cursor) {\n\t\t\tcursor = nextCursor;\n\t\t\temptyPolls = 0;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (envelope.events.length === 0) {\n\t\t\temptyPolls++;\n\t\t\tif (emptyPolls >= maxEmptyPolls || pages >= maxPages) return;\n\t\t\tawait sleep(emptyBackoffMs, opts.signal);\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn;\n\t}\n}\n",
|
|
6
|
+
"export class AuthError extends Error {\n\treadonly status = 401;\n\n\tconstructor(message = \"API key invalid or expired.\") {\n\t\tsuper(message);\n\t\tthis.name = \"AuthError\";\n\t}\n}\n\nexport class RateLimitError extends Error {\n\treadonly status = 429;\n\n\tconstructor(\n\t\tmessage = \"Rate limited. Try again later.\",\n\t\treadonly retryAfter?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"RateLimitError\";\n\t}\n}\n\nexport class ValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly status: number,\n\t\treadonly body?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ValidationError\";\n\t}\n}\n\nexport class StreamsServerError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly status: number,\n\t\treadonly body?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"StreamsServerError\";\n\t}\n}\n",
|
|
7
|
+
"import {\n\tconsumeStreamsEvents,\n\tstreamStreamsEvents,\n\ttype StreamsEventsFetcher,\n} from \"./consumer.ts\";\nimport {\n\tAuthError,\n\tRateLimitError,\n\tStreamsServerError,\n\tValidationError,\n} from \"./errors.ts\";\nimport type {\n\tFetchLike,\n\tStreamsClient,\n\tStreamsEventsEnvelope,\n\tStreamsEventsConsumeParams,\n\tStreamsEventsListParams,\n\tStreamsEventsStreamParams,\n\tStreamsTip,\n} from \"./types.ts\";\n\nconst DEFAULT_STREAMS_BASE_URL = \"https://api.secondlayer.tools\";\n\nexport type CreateStreamsClientOptions = {\n\tapiKey: string;\n\tbaseUrl?: string;\n\tfetchImpl?: FetchLike;\n};\n\nfunction normalizeBaseUrl(baseUrl: string): string {\n\treturn baseUrl.replace(/\\/+$/, \"\");\n}\n\nfunction appendSearchParam(\n\tparams: URLSearchParams,\n\tname: string,\n\tvalue: number | string | null | undefined,\n): void {\n\tif (value === undefined || value === null) return;\n\tparams.set(name, String(value));\n}\n\nasync function responseBody(response: Response): Promise<unknown> {\n\tconst text = await response.text();\n\tif (text.length === 0) return undefined;\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn text;\n\t}\n}\n\nfunction errorMessage(body: unknown, fallback: string): string {\n\tif (body && typeof body === \"object\") {\n\t\tconst record = body as Record<string, unknown>;\n\t\tconst message = record.error ?? record.message;\n\t\tif (typeof message === \"string\" && message.length > 0) return message;\n\t}\n\tif (typeof body === \"string\" && body.length > 0) return body;\n\treturn fallback;\n}\n\nasync function mapStreamsError(response: Response): Promise<never> {\n\tconst body = await responseBody(response);\n\n\tif (response.status === 401) {\n\t\tthrow new AuthError(errorMessage(body, \"API key invalid or expired.\"));\n\t}\n\n\tif (response.status === 429) {\n\t\tconst retryAfter = response.headers.get(\"Retry-After\") ?? undefined;\n\t\tthrow new RateLimitError(\n\t\t\terrorMessage(body, \"Rate limited. Try again later.\"),\n\t\t\tretryAfter,\n\t\t);\n\t}\n\n\tif (response.status >= 500) {\n\t\tthrow new StreamsServerError(\n\t\t\terrorMessage(body, `Streams server returned ${response.status}.`),\n\t\t\tresponse.status,\n\t\t\tbody,\n\t\t);\n\t}\n\n\tthrow new ValidationError(\n\t\terrorMessage(body, `Streams request returned ${response.status}.`),\n\t\tresponse.status,\n\t\tbody,\n\t);\n}\n\nexport function createStreamsClient(\n\toptions: CreateStreamsClientOptions,\n): StreamsClient {\n\tconst baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_STREAMS_BASE_URL);\n\tconst fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));\n\n\tasync function request<T>(path: string): Promise<T> {\n\t\tconst response = await fetchImpl(`${baseUrl}${path}`, {\n\t\t\theaders: { Authorization: `Bearer ${options.apiKey}` },\n\t\t});\n\t\tif (!response.ok) await mapStreamsError(response);\n\t\treturn (await response.json()) as T;\n\t}\n\n\tconst fetchEvents: StreamsEventsFetcher = async ({\n\t\tcursor,\n\t\tlimit,\n\t\ttypes,\n\t}) => {\n\t\treturn listEvents({ cursor, limit, types });\n\t};\n\n\tasync function listEvents(\n\t\tparams: StreamsEventsListParams = {},\n\t): Promise<StreamsEventsEnvelope> {\n\t\tconst searchParams = new URLSearchParams();\n\t\tappendSearchParam(searchParams, \"cursor\", params.cursor);\n\t\tappendSearchParam(searchParams, \"from_height\", params.fromHeight);\n\t\tappendSearchParam(searchParams, \"to_height\", params.toHeight);\n\t\tappendSearchParam(searchParams, \"limit\", params.limit);\n\t\tif (params.types?.length) {\n\t\t\tsearchParams.set(\"types\", params.types.join(\",\"));\n\t\t}\n\n\t\tconst query = searchParams.toString();\n\t\treturn request<StreamsEventsEnvelope>(\n\t\t\t`/v1/streams/events${query ? `?${query}` : \"\"}`,\n\t\t);\n\t}\n\n\treturn {\n\t\tevents: {\n\t\t\tlist: listEvents,\n\t\t\tconsume(params: StreamsEventsConsumeParams) {\n\t\t\t\treturn consumeStreamsEvents({\n\t\t\t\t\tfromCursor: params.fromCursor,\n\t\t\t\t\tmode: params.mode,\n\t\t\t\t\ttypes: params.types,\n\t\t\t\t\tbatchSize: params.batchSize ?? 100,\n\t\t\t\t\tfetchEvents,\n\t\t\t\t\tonBatch: params.onBatch,\n\t\t\t\t\temptyBackoffMs: params.emptyBackoffMs,\n\t\t\t\t\tmaxPages: params.maxPages,\n\t\t\t\t\tmaxEmptyPolls: params.maxEmptyPolls,\n\t\t\t\t\tsignal: params.signal,\n\t\t\t\t});\n\t\t\t},\n\t\t\tstream(params: StreamsEventsStreamParams = {}) {\n\t\t\t\treturn streamStreamsEvents({\n\t\t\t\t\tfromCursor: params.fromCursor,\n\t\t\t\t\ttypes: params.types,\n\t\t\t\t\tbatchSize: params.batchSize ?? 100,\n\t\t\t\t\temptyBackoffMs: params.emptyBackoffMs,\n\t\t\t\t\tmaxPages: params.maxPages,\n\t\t\t\t\tmaxEmptyPolls: params.maxEmptyPolls,\n\t\t\t\t\tsignal: params.signal,\n\t\t\t\t\tfetchEvents,\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t\ttip() {\n\t\t\treturn request<StreamsTip>(\"/v1/streams/tip\");\n\t\t},\n\t};\n}\n",
|
|
8
|
+
"import type { StreamsEvent } from \"./types.ts\";\n\nexport type FtTransferPayload = {\n\tasset_identifier: string;\n\tsender: string;\n\trecipient: string;\n\tamount: string;\n};\n\nexport type FtTransferEvent = StreamsEvent & {\n\tevent_type: \"ft_transfer\";\n\tpayload: FtTransferPayload;\n};\n\nexport type DecodedFtTransferPayload = {\n\tasset_identifier: string;\n\tcontract_id: string;\n\ttoken_name: string | null;\n\tsender: string;\n\trecipient: string;\n\tamount: string;\n};\n\nexport type DecodedFtTransfer = {\n\tcursor: string;\n\tblock_height: number;\n\ttx_id: string;\n\ttx_index: number;\n\tevent_index: number;\n\tevent_type: \"ft_transfer\";\n\tdecoded_payload: DecodedFtTransferPayload;\n\tsource_cursor: string;\n};\n\nfunction requireString(\n\tpayload: Record<string, unknown>,\n\tfield: keyof FtTransferPayload,\n): string {\n\tconst value = payload[field];\n\tif (typeof value !== \"string\" || value.length === 0) {\n\t\tthrow new Error(`ft_transfer payload missing ${field}`);\n\t}\n\treturn value;\n}\n\nfunction parseAssetIdentifier(assetIdentifier: string): {\n\tcontract_id: string;\n\ttoken_name: string | null;\n} {\n\tconst [contractId, tokenName] = assetIdentifier.split(\"::\");\n\tif (!contractId) {\n\t\tthrow new Error(\"ft_transfer payload has malformed asset_identifier\");\n\t}\n\treturn {\n\t\tcontract_id: contractId,\n\t\ttoken_name: tokenName && tokenName.length > 0 ? tokenName : null,\n\t};\n}\n\nexport function isFtTransfer(event: StreamsEvent): event is FtTransferEvent {\n\treturn event.event_type === \"ft_transfer\";\n}\n\nexport function decodeFtTransfer(event: StreamsEvent): DecodedFtTransfer {\n\tif (!isFtTransfer(event)) {\n\t\tthrow new Error(`Expected ft_transfer event, got ${event.event_type}`);\n\t}\n\n\tconst payload = event.payload;\n\tconst assetIdentifier = requireString(payload, \"asset_identifier\");\n\tconst sender = requireString(payload, \"sender\");\n\tconst recipient = requireString(payload, \"recipient\");\n\tconst amount = requireString(payload, \"amount\");\n\tif (!/^(0|[1-9]\\d*)$/.test(amount)) {\n\t\tthrow new Error(\"ft_transfer payload has malformed amount\");\n\t}\n\n\tconst { contract_id, token_name } = parseAssetIdentifier(assetIdentifier);\n\n\treturn {\n\t\tcursor: event.cursor,\n\t\tblock_height: event.block_height,\n\t\ttx_id: event.tx_id,\n\t\ttx_index: event.tx_index,\n\t\tevent_index: event.event_index,\n\t\tevent_type: event.event_type,\n\t\tdecoded_payload: {\n\t\t\tasset_identifier: assetIdentifier,\n\t\t\tcontract_id: event.contract_id ?? contract_id,\n\t\t\ttoken_name,\n\t\t\tsender,\n\t\t\trecipient,\n\t\t\tamount,\n\t\t},\n\t\tsource_cursor: event.cursor,\n\t};\n}\n",
|
|
9
|
+
"import type { StreamsEvent } from \"./types.ts\";\n\nexport type NftTransferPayload = {\n\tasset_identifier: string;\n\tsender: string;\n\trecipient: string;\n\tvalue: string | { hex: string };\n};\n\nexport type NftTransferEvent = StreamsEvent & {\n\tevent_type: \"nft_transfer\";\n\tpayload: NftTransferPayload;\n};\n\nexport type DecodedNftTransferPayload = {\n\tasset_identifier: string;\n\tcontract_id: string;\n\ttoken_name: string | null;\n\tsender: string;\n\trecipient: string;\n\tvalue: string;\n};\n\nexport type DecodedNftTransfer = {\n\tcursor: string;\n\tblock_height: number;\n\ttx_id: string;\n\ttx_index: number;\n\tevent_index: number;\n\tevent_type: \"nft_transfer\";\n\tdecoded_payload: DecodedNftTransferPayload;\n\tsource_cursor: string;\n};\n\nfunction requireString(\n\tpayload: Record<string, unknown>,\n\tfield: \"asset_identifier\" | \"sender\" | \"recipient\",\n): string {\n\tconst value = payload[field];\n\tif (typeof value !== \"string\" || value.length === 0) {\n\t\tthrow new Error(`nft_transfer payload missing ${field}`);\n\t}\n\treturn value;\n}\n\nfunction requireHexValue(payload: Record<string, unknown>): string {\n\tconst value = payload.value;\n\tconst hex =\n\t\ttypeof value === \"string\"\n\t\t\t? value\n\t\t\t: value &&\n\t\t\t\t\ttypeof value === \"object\" &&\n\t\t\t\t\ttypeof (value as { hex?: unknown }).hex === \"string\"\n\t\t\t\t? (value as { hex: string }).hex\n\t\t\t\t: null;\n\n\tif (!hex) {\n\t\tthrow new Error(\"nft_transfer payload missing value\");\n\t}\n\tif (!/^0x[0-9a-fA-F]*$/.test(hex)) {\n\t\tthrow new Error(\"nft_transfer payload has malformed value\");\n\t}\n\treturn hex;\n}\n\nfunction parseAssetIdentifier(assetIdentifier: string): {\n\tcontract_id: string;\n\ttoken_name: string | null;\n} {\n\tconst [contractId, tokenName] = assetIdentifier.split(\"::\");\n\tif (!contractId) {\n\t\tthrow new Error(\"nft_transfer payload has malformed asset_identifier\");\n\t}\n\treturn {\n\t\tcontract_id: contractId,\n\t\ttoken_name: tokenName && tokenName.length > 0 ? tokenName : null,\n\t};\n}\n\nexport function isNftTransfer(event: StreamsEvent): event is NftTransferEvent {\n\treturn event.event_type === \"nft_transfer\";\n}\n\nexport function decodeNftTransfer(event: StreamsEvent): DecodedNftTransfer {\n\tif (!isNftTransfer(event)) {\n\t\tthrow new Error(`Expected nft_transfer event, got ${event.event_type}`);\n\t}\n\n\tconst payload = event.payload;\n\tconst assetIdentifier = requireString(payload, \"asset_identifier\");\n\tconst sender = requireString(payload, \"sender\");\n\tconst recipient = requireString(payload, \"recipient\");\n\tconst value = requireHexValue(payload);\n\tconst { contract_id, token_name } = parseAssetIdentifier(assetIdentifier);\n\n\treturn {\n\t\tcursor: event.cursor,\n\t\tblock_height: event.block_height,\n\t\ttx_id: event.tx_id,\n\t\ttx_index: event.tx_index,\n\t\tevent_index: event.event_index,\n\t\tevent_type: event.event_type,\n\t\tdecoded_payload: {\n\t\t\tasset_identifier: assetIdentifier,\n\t\t\tcontract_id: event.contract_id ?? contract_id,\n\t\t\ttoken_name,\n\t\t\tsender,\n\t\t\trecipient,\n\t\t\tvalue,\n\t\t},\n\t\tsource_cursor: event.cursor,\n\t};\n}\n",
|
|
10
|
+
"export const STREAMS_EVENT_TYPES = [\n\t\"stx_transfer\",\n\t\"stx_mint\",\n\t\"stx_burn\",\n\t\"stx_lock\",\n\t\"ft_transfer\",\n\t\"ft_mint\",\n\t\"ft_burn\",\n\t\"nft_transfer\",\n\t\"nft_mint\",\n\t\"nft_burn\",\n\t\"print\",\n] as const;\n\nexport type StreamsEventType = (typeof STREAMS_EVENT_TYPES)[number];\n\nexport type StreamsEventPayload = Record<string, unknown>;\n\nexport type StreamsEvent = {\n\tcursor: string;\n\tblock_height: number;\n\tindex_block_hash: string;\n\tburn_block_height: number;\n\ttx_id: string;\n\ttx_index: number;\n\tevent_index: number;\n\tevent_type: StreamsEventType;\n\tcontract_id: string | null;\n\tpayload: StreamsEventPayload;\n\tts: string;\n};\n\nexport type StreamsTip = {\n\tblock_height: number;\n\tindex_block_hash: string;\n\tburn_block_height: number;\n\tlag_seconds: number;\n};\n\nexport type StreamsReorg = {\n\tdetected_at: string;\n\tfork_point_height: number;\n\torphaned_range: { from: string; to: string };\n\tnew_canonical_tip: string;\n};\n\nexport type StreamsEventsEnvelope = {\n\tevents: StreamsEvent[];\n\tnext_cursor: string | null;\n\ttip: StreamsTip;\n\treorgs: StreamsReorg[];\n};\n\nexport type StreamsEventsListParams = {\n\tcursor?: string | null;\n\tfromHeight?: number;\n\ttoHeight?: number;\n\ttypes?: readonly StreamsEventType[];\n\tlimit?: number;\n};\n\nexport type StreamsEventsStreamParams = {\n\tfromCursor?: string | null;\n\ttypes?: readonly StreamsEventType[];\n\tbatchSize?: number;\n\temptyBackoffMs?: number;\n\tmaxPages?: number;\n\tmaxEmptyPolls?: number;\n\tsignal?: AbortSignal;\n};\n\nexport type StreamsEventsConsumeParams = {\n\tfromCursor?: string | null;\n\tmode?: \"tail\" | \"bounded\";\n\ttypes?: readonly StreamsEventType[];\n\tbatchSize?: number;\n\tonBatch: (\n\t\tevents: StreamsEvent[],\n\t\tenvelope: StreamsEventsEnvelope,\n\t) => Promise<string | null | undefined> | string | null | undefined;\n\temptyBackoffMs?: number;\n\tmaxPages?: number;\n\tmaxEmptyPolls?: number;\n\tsignal?: AbortSignal;\n};\n\nexport type StreamsEventsConsumeResult = {\n\tcursor: string | null;\n\tpages: number;\n\temptyPolls: number;\n};\n\nexport type FetchLike = (\n\tinput: string | URL | Request,\n\tinit?: RequestInit,\n) => Promise<Response>;\n\nexport type StreamsClient = {\n\tevents: {\n\t\tlist(params?: StreamsEventsListParams): Promise<StreamsEventsEnvelope>;\n\t\t/**\n\t\t * Pull pages from Streams and call `onBatch` after each page.\n\t\t *\n\t\t * Use `consume` for indexers and ETL jobs that own checkpointing. Return\n\t\t * the checkpoint cursor from `onBatch`. Default `mode: \"tail\"` keeps\n\t\t * polling when caught up; `mode: \"bounded\"` exits on the first empty page.\n\t\t * The consumer also exits when `maxPages`, `maxEmptyPolls`, or `signal`\n\t\t * stops it.\n\t\t */\n\t\tconsume(\n\t\t\tparams: StreamsEventsConsumeParams,\n\t\t): Promise<StreamsEventsConsumeResult>;\n\t\t/**\n\t\t * Follow Streams as an async iterator.\n\t\t *\n\t\t * Use `stream` for live processors and watch-style apps. It tails\n\t\t * indefinitely by default and stops when its `AbortSignal`, `maxPages`, or\n\t\t * `maxEmptyPolls` stops it.\n\t\t */\n\t\tstream(params?: StreamsEventsStreamParams): AsyncIterable<StreamsEvent>;\n\t};\n\ttip(): Promise<StreamsTip>;\n};\n"
|
|
11
|
+
],
|
|
12
|
+
"mappings": "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",
|
|
13
|
+
"debugId": "1F9A85058EBF8AD064756E2164756E21",
|
|
14
|
+
"names": []
|
|
15
|
+
}
|
|
@@ -102,6 +102,92 @@ declare class Subgraphs extends BaseClient {
|
|
|
102
102
|
private createTableClient;
|
|
103
103
|
}
|
|
104
104
|
import { InferSubgraphClient as InferSubgraphClient2 } from "@secondlayer/subgraphs";
|
|
105
|
+
type IndexTip = {
|
|
106
|
+
block_height: number
|
|
107
|
+
lag_seconds: number
|
|
108
|
+
};
|
|
109
|
+
type FtTransfer = {
|
|
110
|
+
cursor: string
|
|
111
|
+
block_height: number
|
|
112
|
+
tx_id: string
|
|
113
|
+
tx_index: number
|
|
114
|
+
event_index: number
|
|
115
|
+
event_type: "ft_transfer"
|
|
116
|
+
contract_id: string
|
|
117
|
+
asset_identifier: string
|
|
118
|
+
sender: string
|
|
119
|
+
recipient: string
|
|
120
|
+
amount: string
|
|
121
|
+
};
|
|
122
|
+
type FtTransfersEnvelope = {
|
|
123
|
+
events: FtTransfer[]
|
|
124
|
+
next_cursor: string | null
|
|
125
|
+
tip: IndexTip
|
|
126
|
+
reorgs: never[]
|
|
127
|
+
};
|
|
128
|
+
type FtTransfersListParams = {
|
|
129
|
+
cursor?: string | null
|
|
130
|
+
fromCursor?: string | null
|
|
131
|
+
limit?: number
|
|
132
|
+
contractId?: string
|
|
133
|
+
sender?: string
|
|
134
|
+
recipient?: string
|
|
135
|
+
fromHeight?: number
|
|
136
|
+
toHeight?: number
|
|
137
|
+
};
|
|
138
|
+
type FtTransfersWalkParams = Omit<FtTransfersListParams, "limit"> & {
|
|
139
|
+
batchSize?: number
|
|
140
|
+
signal?: AbortSignal
|
|
141
|
+
};
|
|
142
|
+
type NftTransfer = {
|
|
143
|
+
cursor: string
|
|
144
|
+
block_height: number
|
|
145
|
+
tx_id: string
|
|
146
|
+
tx_index: number
|
|
147
|
+
event_index: number
|
|
148
|
+
event_type: "nft_transfer"
|
|
149
|
+
contract_id: string
|
|
150
|
+
asset_identifier: string
|
|
151
|
+
sender: string
|
|
152
|
+
recipient: string
|
|
153
|
+
value: string
|
|
154
|
+
};
|
|
155
|
+
type NftTransfersEnvelope = {
|
|
156
|
+
events: NftTransfer[]
|
|
157
|
+
next_cursor: string | null
|
|
158
|
+
tip: IndexTip
|
|
159
|
+
reorgs: never[]
|
|
160
|
+
};
|
|
161
|
+
type NftTransfersListParams = {
|
|
162
|
+
cursor?: string | null
|
|
163
|
+
fromCursor?: string | null
|
|
164
|
+
limit?: number
|
|
165
|
+
contractId?: string
|
|
166
|
+
assetIdentifier?: string
|
|
167
|
+
sender?: string
|
|
168
|
+
recipient?: string
|
|
169
|
+
fromHeight?: number
|
|
170
|
+
toHeight?: number
|
|
171
|
+
};
|
|
172
|
+
type NftTransfersWalkParams = Omit<NftTransfersListParams, "limit"> & {
|
|
173
|
+
batchSize?: number
|
|
174
|
+
signal?: AbortSignal
|
|
175
|
+
};
|
|
176
|
+
declare class Index extends BaseClient {
|
|
177
|
+
constructor(options?: Partial<SecondLayerOptions>);
|
|
178
|
+
readonly ftTransfers: {
|
|
179
|
+
list: (params?: FtTransfersListParams) => Promise<FtTransfersEnvelope>
|
|
180
|
+
walk: (params?: FtTransfersWalkParams) => AsyncIterable<FtTransfer>
|
|
181
|
+
};
|
|
182
|
+
readonly nftTransfers: {
|
|
183
|
+
list: (params?: NftTransfersListParams) => Promise<NftTransfersEnvelope>
|
|
184
|
+
walk: (params?: NftTransfersWalkParams) => AsyncIterable<NftTransfer>
|
|
185
|
+
};
|
|
186
|
+
private listFtTransfers;
|
|
187
|
+
private listNftTransfers;
|
|
188
|
+
private walkFtTransfers;
|
|
189
|
+
private walkNftTransfers;
|
|
190
|
+
}
|
|
105
191
|
import { CreateSubscriptionRequest, CreateSubscriptionResponse, DeadRow, DeliveryRow, ReplayResult, RotateSecretResponse, SubscriptionDetail, SubscriptionSummary, UpdateSubscriptionRequest } from "@secondlayer/shared/schemas/subscriptions";
|
|
106
192
|
declare class Subscriptions extends BaseClient {
|
|
107
193
|
list(): Promise<{
|
|
@@ -131,6 +217,7 @@ declare class Subscriptions extends BaseClient {
|
|
|
131
217
|
}>;
|
|
132
218
|
}
|
|
133
219
|
declare class SecondLayer extends BaseClient {
|
|
220
|
+
readonly index: Index;
|
|
134
221
|
readonly subgraphs: Subgraphs;
|
|
135
222
|
readonly subscriptions: Subscriptions;
|
|
136
223
|
constructor(options?: Partial<SecondLayerOptions>);
|
package/dist/subgraphs/index.js
CHANGED
|
@@ -276,6 +276,111 @@ class Subgraphs extends BaseClient {
|
|
|
276
276
|
};
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
+
// src/index-api/client.ts
|
|
280
|
+
function appendSearchParam(params, name, value) {
|
|
281
|
+
if (value === undefined || value === null)
|
|
282
|
+
return;
|
|
283
|
+
params.set(name, String(value));
|
|
284
|
+
}
|
|
285
|
+
function firstWalkFromHeight(params) {
|
|
286
|
+
if (params.fromHeight !== undefined)
|
|
287
|
+
return params.fromHeight;
|
|
288
|
+
if (params.cursor || params.fromCursor)
|
|
289
|
+
return;
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
class Index extends BaseClient {
|
|
294
|
+
constructor(options = {}) {
|
|
295
|
+
super(options);
|
|
296
|
+
}
|
|
297
|
+
ftTransfers = {
|
|
298
|
+
list: (params = {}) => this.listFtTransfers(params),
|
|
299
|
+
walk: (params = {}) => this.walkFtTransfers(params)
|
|
300
|
+
};
|
|
301
|
+
nftTransfers = {
|
|
302
|
+
list: (params = {}) => this.listNftTransfers(params),
|
|
303
|
+
walk: (params = {}) => this.walkNftTransfers(params)
|
|
304
|
+
};
|
|
305
|
+
async listFtTransfers(params = {}) {
|
|
306
|
+
const searchParams = new URLSearchParams;
|
|
307
|
+
appendSearchParam(searchParams, "cursor", params.cursor);
|
|
308
|
+
appendSearchParam(searchParams, "from_cursor", params.fromCursor);
|
|
309
|
+
appendSearchParam(searchParams, "limit", params.limit);
|
|
310
|
+
appendSearchParam(searchParams, "contract_id", params.contractId);
|
|
311
|
+
appendSearchParam(searchParams, "sender", params.sender);
|
|
312
|
+
appendSearchParam(searchParams, "recipient", params.recipient);
|
|
313
|
+
appendSearchParam(searchParams, "from_height", params.fromHeight);
|
|
314
|
+
appendSearchParam(searchParams, "to_height", params.toHeight);
|
|
315
|
+
const query = searchParams.toString();
|
|
316
|
+
return this.request("GET", `/v1/index/ft-transfers${query ? `?${query}` : ""}`);
|
|
317
|
+
}
|
|
318
|
+
async listNftTransfers(params = {}) {
|
|
319
|
+
const searchParams = new URLSearchParams;
|
|
320
|
+
appendSearchParam(searchParams, "cursor", params.cursor);
|
|
321
|
+
appendSearchParam(searchParams, "from_cursor", params.fromCursor);
|
|
322
|
+
appendSearchParam(searchParams, "limit", params.limit);
|
|
323
|
+
appendSearchParam(searchParams, "contract_id", params.contractId);
|
|
324
|
+
appendSearchParam(searchParams, "asset_identifier", params.assetIdentifier);
|
|
325
|
+
appendSearchParam(searchParams, "sender", params.sender);
|
|
326
|
+
appendSearchParam(searchParams, "recipient", params.recipient);
|
|
327
|
+
appendSearchParam(searchParams, "from_height", params.fromHeight);
|
|
328
|
+
appendSearchParam(searchParams, "to_height", params.toHeight);
|
|
329
|
+
const query = searchParams.toString();
|
|
330
|
+
return this.request("GET", `/v1/index/nft-transfers${query ? `?${query}` : ""}`);
|
|
331
|
+
}
|
|
332
|
+
async* walkFtTransfers(params = {}) {
|
|
333
|
+
const batchSize = params.batchSize ?? 200;
|
|
334
|
+
let cursor = params.cursor ?? params.fromCursor ?? null;
|
|
335
|
+
let firstPage = true;
|
|
336
|
+
while (!params.signal?.aborted) {
|
|
337
|
+
const envelope = await this.listFtTransfers({
|
|
338
|
+
...params,
|
|
339
|
+
limit: batchSize,
|
|
340
|
+
cursor: firstPage ? params.cursor : cursor,
|
|
341
|
+
fromCursor: firstPage ? params.fromCursor : undefined,
|
|
342
|
+
fromHeight: firstPage ? firstWalkFromHeight(params) : undefined
|
|
343
|
+
});
|
|
344
|
+
for (const event of envelope.events) {
|
|
345
|
+
if (params.signal?.aborted)
|
|
346
|
+
return;
|
|
347
|
+
yield event;
|
|
348
|
+
}
|
|
349
|
+
const nextCursor = envelope.next_cursor;
|
|
350
|
+
if (!nextCursor || nextCursor === cursor || envelope.events.length < batchSize) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
cursor = nextCursor;
|
|
354
|
+
firstPage = false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
async* walkNftTransfers(params = {}) {
|
|
358
|
+
const batchSize = params.batchSize ?? 200;
|
|
359
|
+
let cursor = params.cursor ?? params.fromCursor ?? null;
|
|
360
|
+
let firstPage = true;
|
|
361
|
+
while (!params.signal?.aborted) {
|
|
362
|
+
const envelope = await this.listNftTransfers({
|
|
363
|
+
...params,
|
|
364
|
+
limit: batchSize,
|
|
365
|
+
cursor: firstPage ? params.cursor : cursor,
|
|
366
|
+
fromCursor: firstPage ? params.fromCursor : undefined,
|
|
367
|
+
fromHeight: firstPage ? firstWalkFromHeight(params) : undefined
|
|
368
|
+
});
|
|
369
|
+
for (const event of envelope.events) {
|
|
370
|
+
if (params.signal?.aborted)
|
|
371
|
+
return;
|
|
372
|
+
yield event;
|
|
373
|
+
}
|
|
374
|
+
const nextCursor = envelope.next_cursor;
|
|
375
|
+
if (!nextCursor || nextCursor === cursor || envelope.events.length < batchSize) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
cursor = nextCursor;
|
|
379
|
+
firstPage = false;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
279
384
|
// src/subscriptions/client.ts
|
|
280
385
|
class Subscriptions extends BaseClient {
|
|
281
386
|
async list() {
|
|
@@ -318,10 +423,12 @@ class Subscriptions extends BaseClient {
|
|
|
318
423
|
|
|
319
424
|
// src/client.ts
|
|
320
425
|
class SecondLayer extends BaseClient {
|
|
426
|
+
index;
|
|
321
427
|
subgraphs;
|
|
322
428
|
subscriptions;
|
|
323
429
|
constructor(options = {}) {
|
|
324
430
|
super(options);
|
|
431
|
+
this.index = new Index(options);
|
|
325
432
|
this.subgraphs = new Subgraphs(options);
|
|
326
433
|
this.subscriptions = new Subscriptions(options);
|
|
327
434
|
}
|
|
@@ -342,5 +449,5 @@ export {
|
|
|
342
449
|
Subgraphs
|
|
343
450
|
};
|
|
344
451
|
|
|
345
|
-
//# debugId=
|
|
452
|
+
//# debugId=5DD669105B05F13064756E2164756E21
|
|
346
453
|
//# sourceMappingURL=index.js.map
|