@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/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,
|
|
@@ -1012,127 +1042,8 @@ function getSubgraph(def, options = {}) {
|
|
|
1012
1042
|
}
|
|
1013
1043
|
return new Subgraphs(options).typed(def);
|
|
1014
1044
|
}
|
|
1015
|
-
// src/streams/ft-transfer.ts
|
|
1016
|
-
function requireString(payload, field) {
|
|
1017
|
-
const value = payload[field];
|
|
1018
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
1019
|
-
throw new Error(`ft_transfer payload missing ${field}`);
|
|
1020
|
-
}
|
|
1021
|
-
return value;
|
|
1022
|
-
}
|
|
1023
|
-
function parseAssetIdentifier(assetIdentifier) {
|
|
1024
|
-
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
1025
|
-
if (!contractId) {
|
|
1026
|
-
throw new Error("ft_transfer payload has malformed asset_identifier");
|
|
1027
|
-
}
|
|
1028
|
-
return {
|
|
1029
|
-
contract_id: contractId,
|
|
1030
|
-
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
1031
|
-
};
|
|
1032
|
-
}
|
|
1033
|
-
function isFtTransfer(event) {
|
|
1034
|
-
return event.event_type === "ft_transfer";
|
|
1035
|
-
}
|
|
1036
|
-
function decodeFtTransfer(event) {
|
|
1037
|
-
if (!isFtTransfer(event)) {
|
|
1038
|
-
throw new Error(`Expected ft_transfer event, got ${event.event_type}`);
|
|
1039
|
-
}
|
|
1040
|
-
const payload = event.payload;
|
|
1041
|
-
const assetIdentifier = requireString(payload, "asset_identifier");
|
|
1042
|
-
const sender = requireString(payload, "sender");
|
|
1043
|
-
const recipient = requireString(payload, "recipient");
|
|
1044
|
-
const amount = requireString(payload, "amount");
|
|
1045
|
-
if (!/^(0|[1-9]\d*)$/.test(amount)) {
|
|
1046
|
-
throw new Error("ft_transfer payload has malformed amount");
|
|
1047
|
-
}
|
|
1048
|
-
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier);
|
|
1049
|
-
return {
|
|
1050
|
-
cursor: event.cursor,
|
|
1051
|
-
block_height: event.block_height,
|
|
1052
|
-
tx_id: event.tx_id,
|
|
1053
|
-
tx_index: event.tx_index,
|
|
1054
|
-
event_index: event.event_index,
|
|
1055
|
-
event_type: event.event_type,
|
|
1056
|
-
decoded_payload: {
|
|
1057
|
-
asset_identifier: assetIdentifier,
|
|
1058
|
-
contract_id: event.contract_id ?? contract_id,
|
|
1059
|
-
token_name,
|
|
1060
|
-
sender,
|
|
1061
|
-
recipient,
|
|
1062
|
-
amount
|
|
1063
|
-
},
|
|
1064
|
-
source_cursor: event.cursor
|
|
1065
|
-
};
|
|
1066
|
-
}
|
|
1067
|
-
// src/streams/nft-transfer.ts
|
|
1068
|
-
function requireString2(payload, field) {
|
|
1069
|
-
const value = payload[field];
|
|
1070
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
1071
|
-
throw new Error(`nft_transfer payload missing ${field}`);
|
|
1072
|
-
}
|
|
1073
|
-
return value;
|
|
1074
|
-
}
|
|
1075
|
-
function requireHexValue(payload) {
|
|
1076
|
-
const rawValue = payload.raw_value;
|
|
1077
|
-
if (typeof rawValue === "string") {
|
|
1078
|
-
if (!/^0x[0-9a-fA-F]*$/.test(rawValue)) {
|
|
1079
|
-
throw new Error("nft_transfer payload has malformed value");
|
|
1080
|
-
}
|
|
1081
|
-
return rawValue;
|
|
1082
|
-
}
|
|
1083
|
-
const value = payload.value;
|
|
1084
|
-
const hex = typeof value === "string" ? value : value && typeof value === "object" && typeof value.hex === "string" ? value.hex : null;
|
|
1085
|
-
if (!hex) {
|
|
1086
|
-
throw new Error("nft_transfer payload missing value");
|
|
1087
|
-
}
|
|
1088
|
-
if (!/^0x[0-9a-fA-F]*$/.test(hex)) {
|
|
1089
|
-
throw new Error("nft_transfer payload has malformed value");
|
|
1090
|
-
}
|
|
1091
|
-
return hex;
|
|
1092
|
-
}
|
|
1093
|
-
function parseAssetIdentifier2(assetIdentifier) {
|
|
1094
|
-
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
1095
|
-
if (!contractId) {
|
|
1096
|
-
throw new Error("nft_transfer payload has malformed asset_identifier");
|
|
1097
|
-
}
|
|
1098
|
-
return {
|
|
1099
|
-
contract_id: contractId,
|
|
1100
|
-
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
1101
|
-
};
|
|
1102
|
-
}
|
|
1103
|
-
function isNftTransfer(event) {
|
|
1104
|
-
return event.event_type === "nft_transfer";
|
|
1105
|
-
}
|
|
1106
|
-
function decodeNftTransfer(event) {
|
|
1107
|
-
if (!isNftTransfer(event)) {
|
|
1108
|
-
throw new Error(`Expected nft_transfer event, got ${event.event_type}`);
|
|
1109
|
-
}
|
|
1110
|
-
const payload = event.payload;
|
|
1111
|
-
const assetIdentifier = requireString2(payload, "asset_identifier");
|
|
1112
|
-
const sender = requireString2(payload, "sender");
|
|
1113
|
-
const recipient = requireString2(payload, "recipient");
|
|
1114
|
-
const value = requireHexValue(payload);
|
|
1115
|
-
const { contract_id, token_name } = parseAssetIdentifier2(assetIdentifier);
|
|
1116
|
-
return {
|
|
1117
|
-
cursor: event.cursor,
|
|
1118
|
-
block_height: event.block_height,
|
|
1119
|
-
tx_id: event.tx_id,
|
|
1120
|
-
tx_index: event.tx_index,
|
|
1121
|
-
event_index: event.event_index,
|
|
1122
|
-
event_type: event.event_type,
|
|
1123
|
-
decoded_payload: {
|
|
1124
|
-
asset_identifier: assetIdentifier,
|
|
1125
|
-
contract_id: event.contract_id ?? contract_id,
|
|
1126
|
-
token_name,
|
|
1127
|
-
sender,
|
|
1128
|
-
recipient,
|
|
1129
|
-
value
|
|
1130
|
-
},
|
|
1131
|
-
source_cursor: event.cursor
|
|
1132
|
-
};
|
|
1133
|
-
}
|
|
1134
1045
|
// src/streams/_payload.ts
|
|
1135
|
-
function
|
|
1046
|
+
function requireString(payload, field, eventType) {
|
|
1136
1047
|
const value = payload[field];
|
|
1137
1048
|
if (typeof value !== "string" || value.length === 0) {
|
|
1138
1049
|
throw new Error(`${eventType} payload missing ${field}`);
|
|
@@ -1143,7 +1054,7 @@ function optionalString(value) {
|
|
|
1143
1054
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1144
1055
|
}
|
|
1145
1056
|
function requireAmountField(payload, field, eventType) {
|
|
1146
|
-
const amount =
|
|
1057
|
+
const amount = requireString(payload, field, eventType);
|
|
1147
1058
|
if (!/^(0|[1-9]\d*)$/.test(amount)) {
|
|
1148
1059
|
throw new Error(`${eventType} payload has malformed ${field}`);
|
|
1149
1060
|
}
|
|
@@ -1152,7 +1063,7 @@ function requireAmountField(payload, field, eventType) {
|
|
|
1152
1063
|
function requireAmount(payload, eventType) {
|
|
1153
1064
|
return requireAmountField(payload, "amount", eventType);
|
|
1154
1065
|
}
|
|
1155
|
-
function
|
|
1066
|
+
function parseAssetIdentifier(assetIdentifier, eventType) {
|
|
1156
1067
|
const [contractId, tokenName] = assetIdentifier.split("::");
|
|
1157
1068
|
if (!contractId) {
|
|
1158
1069
|
throw new Error(`${eventType} payload has malformed asset_identifier`);
|
|
@@ -1162,7 +1073,7 @@ function parseAssetIdentifier3(assetIdentifier, eventType) {
|
|
|
1162
1073
|
token_name: tokenName && tokenName.length > 0 ? tokenName : null
|
|
1163
1074
|
};
|
|
1164
1075
|
}
|
|
1165
|
-
function
|
|
1076
|
+
function requireHexValue(payload, eventType) {
|
|
1166
1077
|
const rawValue = payload.raw_value;
|
|
1167
1078
|
if (typeof rawValue === "string") {
|
|
1168
1079
|
if (!/^0x[0-9a-fA-F]*$/.test(rawValue)) {
|
|
@@ -1193,6 +1104,52 @@ function decodedRow(event, eventType, decoded_payload) {
|
|
|
1193
1104
|
};
|
|
1194
1105
|
}
|
|
1195
1106
|
|
|
1107
|
+
// src/streams/ft-transfer.ts
|
|
1108
|
+
function isFtTransfer(event) {
|
|
1109
|
+
return event.event_type === "ft_transfer";
|
|
1110
|
+
}
|
|
1111
|
+
function decodeFtTransfer(event) {
|
|
1112
|
+
if (!isFtTransfer(event)) {
|
|
1113
|
+
throw new Error(`Expected ft_transfer event, got ${event.event_type}`);
|
|
1114
|
+
}
|
|
1115
|
+
const payload = event.payload;
|
|
1116
|
+
const assetIdentifier = requireString(payload, "asset_identifier", "ft_transfer");
|
|
1117
|
+
const sender = requireString(payload, "sender", "ft_transfer");
|
|
1118
|
+
const recipient = requireString(payload, "recipient", "ft_transfer");
|
|
1119
|
+
const amount = requireAmount(payload, "ft_transfer");
|
|
1120
|
+
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier, "ft_transfer");
|
|
1121
|
+
return decodedRow(event, "ft_transfer", {
|
|
1122
|
+
asset_identifier: assetIdentifier,
|
|
1123
|
+
contract_id: event.contract_id ?? contract_id,
|
|
1124
|
+
token_name,
|
|
1125
|
+
sender,
|
|
1126
|
+
recipient,
|
|
1127
|
+
amount
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
// src/streams/nft-transfer.ts
|
|
1131
|
+
function isNftTransfer(event) {
|
|
1132
|
+
return event.event_type === "nft_transfer";
|
|
1133
|
+
}
|
|
1134
|
+
function decodeNftTransfer(event) {
|
|
1135
|
+
if (!isNftTransfer(event)) {
|
|
1136
|
+
throw new Error(`Expected nft_transfer event, got ${event.event_type}`);
|
|
1137
|
+
}
|
|
1138
|
+
const payload = event.payload;
|
|
1139
|
+
const assetIdentifier = requireString(payload, "asset_identifier", "nft_transfer");
|
|
1140
|
+
const sender = requireString(payload, "sender", "nft_transfer");
|
|
1141
|
+
const recipient = requireString(payload, "recipient", "nft_transfer");
|
|
1142
|
+
const value = requireHexValue(payload, "nft_transfer");
|
|
1143
|
+
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier, "nft_transfer");
|
|
1144
|
+
return decodedRow(event, "nft_transfer", {
|
|
1145
|
+
asset_identifier: assetIdentifier,
|
|
1146
|
+
contract_id: event.contract_id ?? contract_id,
|
|
1147
|
+
token_name,
|
|
1148
|
+
sender,
|
|
1149
|
+
recipient,
|
|
1150
|
+
value
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1196
1153
|
// src/streams/stx-events.ts
|
|
1197
1154
|
function isStxTransfer(event) {
|
|
1198
1155
|
return event.event_type === "stx_transfer";
|
|
@@ -1203,8 +1160,8 @@ function decodeStxTransfer(event) {
|
|
|
1203
1160
|
}
|
|
1204
1161
|
const payload = event.payload;
|
|
1205
1162
|
return decodedRow(event, "stx_transfer", {
|
|
1206
|
-
sender:
|
|
1207
|
-
recipient:
|
|
1163
|
+
sender: requireString(payload, "sender", "stx_transfer"),
|
|
1164
|
+
recipient: requireString(payload, "recipient", "stx_transfer"),
|
|
1208
1165
|
amount: requireAmount(payload, "stx_transfer"),
|
|
1209
1166
|
memo: optionalString(payload.memo)
|
|
1210
1167
|
});
|
|
@@ -1218,7 +1175,7 @@ function decodeStxMint(event) {
|
|
|
1218
1175
|
}
|
|
1219
1176
|
const payload = event.payload;
|
|
1220
1177
|
return decodedRow(event, "stx_mint", {
|
|
1221
|
-
recipient:
|
|
1178
|
+
recipient: requireString(payload, "recipient", "stx_mint"),
|
|
1222
1179
|
amount: requireAmount(payload, "stx_mint")
|
|
1223
1180
|
});
|
|
1224
1181
|
}
|
|
@@ -1231,7 +1188,7 @@ function decodeStxBurn(event) {
|
|
|
1231
1188
|
}
|
|
1232
1189
|
const payload = event.payload;
|
|
1233
1190
|
return decodedRow(event, "stx_burn", {
|
|
1234
|
-
sender:
|
|
1191
|
+
sender: requireString(payload, "sender", "stx_burn"),
|
|
1235
1192
|
amount: requireAmount(payload, "stx_burn")
|
|
1236
1193
|
});
|
|
1237
1194
|
}
|
|
@@ -1244,15 +1201,15 @@ function decodeStxLock(event) {
|
|
|
1244
1201
|
}
|
|
1245
1202
|
const payload = event.payload;
|
|
1246
1203
|
return decodedRow(event, "stx_lock", {
|
|
1247
|
-
sender:
|
|
1204
|
+
sender: requireString(payload, "locked_address", "stx_lock"),
|
|
1248
1205
|
amount: requireAmountField(payload, "locked_amount", "stx_lock"),
|
|
1249
1206
|
payload: { unlock_height: optionalString(payload.unlock_height) }
|
|
1250
1207
|
});
|
|
1251
1208
|
}
|
|
1252
1209
|
// src/streams/token-mint-burn.ts
|
|
1253
1210
|
function assetFields(event, eventType) {
|
|
1254
|
-
const assetIdentifier =
|
|
1255
|
-
const { contract_id, token_name } =
|
|
1211
|
+
const assetIdentifier = requireString(event.payload, "asset_identifier", eventType);
|
|
1212
|
+
const { contract_id, token_name } = parseAssetIdentifier(assetIdentifier, eventType);
|
|
1256
1213
|
return {
|
|
1257
1214
|
asset_identifier: assetIdentifier,
|
|
1258
1215
|
contract_id: event.contract_id ?? contract_id,
|
|
@@ -1268,7 +1225,7 @@ function decodeFtMint(event) {
|
|
|
1268
1225
|
}
|
|
1269
1226
|
return decodedRow(event, "ft_mint", {
|
|
1270
1227
|
...assetFields(event, "ft_mint"),
|
|
1271
|
-
recipient:
|
|
1228
|
+
recipient: requireString(event.payload, "recipient", "ft_mint"),
|
|
1272
1229
|
amount: requireAmount(event.payload, "ft_mint")
|
|
1273
1230
|
});
|
|
1274
1231
|
}
|
|
@@ -1281,7 +1238,7 @@ function decodeFtBurn(event) {
|
|
|
1281
1238
|
}
|
|
1282
1239
|
return decodedRow(event, "ft_burn", {
|
|
1283
1240
|
...assetFields(event, "ft_burn"),
|
|
1284
|
-
sender:
|
|
1241
|
+
sender: requireString(event.payload, "sender", "ft_burn"),
|
|
1285
1242
|
amount: requireAmount(event.payload, "ft_burn")
|
|
1286
1243
|
});
|
|
1287
1244
|
}
|
|
@@ -1294,8 +1251,8 @@ function decodeNftMint(event) {
|
|
|
1294
1251
|
}
|
|
1295
1252
|
return decodedRow(event, "nft_mint", {
|
|
1296
1253
|
...assetFields(event, "nft_mint"),
|
|
1297
|
-
recipient:
|
|
1298
|
-
value:
|
|
1254
|
+
recipient: requireString(event.payload, "recipient", "nft_mint"),
|
|
1255
|
+
value: requireHexValue(event.payload, "nft_mint")
|
|
1299
1256
|
});
|
|
1300
1257
|
}
|
|
1301
1258
|
function isNftBurn(event) {
|
|
@@ -1307,8 +1264,8 @@ function decodeNftBurn(event) {
|
|
|
1307
1264
|
}
|
|
1308
1265
|
return decodedRow(event, "nft_burn", {
|
|
1309
1266
|
...assetFields(event, "nft_burn"),
|
|
1310
|
-
sender:
|
|
1311
|
-
value:
|
|
1267
|
+
sender: requireString(event.payload, "sender", "nft_burn"),
|
|
1268
|
+
value: requireHexValue(event.payload, "nft_burn")
|
|
1312
1269
|
});
|
|
1313
1270
|
}
|
|
1314
1271
|
// src/clarity.ts
|
|
@@ -1379,11 +1336,6 @@ var STREAMS_EVENT_TYPES = [
|
|
|
1379
1336
|
"print"
|
|
1380
1337
|
];
|
|
1381
1338
|
// src/datasets/client.ts
|
|
1382
|
-
function appendParam(params, name, value) {
|
|
1383
|
-
if (value === undefined || value === null)
|
|
1384
|
-
return;
|
|
1385
|
-
params.set(name, String(value));
|
|
1386
|
-
}
|
|
1387
1339
|
var PARAM_KEYS = {
|
|
1388
1340
|
fromBlock: "from_block",
|
|
1389
1341
|
toBlock: "to_block",
|
|
@@ -1424,7 +1376,7 @@ class Datasets extends BaseClient {
|
|
|
1424
1376
|
if (!d) {
|
|
1425
1377
|
throw new Error(`unknown cursor dataset "${slug}" (use one of: ${Object.keys(CURSOR_SLUGS).join(", ")})`);
|
|
1426
1378
|
}
|
|
1427
|
-
const env = await this.get(d.path, this.
|
|
1379
|
+
const env = await this.get(d.path, this.paramsToQuery(params));
|
|
1428
1380
|
return {
|
|
1429
1381
|
rows: env[d.rowKey] ?? [],
|
|
1430
1382
|
next_cursor: env.next_cursor ?? null,
|
|
@@ -1441,40 +1393,37 @@ class Datasets extends BaseClient {
|
|
|
1441
1393
|
bnsNamespaceEvents = this.cursorDataset("bns/namespace-events", "events");
|
|
1442
1394
|
bnsMarketplaceEvents = this.cursorDataset("bns/marketplace-events", "events");
|
|
1443
1395
|
bnsNames(params = {}) {
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1396
|
+
return this.get("bns/names", buildQuery({
|
|
1397
|
+
namespace: params.namespace,
|
|
1398
|
+
owner: params.owner,
|
|
1399
|
+
limit: params.limit,
|
|
1400
|
+
offset: params.offset
|
|
1401
|
+
}));
|
|
1450
1402
|
}
|
|
1451
1403
|
bnsNamespaces() {
|
|
1452
|
-
return this.get("bns/namespaces",
|
|
1404
|
+
return this.get("bns/namespaces", "");
|
|
1453
1405
|
}
|
|
1454
1406
|
bnsResolve(fqn) {
|
|
1455
|
-
|
|
1456
|
-
sp.set("fqn", fqn);
|
|
1457
|
-
return this.get("bns/resolve", sp);
|
|
1407
|
+
return this.get("bns/resolve", buildQuery({ fqn }));
|
|
1458
1408
|
}
|
|
1459
1409
|
networkHealth() {
|
|
1460
|
-
return this.get("network-health/summary",
|
|
1410
|
+
return this.get("network-health/summary", "");
|
|
1461
1411
|
}
|
|
1462
|
-
get(path,
|
|
1463
|
-
|
|
1464
|
-
return this.request("GET", `/v1/datasets/${path}${qs ? `?${qs}` : ""}`);
|
|
1412
|
+
get(path, query) {
|
|
1413
|
+
return this.request("GET", `/v1/datasets/${path}${query}`);
|
|
1465
1414
|
}
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1415
|
+
paramsToQuery(params) {
|
|
1416
|
+
const mapped = {};
|
|
1468
1417
|
for (const [k, v] of Object.entries(params)) {
|
|
1469
1418
|
if (v === undefined || v === null || k === "batchSize" || k === "signal")
|
|
1470
1419
|
continue;
|
|
1471
|
-
|
|
1420
|
+
mapped[PARAM_KEYS[k] ?? k] = v;
|
|
1472
1421
|
}
|
|
1473
|
-
return
|
|
1422
|
+
return buildQuery(mapped);
|
|
1474
1423
|
}
|
|
1475
1424
|
cursorDataset(path, rowKey) {
|
|
1476
1425
|
const list = async (params = {}) => {
|
|
1477
|
-
const envelope = await this.get(path, this.
|
|
1426
|
+
const envelope = await this.get(path, this.paramsToQuery(params));
|
|
1478
1427
|
return {
|
|
1479
1428
|
rows: envelope[rowKey] ?? [],
|
|
1480
1429
|
next_cursor: envelope.next_cursor ?? null,
|
|
@@ -1586,10 +1535,11 @@ export {
|
|
|
1586
1535
|
RateLimitError,
|
|
1587
1536
|
Index,
|
|
1588
1537
|
Datasets,
|
|
1538
|
+
Cursor,
|
|
1589
1539
|
CURSOR_SLUGS,
|
|
1590
1540
|
AuthError,
|
|
1591
1541
|
ApiError
|
|
1592
1542
|
};
|
|
1593
1543
|
|
|
1594
|
-
//# debugId=
|
|
1544
|
+
//# debugId=DF9925BCF7B82FB964756E2164756E21
|
|
1595
1545
|
//# sourceMappingURL=index.js.map
|