@secondlayer/sdk 6.16.0 → 6.18.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 CHANGED
@@ -10,6 +10,10 @@ interface SecondLayerOptions {
10
10
  apiKey?: string;
11
11
  /** Fetch implementation. Tests and edge runtimes can provide their own. */
12
12
  fetchImpl?: FetchLike;
13
+ /** Public base URL for Streams bulk parquet dumps (the cold backfill plane).
14
+ * Required for `streams.dumps.*`; without it the dumps client falls back to
15
+ * its built-in default. */
16
+ dumpsBaseUrl?: string;
13
17
  /** Deploy origin label sent as `x-sl-origin` (telemetry). Defaults to `cli`. */
14
18
  origin?: "cli" | "mcp" | "session";
15
19
  }
@@ -156,6 +160,17 @@ interface CreateApiKeyResponse {
156
160
  tier: string | null;
157
161
  createdAt: string;
158
162
  }
163
+ /** A key as seen by {@link ApiKeys.list} — metadata only, never the plaintext. */
164
+ interface ApiKeySummary {
165
+ id: string;
166
+ prefix: string;
167
+ name: string | null;
168
+ status: "active" | "revoked";
169
+ product: string;
170
+ tier: string | null;
171
+ createdAt: string;
172
+ lastUsedAt: string | null;
173
+ }
159
174
  declare class ApiKeys extends BaseClient {
160
175
  constructor(options?: Partial<SecondLayerOptions>);
161
176
  /**
@@ -164,6 +179,18 @@ declare class ApiKeys extends BaseClient {
164
179
  * only once.
165
180
  */
166
181
  create(params?: CreateApiKeyParams): Promise<CreateApiKeyResponse>;
182
+ /**
183
+ * List the account's keys (metadata only — no plaintext). Requires an
184
+ * account-level (owner) key or a dashboard session.
185
+ */
186
+ list(): Promise<{
187
+ keys: ApiKeySummary[]
188
+ }>;
189
+ /** Revoke a key by id. Existing requests with that key stop working. */
190
+ revoke(id: string): Promise<{
191
+ revoked: true
192
+ id: string
193
+ }>;
167
194
  }
168
195
  /**
169
196
  * Typed client for the contract-discovery API (`GET /v1/contracts`).
@@ -289,13 +316,26 @@ declare const CURSOR_SLUGS: Record<string, {
289
316
  rowKey: string
290
317
  }>;
291
318
  declare class Datasets extends BaseClient {
319
+ private catalogPromise?;
292
320
  constructor(options?: Partial<SecondLayerOptions>);
293
321
  /** Dataset catalog + freshness (the discovery endpoint). */
294
322
  listDatasets(): Promise<unknown>;
295
323
  /**
324
+ * Generic read by slug for ANY catalog dataset — cursor or bespoke. Resolves
325
+ * the slug against the live `/v1/datasets` catalog (so datasets added
326
+ * server-side work with no SDK change), issues the GET, and normalizes the
327
+ * response into a uniform `{ rows, next_cursor, tip }` envelope. Single-object
328
+ * datasets (bns/resolve, network-health/summary) come back as 0-or-1 rows.
329
+ * Accepts both family (`sbtc-events`) and path (`sbtc/events`) slug forms.
330
+ * Prefer this over {@link query} unless you specifically need cursor-only
331
+ * semantics.
332
+ */
333
+ get(slug: string, params?: Record<string, unknown>): Promise<CursorEnvelope>;
334
+ /**
296
335
  * Generic cursor query by slug — used by the CLI. Params are passed through as
297
336
  * REST query keys (snake_case), so callers can use the documented filter names
298
- * directly. Throws for non-cursor (bespoke) datasets.
337
+ * directly. Throws for non-cursor (bespoke) datasets — use {@link get} for
338
+ * those (and for slugs added to the catalog after this SDK was built).
299
339
  */
300
340
  query(slug: string, params?: Record<string, unknown>): Promise<CursorEnvelope>;
301
341
  readonly stxTransfers: CursorDataset<StxTransfersParams>;
