@secondlayer/sdk 6.0.0 → 6.1.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/dist/index.d.ts +65 -3
- package/dist/index.js +252 -302
- package/dist/index.js.map +15 -14
- package/dist/streams/index.d.ts +62 -2
- package/dist/streams/index.js +310 -226
- package/dist/streams/index.js.map +12 -9
- package/dist/subgraphs/index.d.ts +42 -1
- package/dist/subgraphs/index.js +171 -141
- package/dist/subgraphs/index.js.map +10 -9
- package/package.json +2 -2
package/dist/subgraphs/index.js
CHANGED
|
@@ -25,6 +25,19 @@ class VersionConflictError extends ApiError {
|
|
|
25
25
|
|
|
26
26
|
// src/base.ts
|
|
27
27
|
var DEFAULT_BASE_URL = "https://api.secondlayer.tools";
|
|
28
|
+
function buildQuery(params) {
|
|
29
|
+
const search = new URLSearchParams;
|
|
30
|
+
for (const [name, value] of Object.entries(params)) {
|
|
31
|
+
if (value === undefined || value === null)
|
|
32
|
+
continue;
|
|
33
|
+
const serialized = Array.isArray(value) ? value.join(",") : String(value);
|
|
34
|
+
if (serialized.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
search.set(name, serialized);
|
|
37
|
+
}
|
|
38
|
+
const query = search.toString();
|
|
39
|
+
return query ? `?${query}` : "";
|
|
40
|
+
}
|
|
28
41
|
|
|
29
42
|
class BaseClient {
|
|
30
43
|
baseUrl;
|
|
@@ -312,11 +325,6 @@ class Subgraphs extends BaseClient {
|
|
|
312
325
|
}
|
|
313
326
|
}
|
|
314
327
|
// src/index-api/client.ts
|
|
315
|
-
function appendSearchParam(params, name, value) {
|
|
316
|
-
if (value === undefined || value === null)
|
|
317
|
-
return;
|
|
318
|
-
params.set(name, String(value));
|
|
319
|
-
}
|
|
320
328
|
function firstWalkFromHeight(params) {
|
|
321
329
|
if (params.fromHeight !== undefined)
|
|
322
330
|
return params.fromHeight;
|
|
@@ -346,31 +354,29 @@ class Index extends BaseClient {
|
|
|
346
354
|
walk: (params = {}) => this.walkContractCalls(params)
|
|
347
355
|
};
|
|
348
356
|
async listFtTransfers(params = {}) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return this.request("GET", `/v1/index/ft-transfers${query ? `?${query}` : ""}`);
|
|
357
|
+
return this.request("GET", `/v1/index/ft-transfers${buildQuery({
|
|
358
|
+
cursor: params.cursor,
|
|
359
|
+
from_cursor: params.fromCursor,
|
|
360
|
+
limit: params.limit,
|
|
361
|
+
contract_id: params.contractId,
|
|
362
|
+
sender: params.sender,
|
|
363
|
+
recipient: params.recipient,
|
|
364
|
+
from_height: params.fromHeight,
|
|
365
|
+
to_height: params.toHeight
|
|
366
|
+
})}`);
|
|
360
367
|
}
|
|
361
368
|
async listNftTransfers(params = {}) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
return this.request("GET", `/v1/index/nft-transfers${query ? `?${query}` : ""}`);
|
|
369
|
+
return this.request("GET", `/v1/index/nft-transfers${buildQuery({
|
|
370
|
+
cursor: params.cursor,
|
|
371
|
+
from_cursor: params.fromCursor,
|
|
372
|
+
limit: params.limit,
|
|
373
|
+
contract_id: params.contractId,
|
|
374
|
+
asset_identifier: params.assetIdentifier,
|
|
375
|
+
sender: params.sender,
|
|
376
|
+
recipient: params.recipient,
|
|
377
|
+
from_height: params.fromHeight,
|
|
378
|
+
to_height: params.toHeight
|
|
379
|
+
})}`);
|
|
374
380
|
}
|
|
375
381
|
async* walkFtTransfers(params = {}) {
|
|
376
382
|
const batchSize = params.batchSize ?? 200;
|
|
@@ -423,18 +429,18 @@ class Index extends BaseClient {
|
|
|
423
429
|
}
|
|
424
430
|
}
|
|
425
431
|
async listEvents(params) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
432
|
+
return this.request("GET", `/v1/index/events${buildQuery({
|
|
433
|
+
event_type: params.eventType,
|
|
434
|
+
cursor: params.cursor,
|
|
435
|
+
from_cursor: params.fromCursor,
|
|
436
|
+
limit: params.limit,
|
|
437
|
+
contract_id: params.contractId,
|
|
438
|
+
asset_identifier: params.assetIdentifier,
|
|
439
|
+
sender: params.sender,
|
|
440
|
+
recipient: params.recipient,
|
|
441
|
+
from_height: params.fromHeight,
|
|
442
|
+
to_height: params.toHeight
|
|
443
|
+
})}`);
|
|
438
444
|
}
|
|
439
445
|
async* walkEvents(params) {
|
|
440
446
|
const batchSize = params.batchSize ?? 200;
|
|
@@ -462,17 +468,16 @@ class Index extends BaseClient {
|
|
|
462
468
|
}
|
|
463
469
|
}
|
|
464
470
|
async listContractCalls(params = {}) {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
return this.request("GET", `/v1/index/contract-calls${query ? `?${query}` : ""}`);
|
|
471
|
+
return this.request("GET", `/v1/index/contract-calls${buildQuery({
|
|
472
|
+
cursor: params.cursor,
|
|
473
|
+
from_cursor: params.fromCursor,
|
|
474
|
+
limit: params.limit,
|
|
475
|
+
contract_id: params.contractId,
|
|
476
|
+
function_name: params.functionName,
|
|
477
|
+
sender: params.sender,
|
|
478
|
+
from_height: params.fromHeight,
|
|
479
|
+
to_height: params.toHeight
|
|
480
|
+
})}`);
|
|
476
481
|
}
|
|
477
482
|
async* walkContractCalls(params = {}) {
|
|
478
483
|
const batchSize = params.batchSize ?? 200;
|
|
@@ -504,7 +509,74 @@ class Index extends BaseClient {
|
|
|
504
509
|
// src/streams/client.ts
|
|
505
510
|
import { ed25519 } from "@secondlayer/shared";
|
|
506
511
|
|
|
512
|
+
// src/streams/errors.ts
|
|
513
|
+
class AuthError extends Error {
|
|
514
|
+
status = 401;
|
|
515
|
+
constructor(message = "API key invalid or expired.") {
|
|
516
|
+
super(message);
|
|
517
|
+
this.name = "AuthError";
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
class RateLimitError extends Error {
|
|
522
|
+
retryAfter;
|
|
523
|
+
status = 429;
|
|
524
|
+
constructor(message = "Rate limited. Try again later.", retryAfter) {
|
|
525
|
+
super(message);
|
|
526
|
+
this.retryAfter = retryAfter;
|
|
527
|
+
this.name = "RateLimitError";
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
class ValidationError extends Error {
|
|
532
|
+
status;
|
|
533
|
+
body;
|
|
534
|
+
constructor(message, status, body) {
|
|
535
|
+
super(message);
|
|
536
|
+
this.status = status;
|
|
537
|
+
this.body = body;
|
|
538
|
+
this.name = "ValidationError";
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
class StreamsServerError extends Error {
|
|
543
|
+
status;
|
|
544
|
+
body;
|
|
545
|
+
constructor(message, status, body) {
|
|
546
|
+
super(message);
|
|
547
|
+
this.status = status;
|
|
548
|
+
this.body = body;
|
|
549
|
+
this.name = "StreamsServerError";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
class StreamsSignatureError extends Error {
|
|
554
|
+
constructor(message = "Streams response signature verification failed.") {
|
|
555
|
+
super(message);
|
|
556
|
+
this.name = "StreamsSignatureError";
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// src/streams/cursor.ts
|
|
561
|
+
var Cursor = {
|
|
562
|
+
atHeight(height) {
|
|
563
|
+
return `${height}:0`;
|
|
564
|
+
},
|
|
565
|
+
parse(cursor) {
|
|
566
|
+
const parts = cursor.split(":");
|
|
567
|
+
const blockHeight = Number(parts[0]);
|
|
568
|
+
const eventIndex = Number(parts[1]);
|
|
569
|
+
if (parts.length !== 2 || !Number.isInteger(blockHeight) || !Number.isInteger(eventIndex)) {
|
|
570
|
+
throw new ValidationError(`Invalid stream cursor "${cursor}"; expected "<block>:<index>" (e.g. "951475:3").`, 400);
|
|
571
|
+
}
|
|
572
|
+
return { blockHeight, eventIndex };
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
507
576
|
// src/streams/consumer.ts
|
|
577
|
+
function reorgKey(reorg) {
|
|
578
|
+
return `${reorg.detected_at}|${reorg.fork_point_height}|${reorg.new_canonical_tip}`;
|
|
579
|
+
}
|
|
508
580
|
async function defaultSleep(ms, signal) {
|
|
509
581
|
if (signal?.aborted)
|
|
510
582
|
return;
|
|
@@ -521,10 +593,12 @@ async function defaultSleep(ms, signal) {
|
|
|
521
593
|
async function consumeStreamsEvents(opts) {
|
|
522
594
|
const sleep = opts.sleep ?? defaultSleep;
|
|
523
595
|
const mode = opts.mode ?? "tail";
|
|
596
|
+
const finalizedOnly = opts.finalizedOnly ?? false;
|
|
524
597
|
const emptyBackoffMs = opts.emptyBackoffMs ?? 500;
|
|
525
598
|
const maxPages = opts.maxPages ?? Number.POSITIVE_INFINITY;
|
|
526
599
|
const maxEmptyPolls = opts.maxEmptyPolls ?? Number.POSITIVE_INFINITY;
|
|
527
600
|
let cursor = opts.fromCursor ?? null;
|
|
601
|
+
const handledReorgs = new Set;
|
|
528
602
|
let pages = 0;
|
|
529
603
|
let emptyPolls = 0;
|
|
530
604
|
while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
|
|
@@ -539,14 +613,32 @@ async function consumeStreamsEvents(opts) {
|
|
|
539
613
|
assetIdentifier: opts.assetIdentifier
|
|
540
614
|
});
|
|
541
615
|
pages++;
|
|
542
|
-
|
|
543
|
-
|
|
616
|
+
if (!finalizedOnly && opts.onReorg) {
|
|
617
|
+
const fresh = envelope.reorgs.filter((reorg) => !handledReorgs.has(reorgKey(reorg))).sort((a, b) => a.fork_point_height - b.fork_point_height);
|
|
618
|
+
if (fresh.length > 0) {
|
|
619
|
+
const forkPoint = Math.min(...fresh.map((reorg) => reorg.fork_point_height));
|
|
620
|
+
const rewind = Cursor.atHeight(forkPoint);
|
|
621
|
+
for (const reorg of fresh) {
|
|
622
|
+
await opts.onReorg(reorg, { cursor: rewind });
|
|
623
|
+
handledReorgs.add(reorgKey(reorg));
|
|
624
|
+
}
|
|
625
|
+
cursor = rewind;
|
|
626
|
+
emptyPolls = 0;
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const emitted = finalizedOnly ? envelope.events.filter((event) => event.finalized) : envelope.events;
|
|
631
|
+
const checkpoint = finalizedOnly ? emitted.at(-1)?.cursor ?? cursor : envelope.next_cursor;
|
|
632
|
+
const returnedCursor = await opts.onBatch(emitted, envelope, {
|
|
633
|
+
cursor: checkpoint
|
|
634
|
+
});
|
|
635
|
+
const nextCursor = returnedCursor ?? checkpoint;
|
|
544
636
|
if (nextCursor && nextCursor !== cursor) {
|
|
545
637
|
cursor = nextCursor;
|
|
546
638
|
emptyPolls = 0;
|
|
547
639
|
continue;
|
|
548
640
|
}
|
|
549
|
-
if (
|
|
641
|
+
if (emitted.length === 0) {
|
|
550
642
|
emptyPolls++;
|
|
551
643
|
if (mode === "bounded") {
|
|
552
644
|
return { cursor, pages, emptyPolls };
|
|
@@ -602,56 +694,6 @@ async function* streamStreamsEvents(opts) {
|
|
|
602
694
|
|
|
603
695
|
// src/streams/dumps.ts
|
|
604
696
|
import { createHash } from "node:crypto";
|
|
605
|
-
|
|
606
|
-
// src/streams/errors.ts
|
|
607
|
-
class AuthError extends Error {
|
|
608
|
-
status = 401;
|
|
609
|
-
constructor(message = "API key invalid or expired.") {
|
|
610
|
-
super(message);
|
|
611
|
-
this.name = "AuthError";
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
class RateLimitError extends Error {
|
|
616
|
-
retryAfter;
|
|
617
|
-
status = 429;
|
|
618
|
-
constructor(message = "Rate limited. Try again later.", retryAfter) {
|
|
619
|
-
super(message);
|
|
620
|
-
this.retryAfter = retryAfter;
|
|
621
|
-
this.name = "RateLimitError";
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
class ValidationError extends Error {
|
|
626
|
-
status;
|
|
627
|
-
body;
|
|
628
|
-
constructor(message, status, body) {
|
|
629
|
-
super(message);
|
|
630
|
-
this.status = status;
|
|
631
|
-
this.body = body;
|
|
632
|
-
this.name = "ValidationError";
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
class StreamsServerError extends Error {
|
|
637
|
-
status;
|
|
638
|
-
body;
|
|
639
|
-
constructor(message, status, body) {
|
|
640
|
-
super(message);
|
|
641
|
-
this.status = status;
|
|
642
|
-
this.body = body;
|
|
643
|
-
this.name = "StreamsServerError";
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
class StreamsSignatureError extends Error {
|
|
648
|
-
constructor(message = "Streams response signature verification failed.") {
|
|
649
|
-
super(message);
|
|
650
|
-
this.name = "StreamsSignatureError";
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// src/streams/dumps.ts
|
|
655
697
|
function createStreamsDumps(opts) {
|
|
656
698
|
const baseUrl = opts.baseUrl?.replace(/\/+$/, "");
|
|
657
699
|
function requireBaseUrl() {
|
|
@@ -690,8 +732,12 @@ function createStreamsDumps(opts) {
|
|
|
690
732
|
function cursorTuple(cursor) {
|
|
691
733
|
if (!cursor)
|
|
692
734
|
return [-1, -1];
|
|
693
|
-
const
|
|
694
|
-
|
|
735
|
+
const parts = cursor.split(":");
|
|
736
|
+
const [block, index] = parts.map(Number);
|
|
737
|
+
if (parts.length !== 2 || !Number.isInteger(block) || !Number.isInteger(index)) {
|
|
738
|
+
throw new ValidationError(`Invalid stream cursor "${cursor}"; expected "<block>:<index>" (e.g. "951475:3").`, 400);
|
|
739
|
+
}
|
|
740
|
+
return [block, index];
|
|
695
741
|
}
|
|
696
742
|
function maxCursor(a, b) {
|
|
697
743
|
const [ah, ai] = cursorTuple(a);
|
|
@@ -702,18 +748,6 @@ var DEFAULT_STREAMS_BASE_URL = "https://api.secondlayer.tools";
|
|
|
702
748
|
function normalizeBaseUrl(baseUrl) {
|
|
703
749
|
return baseUrl.replace(/\/+$/, "");
|
|
704
750
|
}
|
|
705
|
-
function appendSearchParam2(params, name, value) {
|
|
706
|
-
if (value === undefined || value === null)
|
|
707
|
-
return;
|
|
708
|
-
params.set(name, String(value));
|
|
709
|
-
}
|
|
710
|
-
function appendListParam(params, name, value) {
|
|
711
|
-
if (value === undefined || value === null)
|
|
712
|
-
return;
|
|
713
|
-
const joined = Array.isArray(value) ? value.join(",") : value;
|
|
714
|
-
if (joined.length > 0)
|
|
715
|
-
params.set(name, joined);
|
|
716
|
-
}
|
|
717
751
|
async function responseBody(response) {
|
|
718
752
|
const text = await response.text();
|
|
719
753
|
if (text.length === 0)
|
|
@@ -835,23 +869,18 @@ function createStreamsClient(options) {
|
|
|
835
869
|
});
|
|
836
870
|
};
|
|
837
871
|
async function listEvents(params = {}) {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}
|
|
850
|
-
if (params.notTypes?.length) {
|
|
851
|
-
searchParams.set("not_types", params.notTypes.join(","));
|
|
852
|
-
}
|
|
853
|
-
const query = searchParams.toString();
|
|
854
|
-
return request(`/v1/streams/events${query ? `?${query}` : ""}`);
|
|
872
|
+
return request(`/v1/streams/events${buildQuery({
|
|
873
|
+
cursor: params.cursor,
|
|
874
|
+
from_height: params.fromHeight,
|
|
875
|
+
to_height: params.toHeight,
|
|
876
|
+
limit: params.limit,
|
|
877
|
+
contract_id: params.contractId,
|
|
878
|
+
sender: params.sender,
|
|
879
|
+
recipient: params.recipient,
|
|
880
|
+
asset_identifier: params.assetIdentifier,
|
|
881
|
+
types: params.types,
|
|
882
|
+
not_types: params.notTypes
|
|
883
|
+
})}`);
|
|
855
884
|
}
|
|
856
885
|
return {
|
|
857
886
|
events: {
|
|
@@ -863,6 +892,7 @@ function createStreamsClient(options) {
|
|
|
863
892
|
return consumeStreamsEvents({
|
|
864
893
|
fromCursor: params.fromCursor,
|
|
865
894
|
mode: params.mode,
|
|
895
|
+
finalizedOnly: params.finalizedOnly,
|
|
866
896
|
types: params.types,
|
|
867
897
|
notTypes: params.notTypes,
|
|
868
898
|
contractId: params.contractId,
|
|
@@ -872,6 +902,7 @@ function createStreamsClient(options) {
|
|
|
872
902
|
batchSize: params.batchSize ?? 100,
|
|
873
903
|
fetchEvents,
|
|
874
904
|
onBatch: params.onBatch,
|
|
905
|
+
onReorg: params.onReorg,
|
|
875
906
|
emptyBackoffMs: params.emptyBackoffMs,
|
|
876
907
|
maxPages: params.maxPages,
|
|
877
908
|
maxEmptyPolls: params.maxEmptyPolls,
|
|
@@ -926,11 +957,10 @@ function createStreamsClient(options) {
|
|
|
926
957
|
},
|
|
927
958
|
reorgs: {
|
|
928
959
|
list(params) {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
return request(`/v1/streams/reorgs${query ? `?${query}` : ""}`);
|
|
960
|
+
return request(`/v1/streams/reorgs${buildQuery({
|
|
961
|
+
since: params.since,
|
|
962
|
+
limit: params.limit
|
|
963
|
+
})}`);
|
|
934
964
|
}
|
|
935
965
|
},
|
|
936
966
|
dumps,
|
|
@@ -1017,5 +1047,5 @@ export {
|
|
|
1017
1047
|
Subgraphs
|
|
1018
1048
|
};
|
|
1019
1049
|
|
|
1020
|
-
//# debugId=
|
|
1050
|
+
//# debugId=CDC19E41AE11FF9164756E2164756E21
|
|
1021
1051
|
//# sourceMappingURL=index.js.map
|