@@ -328,7 +368,15 @@ declare class Datasets extends BaseClient {
328
368
  networkHealth(): Promise<{
329
369
  summary: DatasetRow
330
370
  }>;
331
- private get;
371
+ private requestPath;
372
+ /** Resolve a slug → relative path + row key. Known cursor slugs take a
373
+ * network-free fast path; anything else is matched against the live catalog
374
+ * by family name or path tail. */
375
+ private resolveDataset;
376
+ /** Fetch + cache the catalog families. Caches the in-flight promise so
377
+ * concurrent first-calls share one request; no TTL — agent sessions are
378
+ * short-lived, and a new client picks up newly added datasets. */
379
+ private loadCatalog;
332
380
  /** Map camelCase filter fields to snake_case query keys (dropping pagination
333
381
  * controls) and build the canonical query suffix. */
334
382
  private paramsToQuery;
@@ -538,6 +586,9 @@ type EventsListParams = {
538
586
  recipient?: string
539
587
  fromHeight?: number
540
588
  toHeight?: number
589
+ /** Restrict to contracts conforming to a trait/standard (e.g. "sip-010").
590
+ * Mutually exclusive with contractId; contract-keyed event types only. */
591
+ trait?: string
541
592
  };
542
593
  type EventsWalkParams = Omit<EventsListParams, "limit"> & {
543
594
  batchSize?: number
@@ -572,6 +623,9 @@ type ContractCallsListParams = {
572
623
  sender?: string
573
624
  fromHeight?: number
574
625
  toHeight?: number
626
+ /** Restrict to contracts conforming to a trait/standard (e.g. "sip-010").
627
+ * Mutually exclusive with contractId. */
628
+ trait?: string
575
629
  };
576
630
  type ContractCallsWalkParams = Omit<ContractCallsListParams, "limit"> & {
577
631
  batchSize?: number
@@ -828,10 +882,30 @@ type MempoolWalkParams = Omit<MempoolListParams, "limit"> & {
828
882
  batchSize?: number
829
883
  signal?: AbortSignal
830
884
  };
885
+ /** Per-event-type filter vocabulary in the {@link IndexDiscovery} doc. */
886
+ type IndexEventTypeFilters = {
887
+ columns?: string[]
888
+ allowed_filters?: string[]
889
+ equality_filters?: string[]
890
+ required_non_null?: string[]
891
+ };
892
+ /** The `GET /v1/index` discovery doc — live endpoint + filter vocabulary.
893
+ * Shape is intentionally open (the server may add fields); the agent-relevant
894
+ * parts are the per-type filter rules. */
895
+ type IndexDiscovery = {
896
+ event_type_filters?: Record<string, IndexEventTypeFilters>
897
+ [key: string]: unknown
898
+ };
831
899
  declare class Index extends BaseClient {
832
900
  constructor(options?: Partial<SecondLayerOptions>);
833
901
  /** Your own Index consumption (decoded events today + this month) and tier limits. */
834
902
  usage(): Promise<IndexUsage>;
903
+ /**
904
+ * Index discovery doc — the live vocabulary: every endpoint, each event type's
905
+ * columns, allowed/equality filters, and required-non-null fields. Read this to
906
+ * learn what's queryable (and which types accept `trait`) instead of hardcoding.
907
+ */
908
+ discover(): Promise<IndexDiscovery>;
835
909
  readonly ftTransfers: {
836
910
  list: (params?: FtTransfersListParams) => Promise<FtTransfersEnvelope>
837
911
  walk: (params?: FtTransfersWalkParams) => AsyncIterable<FtTransfer>
@@ -903,6 +977,76 @@ declare class Index extends BaseClient {
903
977
  private getMempoolTx;
904
978
  private walkMempool;
905
979
  }
980
+ /**
981
+ * Typed client for project management (`/api/projects/*`).
982
+ *
983
+ * Projects are the account-scoped containers for work. Every method requires an
984
+ * account-level (owner) API key or a dashboard session — scoped read keys are
985
+ * rejected. Team mutations (invite/remove/role) are intentionally not exposed
986
+ * here; only the read view ({@link Projects.team}) is.
987
+ */
988
+ interface Project {
989
+ id: string;
990
+ name: string;
991
+ slug: string;
992
+ network: string;
993
+ nodeRpc: string | null;
994
+ settings: Record<string, unknown> | null;
995
+ createdAt: string;
996
+ updatedAt: string;
997
+ }
998
+ interface ProjectTeamMember {
999
+ id: string;
1000
+ role: string;
1001
+ email: string;
1002
+ displayName: string | null;
1003
+ avatarUrl: string | null;
1004
+ createdAt: string;
1005
+ }
1006
+ interface ProjectInvitation {
1007
+ id: string;
1008
+ email: string;
1009
+ role: string;
1010
+ expiresAt: string;
1011
+ createdAt: string;
1012
+ }
1013
+ interface ProjectTeam {
1014
+ members: ProjectTeamMember[];
1015
+ invitations: ProjectInvitation[];
1016
+ }
1017
+ interface CreateProjectParams {
1018
+ name: string;
1019
+ slug?: string;
1020
+ network?: string;
1021
+ nodeRpc?: string;
1022
+ }
1023
+ interface UpdateProjectParams {
1024
+ name?: string;
1025
+ /** Rename the project's URL slug. */
1026
+ slug?: string;
1027
+ network?: string;
1028
+ nodeRpc?: string;
1029
+ settings?: Record<string, unknown>;
1030
+ }
1031
+ declare class Projects extends BaseClient {
1032
+ constructor(options?: Partial<SecondLayerOptions>);
1033
+ /** All projects owned by the account, newest-relevant first. */
1034
+ list(): Promise<{
1035
+ projects: Project[]
1036
+ }>;
1037
+ /** A single project by slug. */
1038
+ get(slug: string): Promise<Project>;
1039
+ /** Create a project. The creator is added as the project owner. */
1040
+ create(params: CreateProjectParams): Promise<Project>;
1041
+ /** Update a project's name, slug (rename), network, RPC, or settings. */
1042
+ update(slug: string, patch: UpdateProjectParams): Promise<Project>;
1043
+ /** Delete a project. The account's last remaining project cannot be deleted. */
1044
+ delete(slug: string): Promise<{
1045
+ ok: true
1046
+ }>;
1047
+ /** Team members and pending invitations for a project. */
1048
+ team(slug: string): Promise<ProjectTeam>;
1049
+ }
906
1050
  import { StreamsEventType } from "@secondlayer/shared";
907
1051
  /** A Clarity value as Streams serves it: the canonical hex string, a typed
908
1052
  * object carrying that hex (`{ hex }`), or a decoded Clarity-JSON object.
@@ -1308,6 +1452,7 @@ declare class Subscriptions extends BaseClient {
1308
1452
  replay(id: string, range: {
1309
1453
  fromBlock: number
1310
1454
  toBlock: number
1455
+ force?: string
1311
1456
  }): Promise<ReplayResult>;
1312
1457
  dead(id: string): Promise<{
1313
1458
  data: DeadRow[]
@@ -1320,6 +1465,19 @@ interface ContextAccount {
1320
1465
  email: string;
1321
1466
  plan: string;
1322
1467
  }
1468
+ /** Compact project view for {@link ContextSnapshot}. */
1469
+ interface ContextProject {
1470
+ name: string;
1471
+ slug: string;
1472
+ network: string;
1473
+ }
1474
+ /** Compact API-key view for {@link ContextSnapshot} — never the plaintext. */
1475
+ interface ContextApiKey {
1476
+ prefix: string;
1477
+ name: string | null;
1478
+ status: string;
1479
+ product: string;
1480
+ }
1323
1481
  interface ActiveSubgraphOperation {
1324
1482
  subgraph: string;
1325
1483
  operationId: string;
@@ -1341,6 +1499,10 @@ interface ContextSnapshot {
1341
1499
  count: number
1342
1500
  byStatus: Record<string, number>
1343
1501
  } | null;
1502
+ /** The account's projects (null when unreadable — e.g. a scoped key). */
1503
+ projects: ContextProject[] | null;
1504
+ /** The account's API keys, metadata only (null when unreadable). */
1505
+ apiKeys: ContextApiKey[] | null;
1344
1506
  /** In-flight reindex operations (bounded to subgraphs reporting `reindexing`). */
1345
1507
  activeOperations: ActiveSubgraphOperation[] | null;
1346
1508
  }
@@ -1352,6 +1514,7 @@ declare class SecondLayer extends BaseClient {
1352
1514
  readonly subgraphs: Subgraphs;
1353
1515
  readonly subscriptions: Subscriptions;
1354
1516
  readonly apiKeys: ApiKeys;
1517
+ readonly projects: Projects;
1355
1518
  constructor(options?: Partial<SecondLayerOptions>);
1356
1519
  /**
1357
1520
  * Assemble a {@link ContextSnapshot} — the same orientation an MCP agent reads
@@ -1949,4 +2112,4 @@ declare function toJsonSafe(value: unknown): unknown;
1949
2112
  /** Decode a hex-encoded Clarity value to JSON-safe JS (uints as strings,
1950
2113
  * buffers as `0x…` hex, tuples as objects). Returns the input hex on failure. */
1951
2114
  declare function decodeClarityValue(hex: string): unknown;
1952
- export { verifyWebhookSignature, verifyTransactionProof, verifySecondlayerSignature, trigger, toJsonSafe, isStxTransfer, isStxMint, isStxLock, isStxBurn, isPrint, isNftTransfer, isNftMint, isNftBurn, isFtTransfer, isFtMint, isFtBurn, getSubgraph, fetchRewardSet, decodeStxTransfer, decodeStxMint, decodeStxLock, decodeStxBurn, decodePrint, decodeNftTransfer, decodeNftMint, decodeNftBurn, decodeFtTransfer, decodeFtMint, decodeFtBurn, decodeClarityValue, createStreamsClient, VersionConflictError, ValidationError, UpdateSubscriptionRequest2 as UpdateSubscriptionRequest, TransactionsWalkParams, TransactionsListParams, TransactionsEnvelope, TransactionProofVerifyResult, TransactionProof, TransactionEnvelope, Subscriptions, SubscriptionSummary2 as SubscriptionSummary, SubscriptionStatus, SubscriptionRuntime, SubscriptionKind, SubscriptionFormat, SubscriptionDetail2 as SubscriptionDetail, Subgraphs, SubgraphSpecOptions3 as SubgraphSpecOptions, SubgraphSpecFormat2 as SubgraphSpecFormat, SubgraphOperationStatus, SubgraphAgentSchema3 as SubgraphAgentSchema, StreamsUsage, StreamsTip, StreamsSignatureError, StreamsServerError, StreamsReorgsListParams, StreamsReorgsListEnvelope, StreamsReorgContext, StreamsReorg, StreamsEventsSubscribeParams, StreamsEventsStreamParams, StreamsEventsListParams, StreamsEventsListEnvelope, StreamsEventsEnvelope, StreamsEventsConsumeResult, StreamsEventsConsumeParams, StreamsEventType, StreamsEventPayload, StreamsEvent, StreamsDumpsManifest, StreamsDumps, StreamsDumpFile, StreamsClient, StreamsCanonicalBlock, StreamsBatchContext, StackingWalkParams, StackingListParams, StackingEnvelope, SecondLayerOptions, SecondLayer, ScopedKeyProduct, RotateSecretResponse2 as RotateSecretResponse, RewardSet2 as RewardSet, ReplayResult2 as ReplayResult, RateLimitError, Pox4CallsParams, NftTransfersWalkParams, NftTransfersListParams, NftTransfersEnvelope, NftTransferPayload, NftTransferEvent, NftTransfer, MempoolWalkParams, MempoolTransactionEnvelope, MempoolListParams, MempoolEnvelope, IndexUsage, IndexTransaction, IndexTip, IndexStackingAction, IndexReorg, IndexPostCondition, IndexMempoolTransaction, IndexEventType, IndexEvent, IndexContractCall, IndexCanonicalBlock, IndexBlock, Index, FtTransfersWalkParams, FtTransfersListParams, FtTransfersEnvelope, FtTransferPayload, FtTransferEvent, FtTransfer, FetchLike2 as FetchLike, EventsWalkParams, EventsListParams, EventsEnvelope, DeliveryRow2 as DeliveryRow, DecodedStxTransferPayload, DecodedStxTransfer, DecodedStxMintPayload, DecodedStxMint, DecodedStxLockPayload, DecodedStxLock, DecodedStxBurnPayload, DecodedStxBurn, DecodedPrintValue, DecodedPrintPayload, DecodedPrint, DecodedNftTransferPayload, DecodedNftTransfer, DecodedNftMintPayload, DecodedNftMint, DecodedNftBurnPayload, DecodedNftBurn, DecodedFtTransferPayload, DecodedFtTransfer, DecodedFtMintPayload, DecodedFtMint, DecodedFtBurnPayload, DecodedFtBurn, DecodedEventRow, DecodedEventColumns, DeadRow2 as DeadRow, Datasets, DatasetRow, CursorListParams, CursorEnvelope, Cursor, CreateSubscriptionResponse2 as CreateSubscriptionResponse, CreateSubscriptionRequest2 as CreateSubscriptionRequest, CreateApiKeyResponse, CreateApiKeyParams, ContractsListParams, ContractsEnvelope, Contracts, ContractSummary, ContractConformance, ContractCallsWalkParams, ContractCallsListParams, ContractCallsEnvelope, ContextSnapshot, ContextAccount, ChainTriggerType, ChainTrigger, CanonicalWalkParams, CanonicalListParams, CanonicalEnvelope, CURSOR_SLUGS, ByoBreakingChangeError, ByoBreakingChangeDetails, BlocksWalkParams, BlocksListParams, BlocksEnvelope, BlockEnvelope, AuthError, ApiKeys, ApiError, ActiveSubgraphOperation };
2115
+ export { verifyWebhookSignature, verifyTransactionProof, verifySecondlayerSignature, trigger, toJsonSafe, isStxTransfer, isStxMint, isStxLock, isStxBurn, isPrint, isNftTransfer, isNftMint, isNftBurn, isFtTransfer, isFtMint, isFtBurn, getSubgraph, fetchRewardSet, decodeStxTransfer, decodeStxMint, decodeStxLock, decodeStxBurn, decodePrint, decodeNftTransfer, decodeNftMint, decodeNftBurn, decodeFtTransfer, decodeFtMint, decodeFtBurn, decodeClarityValue, createStreamsClient, VersionConflictError, ValidationError, UpdateSubscriptionRequest2 as UpdateSubscriptionRequest, UpdateProjectParams, TransactionsWalkParams, TransactionsListParams, TransactionsEnvelope, TransactionProofVerifyResult, TransactionProof, TransactionEnvelope, Subscriptions, SubscriptionSummary2 as SubscriptionSummary, SubscriptionStatus, SubscriptionRuntime, SubscriptionKind, SubscriptionFormat, SubscriptionDetail2 as SubscriptionDetail, Subgraphs, SubgraphSpecOptions3 as SubgraphSpecOptions, SubgraphSpecFormat2 as SubgraphSpecFormat, SubgraphOperationStatus, SubgraphAgentSchema3 as SubgraphAgentSchema, StreamsUsage, StreamsTip, StreamsSignatureError, StreamsServerError, StreamsReorgsListParams, StreamsReorgsListEnvelope, StreamsReorgContext, StreamsReorg, StreamsEventsSubscribeParams, StreamsEventsStreamParams, StreamsEventsListParams, StreamsEventsListEnvelope, StreamsEventsEnvelope, StreamsEventsConsumeResult, StreamsEventsConsumeParams, StreamsEventType, StreamsEventPayload, StreamsEvent, StreamsDumpsManifest, StreamsDumps, StreamsDumpFile, StreamsClient, StreamsCanonicalBlock, StreamsBatchContext, StackingWalkParams, StackingListParams, StackingEnvelope, SecondLayerOptions, SecondLayer, ScopedKeyProduct, RotateSecretResponse2 as RotateSecretResponse, RewardSet2 as RewardSet, ReplayResult2 as ReplayResult, RateLimitError, Projects, ProjectTeamMember, ProjectTeam, ProjectInvitation, Project, Pox4CallsParams, NftTransfersWalkParams, NftTransfersListParams, NftTransfersEnvelope, NftTransferPayload, NftTransferEvent, NftTransfer, MempoolWalkParams, MempoolTransactionEnvelope, MempoolListParams, MempoolEnvelope, IndexUsage, IndexTransaction, IndexTip, IndexStackingAction, IndexReorg, IndexPostCondition, IndexMempoolTransaction, IndexEventTypeFilters, IndexEventType, IndexEvent, IndexDiscovery, IndexContractCall, IndexCanonicalBlock, IndexBlock, Index, FtTransfersWalkParams, FtTransfersListParams, FtTransfersEnvelope, FtTransferPayload, FtTransferEvent, FtTransfer, FetchLike2 as FetchLike, EventsWalkParams, EventsListParams, EventsEnvelope, DeliveryRow2 as DeliveryRow, DecodedStxTransferPayload, DecodedStxTransfer, DecodedStxMintPayload, DecodedStxMint, DecodedStxLockPayload, DecodedStxLock, DecodedStxBurnPayload, DecodedStxBurn, DecodedPrintValue, DecodedPrintPayload, DecodedPrint, DecodedNftTransferPayload, DecodedNftTransfer, DecodedNftMintPayload, DecodedNftMint, DecodedNftBurnPayload, DecodedNftBurn, DecodedFtTransferPayload, DecodedFtTransfer, DecodedFtMintPayload, DecodedFtMint, DecodedFtBurnPayload, DecodedFtBurn, DecodedEventRow, DecodedEventColumns, DeadRow2 as DeadRow, Datasets, DatasetRow, CursorListParams, CursorEnvelope, Cursor, CreateSubscriptionResponse2 as CreateSubscriptionResponse, CreateSubscriptionRequest2 as CreateSubscriptionRequest, CreateProjectParams, CreateApiKeyResponse, CreateApiKeyParams, ContractsListParams, ContractsEnvelope, Contracts, ContractSummary, ContractConformance, ContractCallsWalkParams, ContractCallsListParams, ContractCallsEnvelope, ContextSnapshot, ContextProject, ContextApiKey, ContextAccount, ChainTriggerType, ChainTrigger, CanonicalWalkParams, CanonicalListParams, CanonicalEnvelope, CURSOR_SLUGS, ByoBreakingChangeError, ByoBreakingChangeDetails, BlocksWalkParams, BlocksListParams, BlocksEnvelope, BlockEnvelope, AuthError, ApiKeys, ApiKeySummary, ApiError, ActiveSubgraphOperation };
package/dist/index.js CHANGED
@@ -395,6 +395,12 @@ class ApiKeys extends BaseClient {
395
395
  name: params.name
396
396
  });
397
397
  }
398
+ list() {
399
+ return this.request("GET", "/api/keys");
400
+ }
401
+ revoke(id) {
402
+ return this.request("DELETE", `/api/keys/${id}`);
403
+ }
398
404
  }
399
405
 
400
406
  // src/contracts/client.ts
@@ -441,20 +447,35 @@ var CURSOR_SLUGS = {
441
447
  rowKey: "events"
442
448
  }
443
449
  };
450
+ function catalogPathTail(path) {
451
+ return path.replace(/^\/?v1\/datasets\//, "").replace(/^\/+/, "");
452
+ }
444
453
 
445
454
  class Datasets extends BaseClient {
455
+ catalogPromise;
446
456
  constructor(options = {}) {
447
457
  super(options);
448
458
  }
449
459
  listDatasets() {
450
460
  return this.request("GET", "/v1/datasets");
451
461
  }
462
+ async get(slug, params = {}) {
463
+ const { path, rowKey } = await this.resolveDataset(slug);
464
+ const env = await this.requestPath(path, this.paramsToQuery(params));
465
+ const value = env[rowKey];
466
+ const rows = Array.isArray(value) ? value : value == null ? [] : [value];
467
+ return {
468
+ rows,
469
+ next_cursor: env.next_cursor ?? null,
470
+ tip: env.tip
471
+ };
472
+ }
452
473
  async query(slug, params = {}) {
453
474
  const d = CURSOR_SLUGS[slug];
454
475
  if (!d) {
455
476
  throw new Error(`unknown cursor dataset "${slug}" (use one of: ${Object.keys(CURSOR_SLUGS).join(", ")})`);
456
477
  }
457
- const env = await this.get(d.path, this.paramsToQuery(params));
478
+ const env = await this.requestPath(d.path, this.paramsToQuery(params));
458
479
  return {
459
480
  rows: env[d.rowKey] ?? [],
460
481
  next_cursor: env.next_cursor ?? null,
@@ -471,7 +492,7 @@ class Datasets extends BaseClient {
471
492
  bnsNamespaceEvents = this.cursorDataset("bns/namespace-events", "events");
472
493
  bnsMarketplaceEvents = this.cursorDataset("bns/marketplace-events", "events");
473
494
  bnsNames(params = {}) {
474
- return this.get("bns/names", buildQuery({
495
+ return this.requestPath("bns/names", buildQuery({
475
496
  namespace: params.namespace,
476
497
  owner: params.owner,
477
498
  limit: params.limit,
@@ -479,17 +500,40 @@ class Datasets extends BaseClient {
479
500
  }));
480
501
  }
481
502
  bnsNamespaces() {
482
- return this.get("bns/namespaces", "");
503
+ return this.requestPath("bns/namespaces", "");
483
504
  }
484
505
  bnsResolve(fqn) {
485
- return this.get("bns/resolve", buildQuery({ fqn }));
506
+ return this.requestPath("bns/resolve", buildQuery({ fqn }));
486
507
  }
487
508
  networkHealth() {
488
- return this.get("network-health/summary", "");
509
+ return this.requestPath("network-health/summary", "");
489
510
  }
490
- get(path, query) {
511
+ requestPath(path, query) {
491
512
  return this.request("GET", `/v1/datasets/${path}${query}`);
492
513
  }
514
+ async resolveDataset(slug) {
515
+ const cursor = CURSOR_SLUGS[slug];
516
+ if (cursor)
517
+ return { path: cursor.path, rowKey: cursor.rowKey };
518
+ const families = await this.loadCatalog();
519
+ const tail = catalogPathTail(slug);
520
+ const match = families.find((f) => f.family === slug || catalogPathTail(f.path) === tail);
521
+ if (!match) {
522
+ throw new Error(`unknown dataset "${slug}" (available: ${families.map((f) => f.family).join(", ")})`);
523
+ }
524
+ return { path: catalogPathTail(match.path), rowKey: match.row_key };
525
+ }
526
+ loadCatalog() {
527
+ this.catalogPromise ??= (async () => {
528
+ const raw = await this.listDatasets();
529
+ const families = raw.families;
530
+ if (!Array.isArray(families)) {
531
+ throw new Error("dataset catalog response missing families[]");
532
+ }
533
+ return families;
534
+ })();
535
+ return this.catalogPromise;
536
+ }
493
537
  paramsToQuery(params) {
494
538
  const mapped = {};
495
539
  for (const [k, v] of Object.entries(params)) {
@@ -501,7 +545,7 @@ class Datasets extends BaseClient {
501
545
  }
502
546
  cursorDataset(path, rowKey) {
503
547
  const list = async (params = {}) => {
504
- const envelope = await this.get(path, this.paramsToQuery(params));
548
+ const envelope = await this.requestPath(path, this.paramsToQuery(params));
505
549
  return {
506
550
  rows: envelope[rowKey] ?? [],
507
551
  next_cursor: envelope.next_cursor ?? null,
@@ -549,6 +593,9 @@ class Index extends BaseClient {
549
593
  usage() {
550
594
  return this.request("GET", "/v1/index/usage");
551
595
  }
596
+ discover() {
597
+ return this.request("GET", "/v1/index");
598
+ }
552
599
  ftTransfers = {
553
600
  list: (params = {}) => this.listFtTransfers(params),
554
601
  walk: (params = {}) => this.walkFtTransfers(params)
@@ -674,7 +721,8 @@ class Index extends BaseClient {
674
721
  sender: params.sender,
675
722
  recipient: params.recipient,
676
723
  from_height: params.fromHeight,
677
- to_height: params.toHeight
724
+ to_height: params.toHeight,
725
+ trait: params.trait
678
726
  })}`);
679
727
  }
680
728
  async* walkEvents(params) {
@@ -711,7 +759,8 @@ class Index extends BaseClient {
711
759
  function_name: params.functionName,
712
760
  sender: params.sender,
713
761
  from_height: params.fromHeight,
714
- to_height: params.toHeight
762
+ to_height: params.toHeight,
763
+ trait: params.trait
715
764
  })}`);
716
765
  }
717
766
  async* walkContractCalls(params = {}) {
@@ -944,6 +993,31 @@ class Index extends BaseClient {
944
993
  }
945
994
  }
946
995
 
996
+ // src/projects/client.ts
997
+ class Projects extends BaseClient {
998
+ constructor(options = {}) {
999
+ super(options);
1000
+ }
1001
+ list() {
1002
+ return this.request("GET", "/api/projects");
1003
+ }
1004
+ get(slug) {
1005
+ return this.request("GET", `/api/projects/${slug}`);
1006
+ }
1007
+ create(params) {
1008
+ return this.request("POST", "/api/projects", params);
1009
+ }
1010
+ update(slug, patch) {
1011
+ return this.request("PATCH", `/api/projects/${slug}`, patch);
1012
+ }
1013
+ delete(slug) {
1014
+ return this.request("DELETE", `/api/projects/${slug}`);
1015
+ }
1016
+ team(slug) {
1017
+ return this.request("GET", `/api/projects/${slug}/team`);
1018
+ }
1019
+ }
1020
+
947
1021
  // src/streams/client.ts
948
1022
  import { ed25519 as ed255192 } from "@secondlayer/shared";
949
1023
 
@@ -1622,12 +1696,14 @@ class SecondLayer extends BaseClient {
1622
1696
  subgraphs;
1623
1697
  subscriptions;
1624
1698
  apiKeys;
1699
+ projects;
1625
1700
  constructor(options = {}) {
1626
1701
  super(options);
1627
1702
  this.streams = createStreamsClient({
1628
1703
  apiKey: options.apiKey ?? "",
1629
1704
  baseUrl: options.baseUrl,
1630
- fetchImpl: options.fetchImpl
1705
+ fetchImpl: options.fetchImpl,
1706
+ dumpsBaseUrl: options.dumpsBaseUrl
1631
1707
  });
1632
1708
  this.index = new Index(options);
1633
1709
  this.datasets = new Datasets(options);
@@ -1635,15 +1711,26 @@ class SecondLayer extends BaseClient {
1635
1711
  this.subgraphs = new Subgraphs(options);
1636
1712
  this.subscriptions = new Subscriptions(options);
1637
1713
  this.apiKeys = new ApiKeys(options);
1714
+ this.projects = new Projects(options);
1638
1715
  }
1639
1716
  async context() {
1640
1717
  const safe = (p) => p.then((v) => v).catch(() => null);
1641
- const [account, streamsTip, indexEnv, subgraphsRes, subscriptionsRes] = await Promise.all([
1718
+ const [
1719
+ account,
1720
+ streamsTip,
1721
+ indexEnv,
1722
+ subgraphsRes,
1723
+ subscriptionsRes,
1724
+ projectsRes,
1725
+ apiKeysRes
1726
+ ] = await Promise.all([
1642
1727
  safe(this.request("GET", "/api/accounts/me")),
1643
1728
  safe(this.streams.tip()),
1644
1729
  safe(this.index.canonical.list({ limit: 1 })),
1645
1730
  safe(this.subgraphs.list()),
1646
- safe(this.subscriptions.list())
1731
+ safe(this.subscriptions.list()),
1732
+ safe(this.projects.list()),
1733
+ safe(this.apiKeys.list())
1647
1734
  ]);
1648
1735
  const subgraphs = subgraphsRes?.data ?? null;
1649
1736
  let subscriptions = null;
@@ -1669,12 +1756,25 @@ class SecondLayer extends BaseClient {
1669
1756
  }));
1670
1757
  activeOperations = probed.filter((o) => o !== null);
1671
1758
  }
1759
+ const projects = projectsRes ? projectsRes.projects.map((p) => ({
1760
+ name: p.name,
1761
+ slug: p.slug,
1762
+ network: p.network
1763
+ })) : null;
1764
+ const apiKeys = apiKeysRes ? apiKeysRes.keys.map((k) => ({
1765
+ prefix: k.prefix,
1766
+ name: k.name,
1767
+ status: k.status,
1768
+ product: k.product
1769
+ })) : null;
1672
1770
  return {
1673
1771
  account,
1674
1772
  streamsTip,
1675
1773
  indexTip: indexEnv?.tip ?? null,
1676
1774
  subgraphs,
1677
1775
  subscriptions,
1776
+ projects,
1777
+ apiKeys,
1678
1778
  activeOperations
1679
1779
  };
1680
1780
  }
@@ -2137,6 +2237,7 @@ export {
2137
2237
  StreamsServerError,
2138
2238
  SecondLayer,
2139
2239
  RateLimitError,
2240
+ Projects,
2140
2241
  Index,
2141
2242
  Datasets,
2142
2243
  Cursor,
@@ -2148,5 +2249,5 @@ export {
2148
2249
  ApiError
2149
2250
  };
2150
2251
 
2151
- //# debugId=997245D8D7EE2D5664756E2164756E21
2252
+ //# debugId=DBAA238399806ED364756E2164756E21
2152
2253
  //# sourceMappingURL=index.js.map