@secondlayer/sdk 6.36.0 → 6.37.1

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
@@ -285,6 +285,8 @@ declare class Contracts extends BaseClient {
285
285
  includeAbi?: boolean
286
286
  }): Promise<ContractSummary | null>;
287
287
  }
288
+ import { Pox5EventTopic } from "@secondlayer/stacks/pox5";
289
+ import { SbtcEventTopic } from "@secondlayer/stacks/sbtc";
288
290
  import { InferredTopicSchema } from "@secondlayer/subgraphs";
289
291
  import { RewardSet } from "@secondlayer/shared/node/consensus";
290
292
  import { MerkleProofStep } from "@secondlayer/shared/node/nakamoto";
@@ -641,6 +643,18 @@ type StreamsEventsConsumeParams = {
641
643
  * stale rows from an orphaned fork are left in place).
642
644
  */
643
645
  onReorg?: (reorg: StreamsReorg, ctx: StreamsReorgContext) => Promise<void> | void
646
+ /** Page-fetch retries after the first failure (429/5xx/network only —
647
+ * 4xx and handler throws always propagate). Default 3; `0` disables. */
648
+ retryCount?: number
649
+ /** Base retry delay in ms; the n-th retry waits `retryDelay * n`. A server
650
+ * `Retry-After` overrides it. Default 1000. */
651
+ retryDelay?: number
652
+ /** Void observer, called before each retry sleep (metrics/logging). */
653
+ onError?: (err: unknown, ctx: {
654
+ attempt: number
655
+ retriesLeft: number
656
+ delayMs: number
657
+ }) => void
644
658
  emptyBackoffMs?: number
645
659
  maxPages?: number
646
660
  maxEmptyPolls?: number
@@ -829,6 +843,23 @@ type StreamsUsage = {
829
843
  }
830
844
  };
831
845
  type Sleep = (ms: number, signal?: AbortSignal) => Promise<void>;
846
+ /** Options shared by both consume loops' page-fetch retry. Vocabulary matches
847
+ * `@secondlayer/stacks` transports (`retryCount`/`retryDelay`) — one retry
848
+ * language across the family, not a third. */
849
+ type PageRetryOptions = {
850
+ /** Retries after the first failure. Default 3; `0` disables. */
851
+ retryCount?: number
852
+ /** Base delay in ms; the n-th retry waits `retryDelay * n` (matches the
853
+ * stacks transport). A server `Retry-After` overrides it. Default 1000. */
854
+ retryDelay?: number
855
+ /** Void observer, called before each retry sleep (metrics/logging). The
856
+ * retry policy owns the decision; this cannot change it. */
857
+ onError?: (err: unknown, ctx: {
858
+ attempt: number
859
+ retriesLeft: number
860
+ delayMs: number
861
+ }) => void
862
+ };
832
863
  /** Minimum shape a consumed Index row must expose. */
833
864
  type IndexFeedItem = {
834
865
  cursor: string
@@ -878,6 +909,15 @@ type IndexConsumeOptions<
878
909
  maxPages?: number
879
910
  maxEmptyPolls?: number
880
911
  signal?: AbortSignal
912
+ /** Page-fetch retries after the first failure (429/5xx/network only —
913
+ * 4xx and handler throws always propagate). Default 3; `0` disables. */
914
+ retryCount?: number
915
+ /** Base retry delay in ms; the n-th retry waits `retryDelay * n`. A server
916
+ * `Retry-After` overrides it. Default 1000. */
917
+ retryDelay?: number
918
+ /** Void observer, called before each retry sleep. Cannot change the retry
919
+ * decision — the policy owns it. */
920
+ onError?: PageRetryOptions["onError"]
881
921
  };
882
922
  /**
883
923
  * Checkpointed pull loop over a cursor-paginated Index feed — the Index port
@@ -900,6 +940,7 @@ declare function consumeIndexFeed<
900
940
  pages: number
901
941
  emptyPolls: number
902
942
  }>;
943
+ import { SbtcEventTopic as SbtcEventTopic2 } from "@secondlayer/stacks/sbtc";
903
944
  type IndexTip = {
904
945
  block_height: number
905
946
  /** Highest height treated as immutable (past the burn-confirmation
@@ -1458,8 +1499,6 @@ type PrintSchemaResponse = {
1458
1499
  }
1459
1500
  tip: IndexTip
1460
1501
  };
1461
- /** The decoded `sbtc_events` topics. */
1462
- type SbtcEventTopic = "completed-deposit" | "withdrawal-create" | "withdrawal-accept" | "withdrawal-reject" | "key-rotation" | "update-protocol-contract";
1463
1502
  type SbtcWithdrawalStatus = "REQUESTED" | "ACCEPTED" | "REJECTED";
1464
1503
  /** A completed sBTC peg-in, keyed by `bitcoin_txid` (deposits carry no
1465
1504
  * `request_id`). One terminal `completed-deposit` event per deposit. */
@@ -1749,10 +1788,10 @@ interface PoxResource {
1749
1788
  get(rewardCycle: number): Promise<PoxCycleEnvelope | null>
1750
1789
  };
1751
1790
  }
1752
- /** The decoded `pox-5` boot-contract print topics (SIP-045 Bitcoin Staking).
1753
- * Declared locally rather than imported from the server packages — the SDK is
1754
- * published and owns its own dependency surface (same as {@link SbtcEventTopic}). */
1755
- type IndexPox5EventTopic = "set-bond-admin" | "set-pause-admin" | "pause-rewards" | "setup-bond" | "add-to-allowlist" | "register-for-bond" | "update-bond-registration" | "register-signer" | "stake" | "stake-update" | "announce-l1-early-exit" | "unstake-sbtc" | "unstake" | "calculate-rewards" | "bond-distribution" | "claim-rewards" | "claim-staker-rewards-for-signer" | "grant-signer-key" | "revoke-signer-grant";
1791
+ /** The decoded `pox-5` boot-contract print topics (SIP-045 Bitcoin Staking) —
1792
+ * one source of truth in `@secondlayer/stacks/pox5` (already a dependency;
1793
+ * the old "SDK owns its own dependency surface" rationale predated that). */
1794
+ type IndexPox5EventTopic = Pox5EventTopic;
1756
1795
  /** A raw decoded PoX-5 print event. Promoted fields cover the hot query paths;
1757
1796
  * `data` always carries the full decoded tuple, including nested shapes
1758
1797
  * (`btc-lockup`, `bond-rewards`, `bond-periods`) that have no flat column. */
@@ -2217,27 +2256,141 @@ type CreateStreamsClientOptions = {
2217
2256
  verifyDumpsManifest?: boolean
2218
2257
  };
2219
2258
  declare function createStreamsClient(options: CreateStreamsClientOptions): StreamsClient;
2220
- declare class AuthError extends Error {
2221
- readonly status = 401;
2259
+ import { ByoBreakingChangeDetails } from "@secondlayer/shared/errors";
2260
+ /** Options accepted by every error in the family. */
2261
+ interface SecondLayerErrorOptions {
2262
+ cause?: Error;
2263
+ details?: string;
2264
+ /** Stable machine-readable code (e.g. `UPGRADE_REQUIRED`, `BYO_BREAKING_CHANGE`). */
2265
+ code?: string;
2266
+ /** Docs page that explains this failure and its fix. */
2267
+ docsUrl?: string;
2268
+ /** Extra context lines appended to the message (DDL to run, next steps). */
2269
+ metaMessages?: string[];
2270
+ /** Whether retrying the SAME request can succeed (429/5xx/network). */
2271
+ retryable?: boolean;
2272
+ /** Parsed `Retry-After`, in seconds — set on rate limits that carry it. */
2273
+ retryAfterSeconds?: number;
2274
+ }
2275
+ /**
2276
+ * Root of the SDK error family. Implements the same protocol as `BaseError`
2277
+ * in `@secondlayer/stacks` (`shortMessage`, `cause`, `toJSON`) so a failed
2278
+ * chain read and a failed platform read serialize and introspect identically.
2279
+ * It intentionally does NOT extend that class: `BaseError.details` is a
2280
+ * `string`, while {@link ByoBreakingChangeError.details} is the documented
2281
+ * structured migration plan — and cross-package `instanceof` is unreliable
2282
+ * under per-package bundling anyway (match on `code`/`name` across packages).
2283
+ *
2284
+ * `retryable` is the signal the consume loops act on: 429/5xx/network are
2285
+ * retryable, 4xx and body-serialization failures are not.
2286
+ */
2287
+ declare class SecondLayerError extends Error {
2288
+ name: string;
2289
+ /** The one-line failure, without the appended context blocks. */
2290
+ shortMessage: string;
2291
+ code?: string;
2292
+ docsUrl?: string;
2293
+ metaMessages?: string[];
2294
+ retryable: boolean;
2295
+ retryAfterSeconds?: number;
2296
+ constructor(shortMessage: string, options?: SecondLayerErrorOptions);
2297
+ /**
2298
+ * Walk the cause chain. With a predicate, returns the first error matching
2299
+ * it (or `null`); without one, returns the deepest cause. Mirrors viem's
2300
+ * `error.walk()` so cross-library error handling reads the same.
2301
+ */
2302
+ walk(fn?: (err: unknown) => boolean): unknown;
2303
+ toJSON(): {
2304
+ name: string
2305
+ message: string
2306
+ shortMessage: string
2307
+ cause: string | undefined
2308
+ code: string | undefined
2309
+ docsUrl: string | undefined
2310
+ retryable: boolean
2311
+ retryAfterSeconds: number | undefined
2312
+ };
2313
+ }
2314
+ /**
2315
+ * Error thrown by {@link SecondLayer} when an API request fails.
2316
+ * Includes the HTTP status code for programmatic error handling.
2317
+ *
2318
+ * @example
2319
+ * ```ts
2320
+ * try {
2321
+ * await client.subgraphs.get("my-subgraph");
2322
+ * } catch (err) {
2323
+ * if (err instanceof ApiError && err.status === 404) {
2324
+ * console.log("Subgraph not found");
2325
+ * }
2326
+ * }
2327
+ * ```
2328
+ */
2329
+ declare class ApiError extends SecondLayerError {
2330
+ /** HTTP status code (0 for network errors). */
2331
+ status: number;
2332
+ /** Raw response body (parsed JSON if possible) — preserved for callers that need error details. */
2333
+ body?: unknown;
2334
+ constructor(status: number, message: string, body?: unknown, code?: string, options?: SecondLayerErrorOptions);
2335
+ }
2336
+ /** Thrown on a 401 — by both the platform clients and Streams. */
2337
+ declare class AuthError extends ApiError {
2338
+ readonly status: 401;
2222
2339
  constructor(message?: string);
2223
2340
  }
2224
- declare class RateLimitError extends Error {
2341
+ /** Thrown on a 429 — by both the platform clients and Streams. `retryable`,
2342
+ * with `retryAfterSeconds` parsed from the `Retry-After` header when sent. */
2343
+ declare class RateLimitError extends ApiError {
2344
+ /** Raw `Retry-After` header value (seconds or HTTP-date). */
2225
2345
  readonly retryAfter?: string;
2226
- readonly status = 429;
2346
+ readonly status: 429;
2227
2347
  constructor(message?: string, retryAfter?: string);
2228
2348
  }
2229
- declare class ValidationError extends Error {
2230
- readonly status: number;
2231
- readonly body?: unknown;
2349
+ /** Thrown on a 4xx the caller can fix (bad cursor, bad params). Never retried. */
2350
+ declare class ValidationError extends ApiError {
2232
2351
  constructor(message: string, status: number, body?: unknown);
2233
2352
  }
2234
- declare class StreamsServerError extends Error {
2235
- readonly status: number;
2236
- readonly body?: unknown;
2353
+ /** Parse a `Retry-After` header: delta-seconds or an HTTP-date. */
2354
+ declare function parseRetryAfter(value?: string | null): number | undefined;
2355
+ /**
2356
+ * Thrown on optimistic-concurrency conflict when a deploy supplies an
2357
+ * `expectedVersion` that no longer matches the server's stored version.
2358
+ */
2359
+ declare class VersionConflictError extends ApiError {
2360
+ currentVersion: string;
2361
+ expectedVersion: string;
2362
+ constructor(currentVersion: string, expectedVersion: string, message?: string);
2363
+ }
2364
+ /**
2365
+ * Thrown when a BYO subgraph deploy is refused for a breaking schema change.
2366
+ * The deploy did NOT run — `details.plan` carries the DROP + rebuild DDL to run
2367
+ * manually on your own database, plus the breaking `reasons` and the `diff`.
2368
+ * The same DDL is surfaced on `metaMessages`, so a bare `console.error(err)`
2369
+ * already shows the operator what to run.
2370
+ *
2371
+ * @example
2372
+ * ```ts
2373
+ * try {
2374
+ * await client.subgraphs.deploy(bundle);
2375
+ * } catch (err) {
2376
+ * if (err instanceof ByoBreakingChangeError) {
2377
+ * console.log(err.details.plan.dropStatement);
2378
+ * console.log(err.details.plan.statements.join(";
2379
+ "));
2380
+ * }
2381
+ * }
2382
+ * ```
2383
+ */
2384
+ declare class ByoBreakingChangeError extends ApiError {
2385
+ readonly details: ByoBreakingChangeDetails;
2386
+ constructor(message: string, details: ByoBreakingChangeDetails);
2387
+ }
2388
+ /** Thrown on a 5xx from the Streams API. `retryable`. */
2389
+ declare class StreamsServerError extends ApiError {
2237
2390
  constructor(message: string, status: number, body?: unknown);
2238
2391
  }
2239
2392
  /** Thrown when response signature verification is enabled and fails. */
2240
- declare class StreamsSignatureError extends Error {
2393
+ declare class StreamsSignatureError extends SecondLayerError {
2241
2394
  constructor(message?: string);
2242
2395
  }
2243
2396
  type FtTransferEvent = Extract<StreamsEvent, {
@@ -2677,62 +2830,6 @@ type PayAndRetryOptions = Omit<WithX402Options, never> & {
2677
2830
  */
2678
2831
  declare function payAndRetry(doFetch: X402FetchFn, opts: PayAndRetryOptions): Promise<Response>;
2679
2832
  import { SubgraphAgentSchema as SubgraphAgentSchema3, SubgraphSpecFormat as SubgraphSpecFormat2, SubgraphSpecOptions as SubgraphSpecOptions3 } from "@secondlayer/shared/subgraphs/spec";
2680
- import { ByoBreakingChangeDetails } from "@secondlayer/shared/errors";
2681
- /**
2682
- * Error thrown by {@link SecondLayer} when an API request fails.
2683
- * Includes the HTTP status code for programmatic error handling.
2684
- *
2685
- * @example
2686
- * ```ts
2687
- * try {
2688
- * await client.subgraphs.get("my-subgraph");
2689
- * } catch (err) {
2690
- * if (err instanceof ApiError && err.status === 404) {
2691
- * console.log("Subgraph not found");
2692
- * }
2693
- * }
2694
- * ```
2695
- */
2696
- declare class ApiError extends Error {
2697
- /** HTTP status code (0 for network errors). */
2698
- status: number;
2699
- /** Raw response body (parsed JSON if possible) — preserved for callers that need error details. */
2700
- body?: unknown;
2701
- /** Stable machine-readable code from the API's `{error, code}` error envelope. */
2702
- code?: string;
2703
- constructor(status: number, message: string, body?: unknown, code?: string);
2704
- }
2705
- /**
2706
- * Thrown on optimistic-concurrency conflict when a deploy supplies an
2707
- * `expectedVersion` that no longer matches the server's stored version.
2708
- */
2709
- declare class VersionConflictError extends ApiError {
2710
- currentVersion: string;
2711
- expectedVersion: string;
2712
- constructor(currentVersion: string, expectedVersion: string, message?: string);
2713
- }
2714
- /**
2715
- * Thrown when a BYO subgraph deploy is refused for a breaking schema change.
2716
- * The deploy did NOT run — `details.plan` carries the DROP + rebuild DDL to run
2717
- * manually on your own database, plus the breaking `reasons` and the `diff`.
2718
- *
2719
- * @example
2720
- * ```ts
2721
- * try {
2722
- * await client.subgraphs.deploy(bundle);
2723
- * } catch (err) {
2724
- * if (err instanceof ByoBreakingChangeError) {
2725
- * console.log(err.details.plan.dropStatement);
2726
- * console.log(err.details.plan.statements.join(";
2727
- "));
2728
- * }
2729
- * }
2730
- * ```
2731
- */
2732
- declare class ByoBreakingChangeError extends ApiError {
2733
- readonly details: ByoBreakingChangeDetails;
2734
- constructor(message: string, details: ByoBreakingChangeDetails);
2735
- }
2736
2833
  import { ChainWebhookDelivery } from "@secondlayer/shared";
2737
2834
  import { StandardWebhooksHeaders } from "@secondlayer/shared/crypto/standard-webhooks";
2738
2835
  import { StandardWebhooksHeaders as StandardWebhooksHeaders2, verify } from "@secondlayer/shared/crypto/standard-webhooks";
@@ -2896,4 +2993,4 @@ declare function toJsonSafe(value: unknown): unknown;
2896
2993
  /** Decode a hex-encoded Clarity value to JSON-safe JS (uints as strings,
2897
2994
  * buffers as `0x…` hex, tuples as objects). Returns the input hex on failure. */
2898
2995
  declare function decodeClarityValue(hex: string): unknown;
2899
- export { withX402, verifyWebhookSignature, verifyTransactionProof, verify as verifyStandardWebhooksHeaders, verifySecondlayerSignature, trigger, toJsonSafe, selectOffer, resolveApiKey, resolveAccountNonce, readX402Receipt, readX402Challenge, payAndRetry, 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, decodeChainWebhook, createX402Client, createStreamsClient, consumeIndexFeed, buildSignedX402Payment, X402SpendGuardError, X402Result, X402Receipt, X402Fetch, X402ClientOptions, X402Client, X402Challenge, X402Accept, WithX402Options, WebhookHeaderInput, 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, StreamsConsumeParams, StreamsClient, StreamsCanonicalBlock, StreamsBatchContext, StreamsBatch, StandardWebhooksHeaders2 as StandardWebhooksHeaders, StackingWalkParams, StackingListParams, StackingEnvelope, SelectOfferOptions, SecondLayerOptions, SecondLayer, ScopedKeyProduct, SbtcWithdrawalsWalkParams, SbtcWithdrawalsListParams, SbtcWithdrawalsEnvelope, SbtcWithdrawalSweptConfirmedEvent, SbtcWithdrawalStatus, SbtcWithdrawalEvent, SbtcWithdrawalEnvelope, SbtcSummaryEnvelope, SbtcResource, SbtcEventsWalkParams, SbtcEventsListParams, SbtcEventsEnvelope, SbtcEventsConsumeParams, SbtcEventTopic, SbtcDepositsWalkParams, SbtcDepositsListParams, SbtcDepositsEnvelope, SbtcDepositsConsumeParams, SbtcDepositEvent, SbtcDepositEnvelope, RotateSecretResponse2 as RotateSecretResponse, RewardSet2 as RewardSet, ReplayResult2 as ReplayResult, RateLimitError, Projects, ProjectTeamMember, ProjectTeam, ProjectInvitation, Project, PrintSchemaResponse, PoxResource, PoxCyclesWalkParams, PoxCyclesListParams, PoxCyclesEnvelope, PoxCycleEnvelope, Pox5Resource, Pox5EventsWalkParams, Pox5EventsListParams, Pox5EventsEnvelope, PayAndRetryOptions, NftTransfersWalkParams, NftTransfersResource, NftTransfersListParams, NftTransfersEnvelope, NftTransferPayload, NftTransferEvent, NftTransfer, MempoolWalkParams, MempoolTransactionEnvelope, MempoolListParams, MempoolEnvelope, IndexUsage, IndexTransaction, IndexTip, IndexStxTransfer, IndexStxMint, IndexStxLock, IndexStxBurn, IndexStackingAction, IndexSbtcWithdrawalPhase, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawal, IndexSbtcSummary, IndexSbtcEvent, IndexSbtcDepositDetail, IndexSbtcDeposit, IndexReorg, IndexPrint, IndexPoxFunctionCount, IndexPoxCycle, IndexPox5EventTopic, IndexPox5Event, IndexPostCondition, IndexNftTransfer, IndexNftMint, IndexNftBurn, IndexMempoolTransaction, IndexFtTransfer, IndexFtMint, IndexFtBurn, IndexFeedItem, IndexFeedFetcher, IndexFeedEnvelope, IndexEventsResource, IndexEventTypeFilters, IndexEventType, IndexEventOf, IndexEvent, IndexDiscovery, IndexContractCall, IndexConsumeOptions, IndexCanonicalBlock, IndexBlock, Index, FtTransfersWalkParams, FtTransfersResource, FtTransfersListParams, FtTransfersEnvelope, FtTransferPayload, FtTransferEvent, FtTransfer, FetchLike2 as FetchLike, EventsWalkParams, EventsListParams, EventsEnvelope, EventsConsumeParams, 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, DEFAULT_PREFER_ASSETS, Cursor, CreateSubscriptionResponse2 as CreateSubscriptionResponse, CreateSubscriptionRequest2 as CreateSubscriptionRequest, CreateProjectParams, CreateApiKeyResponse, CreateApiKeyParams, ContractsListParams, ContractsEnvelope, Contracts, ContractSummary, ContractConformance, ContractCallsWalkParams, ContractCallsListParams, ContractCallsEnvelope, ContractCallsConsumeParams, ContextSnapshot, ContextProject, ContextApiKey, ContextAccount, ConsumerBatchContext, ChainWebhookEnvelope, ChainWebhookDelivery2 as ChainWebhookDelivery, ChainTxLevelEvent, ChainTriggerType, ChainTrigger, ChainTestDelivery, ChainStxTransferData, ChainStxMintData, ChainStxLockData, ChainStxBurnData, ChainReorgRollbackEnvelope, ChainReorgRollbackDelivery, ChainReorgOrphanedEntry, ChainPrintEventData, ChainNftTransferData, ChainNftMintData, ChainNftBurnData, ChainFtTransferData, ChainFtMintData, ChainFtBurnData, ChainEventEnvelope, ChainApplyEnvelopeOf, ChainApplyEnvelope, ChainApplyDeliveryOf, CanonicalWalkParams, CanonicalListParams, CanonicalEnvelope, ByoBreakingChangeError, ByoBreakingChangeDetails, BuildSignedX402PaymentOptions, BlocksWalkParams, BlocksListParams, BlocksEnvelope, BlockEnvelope, AuthError, ApiKeys, ApiKeySummary, ApiError, ActiveSubgraphOperation };
2996
+ export { withX402, verifyWebhookSignature, verifyTransactionProof, verify as verifyStandardWebhooksHeaders, verifySecondlayerSignature, trigger, toJsonSafe, selectOffer, resolveApiKey, resolveAccountNonce, readX402Receipt, readX402Challenge, payAndRetry, parseRetryAfter, 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, decodeChainWebhook, createX402Client, createStreamsClient, consumeIndexFeed, buildSignedX402Payment, X402SpendGuardError, X402Result, X402Receipt, X402Fetch, X402ClientOptions, X402Client, X402Challenge, X402Accept, WithX402Options, WebhookHeaderInput, 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, StreamsConsumeParams, StreamsClient, StreamsCanonicalBlock, StreamsBatchContext, StreamsBatch, StandardWebhooksHeaders2 as StandardWebhooksHeaders, StackingWalkParams, StackingListParams, StackingEnvelope, SelectOfferOptions, SecondLayerOptions, SecondLayerErrorOptions, SecondLayerError, SecondLayer, ScopedKeyProduct, SbtcWithdrawalsWalkParams, SbtcWithdrawalsListParams, SbtcWithdrawalsEnvelope, SbtcWithdrawalSweptConfirmedEvent, SbtcWithdrawalStatus, SbtcWithdrawalEvent, SbtcWithdrawalEnvelope, SbtcSummaryEnvelope, SbtcResource, SbtcEventsWalkParams, SbtcEventsListParams, SbtcEventsEnvelope, SbtcEventsConsumeParams, SbtcEventTopic2 as SbtcEventTopic, SbtcDepositsWalkParams, SbtcDepositsListParams, SbtcDepositsEnvelope, SbtcDepositsConsumeParams, SbtcDepositEvent, SbtcDepositEnvelope, RotateSecretResponse2 as RotateSecretResponse, RewardSet2 as RewardSet, ReplayResult2 as ReplayResult, RateLimitError, Projects, ProjectTeamMember, ProjectTeam, ProjectInvitation, Project, PrintSchemaResponse, PoxResource, PoxCyclesWalkParams, PoxCyclesListParams, PoxCyclesEnvelope, PoxCycleEnvelope, Pox5Resource, Pox5EventsWalkParams, Pox5EventsListParams, Pox5EventsEnvelope, PayAndRetryOptions, NftTransfersWalkParams, NftTransfersResource, NftTransfersListParams, NftTransfersEnvelope, NftTransferPayload, NftTransferEvent, NftTransfer, MempoolWalkParams, MempoolTransactionEnvelope, MempoolListParams, MempoolEnvelope, IndexUsage, IndexTransaction, IndexTip, IndexStxTransfer, IndexStxMint, IndexStxLock, IndexStxBurn, IndexStackingAction, IndexSbtcWithdrawalPhase, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawal, IndexSbtcSummary, IndexSbtcEvent, IndexSbtcDepositDetail, IndexSbtcDeposit, IndexReorg, IndexPrint, IndexPoxFunctionCount, IndexPoxCycle, IndexPox5EventTopic, IndexPox5Event, IndexPostCondition, IndexNftTransfer, IndexNftMint, IndexNftBurn, IndexMempoolTransaction, IndexFtTransfer, IndexFtMint, IndexFtBurn, IndexFeedItem, IndexFeedFetcher, IndexFeedEnvelope, IndexEventsResource, IndexEventTypeFilters, IndexEventType, IndexEventOf, IndexEvent, IndexDiscovery, IndexContractCall, IndexConsumeOptions, IndexCanonicalBlock, IndexBlock, Index, FtTransfersWalkParams, FtTransfersResource, FtTransfersListParams, FtTransfersEnvelope, FtTransferPayload, FtTransferEvent, FtTransfer, FetchLike2 as FetchLike, EventsWalkParams, EventsListParams, EventsEnvelope, EventsConsumeParams, 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, DEFAULT_PREFER_ASSETS, Cursor, CreateSubscriptionResponse2 as CreateSubscriptionResponse, CreateSubscriptionRequest2 as CreateSubscriptionRequest, CreateProjectParams, CreateApiKeyResponse, CreateApiKeyParams, ContractsListParams, ContractsEnvelope, Contracts, ContractSummary, ContractConformance, ContractCallsWalkParams, ContractCallsListParams, ContractCallsEnvelope, ContractCallsConsumeParams, ContextSnapshot, ContextProject, ContextApiKey, ContextAccount, ConsumerBatchContext, ChainWebhookEnvelope, ChainWebhookDelivery2 as ChainWebhookDelivery, ChainTxLevelEvent, ChainTriggerType, ChainTrigger, ChainTestDelivery, ChainStxTransferData, ChainStxMintData, ChainStxLockData, ChainStxBurnData, ChainReorgRollbackEnvelope, ChainReorgRollbackDelivery, ChainReorgOrphanedEntry, ChainPrintEventData, ChainNftTransferData, ChainNftMintData, ChainNftBurnData, ChainFtTransferData, ChainFtMintData, ChainFtBurnData, ChainEventEnvelope, ChainApplyEnvelopeOf, ChainApplyEnvelope, ChainApplyDeliveryOf, CanonicalWalkParams, CanonicalListParams, CanonicalEnvelope, ByoBreakingChangeError, ByoBreakingChangeDetails, BuildSignedX402PaymentOptions, BlocksWalkParams, BlocksListParams, BlocksEnvelope, BlockEnvelope, AuthError, ApiKeys, ApiKeySummary, ApiError, ActiveSubgraphOperation };
package/dist/index.js CHANGED
@@ -1,17 +1,127 @@
1
1
  // src/errors.ts
2
- class ApiError extends Error {
2
+ var DOCS_BASE = "https://www.secondlayer.tools";
3
+
4
+ class SecondLayerError extends Error {
5
+ name = "SecondLayerError";
6
+ shortMessage;
7
+ code;
8
+ docsUrl;
9
+ metaMessages;
10
+ retryable;
11
+ retryAfterSeconds;
12
+ constructor(shortMessage, options = {}) {
13
+ const detailBlocks = [
14
+ ...options.metaMessages ?? [],
15
+ ...options.details ? [options.details] : [],
16
+ ...options.docsUrl ? [`Docs: ${options.docsUrl}`] : []
17
+ ];
18
+ const message = [
19
+ shortMessage,
20
+ detailBlocks.length > 0 ? `
21
+ ${detailBlocks.join(`
22
+ `)}` : ""
23
+ ].join("");
24
+ super(message, options.cause ? { cause: options.cause } : undefined);
25
+ this.shortMessage = shortMessage;
26
+ this.code = options.code;
27
+ this.docsUrl = options.docsUrl;
28
+ this.metaMessages = options.metaMessages;
29
+ this.retryable = options.retryable ?? false;
30
+ this.retryAfterSeconds = options.retryAfterSeconds;
31
+ }
32
+ walk(fn) {
33
+ let err = this;
34
+ let last = this;
35
+ while (err != null) {
36
+ if (fn?.(err))
37
+ return err;
38
+ last = err;
39
+ err = err.cause;
40
+ }
41
+ return fn ? null : last;
42
+ }
43
+ toJSON() {
44
+ return {
45
+ name: this.name,
46
+ message: this.message,
47
+ shortMessage: this.shortMessage,
48
+ cause: this.cause instanceof Error ? this.cause.message : undefined,
49
+ code: this.code,
50
+ docsUrl: this.docsUrl,
51
+ retryable: this.retryable,
52
+ retryAfterSeconds: this.retryAfterSeconds
53
+ };
54
+ }
55
+ }
56
+ function statusRetryable(status) {
57
+ return status === 429 || status >= 500;
58
+ }
59
+ function docsFor(status, code) {
60
+ if (code === "UPGRADE_REQUIRED" || code === "PLAN_REQUIRED" || status === 402)
61
+ return `${DOCS_BASE}/docs/authentication#pay-as-you-go-credits`;
62
+ if (status === 429 || status === 401)
63
+ return `${DOCS_BASE}/docs/authentication`;
64
+ return;
65
+ }
66
+
67
+ class ApiError extends SecondLayerError {
3
68
  status;
4
69
  body;
5
- code;
6
- constructor(status, message, body, code) {
7
- super(message);
70
+ constructor(status, message, body, code, options = {}) {
71
+ super(message, {
72
+ code,
73
+ retryable: options.retryable ?? statusRetryable(status),
74
+ docsUrl: options.docsUrl ?? docsFor(status, code),
75
+ ...options.cause ? { cause: options.cause } : {},
76
+ ...options.details ? { details: options.details } : {},
77
+ ...options.metaMessages ? { metaMessages: options.metaMessages } : {},
78
+ ...options.retryAfterSeconds !== undefined ? { retryAfterSeconds: options.retryAfterSeconds } : {}
79
+ });
8
80
  this.status = status;
9
81
  this.body = body;
10
- this.code = code;
11
82
  this.name = "ApiError";
12
83
  }
13
84
  }
14
85
 
86
+ class AuthError extends ApiError {
87
+ status = 401;
88
+ constructor(message = "API key invalid or expired.") {
89
+ super(401, message);
90
+ this.name = "AuthError";
91
+ }
92
+ }
93
+
94
+ class RateLimitError extends ApiError {
95
+ retryAfter;
96
+ status = 429;
97
+ constructor(message = "Rate limited. Try again later.", retryAfter) {
98
+ super(429, message, undefined, undefined, {
99
+ retryable: true,
100
+ retryAfterSeconds: parseRetryAfter(retryAfter)
101
+ });
102
+ this.retryAfter = retryAfter;
103
+ this.name = "RateLimitError";
104
+ }
105
+ }
106
+
107
+ class ValidationError extends ApiError {
108
+ constructor(message, status, body) {
109
+ super(status, message, body, undefined, { retryable: false });
110
+ this.name = "ValidationError";
111
+ }
112
+ }
113
+ function parseRetryAfter(value) {
114
+ if (!value)
115
+ return;
116
+ const seconds = Number(value);
117
+ if (Number.isFinite(seconds) && seconds >= 0)
118
+ return seconds;
119
+ const date = Date.parse(value);
120
+ if (!Number.isNaN(date))
121
+ return Math.max(0, (date - Date.now()) / 1000);
122
+ return;
123
+ }
124
+
15
125
  class VersionConflictError extends ApiError {
16
126
  currentVersion;
17
127
  expectedVersion;
@@ -26,7 +136,13 @@ class VersionConflictError extends ApiError {
26
136
  class ByoBreakingChangeError extends ApiError {
27
137
  details;
28
138
  constructor(message, details) {
29
- super(422, message, details, "BYO_BREAKING_CHANGE");
139
+ super(422, message, details, "BYO_BREAKING_CHANGE", {
140
+ metaMessages: [
141
+ "Review and run manually on your database:",
142
+ details.plan.dropStatement,
143
+ ...details.plan.statements
144
+ ]
145
+ });
30
146
  this.name = "ByoBreakingChangeError";
31
147
  this.details = details;
32
148
  }
@@ -112,7 +228,7 @@ class BaseClient {
112
228
  serializedBody = JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value);
113
229
  } catch (err) {
114
230
  const detail = err instanceof Error ? err.message : String(err);
115
- throw new ApiError(0, `Failed to serialize request body: ${detail}`);
231
+ throw new ApiError(0, `Failed to serialize request body: ${detail}`, undefined, undefined, { retryable: false });
116
232
  }
117
233
  }
118
234
  let response;
@@ -122,17 +238,17 @@ class BaseClient {
122
238
  headers,
123
239
  body: serializedBody
124
240
  });
125
- } catch {
126
- throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`);
241
+ } catch (err) {
242
+ throw new ApiError(0, `Cannot reach API at ${this.baseUrl}. Check your connection or try again.`, undefined, undefined, { retryable: true, cause: err instanceof Error ? err : undefined });
127
243
  }
128
244
  if (!response.ok) {
129
245
  if (response.status === 401) {
130
- throw new ApiError(401, "API key invalid or expired.");
246
+ throw new AuthError;
131
247
  }
132
248
  if (response.status === 429) {
133
249
  const retryAfter = response.headers.get("Retry-After");
134
250
  const msg = retryAfter ? `Rate limited. Wait ${retryAfter} seconds.` : "Rate limited. Try again later.";
135
- throw new ApiError(429, msg);
251
+ throw new RateLimitError(msg, retryAfter ?? undefined);
136
252
  }
137
253
  if (response.status >= 500) {
138
254
  throw new ApiError(response.status, `Server error. Try again or check status at ${this.baseUrl}/health`);
@@ -426,47 +542,14 @@ class Contracts extends BaseClient {
426
542
  }
427
543
 
428
544
  // src/streams/errors.ts
429
- class AuthError extends Error {
430
- status = 401;
431
- constructor(message = "API key invalid or expired.") {
432
- super(message);
433
- this.name = "AuthError";
434
- }
435
- }
436
-
437
- class RateLimitError extends Error {
438
- retryAfter;
439
- status = 429;
440
- constructor(message = "Rate limited. Try again later.", retryAfter) {
441
- super(message);
442
- this.retryAfter = retryAfter;
443
- this.name = "RateLimitError";
444
- }
445
- }
446
-
447
- class ValidationError extends Error {
448
- status;
449
- body;
450
- constructor(message, status, body) {
451
- super(message);
452
- this.status = status;
453
- this.body = body;
454
- this.name = "ValidationError";
455
- }
456
- }
457
-
458
- class StreamsServerError extends Error {
459
- status;
460
- body;
545
+ class StreamsServerError extends ApiError {
461
546
  constructor(message, status, body) {
462
- super(message);
463
- this.status = status;
464
- this.body = body;
547
+ super(status, message, body, undefined, { retryable: true });
465
548
  this.name = "StreamsServerError";
466
549
  }
467
550
  }
468
551
 
469
- class StreamsSignatureError extends Error {
552
+ class StreamsSignatureError extends SecondLayerError {
470
553
  constructor(message = "Streams response signature verification failed.") {
471
554
  super(message);
472
555
  this.name = "StreamsSignatureError";
@@ -517,6 +600,41 @@ function batchContext(cursor, height, tipHeight) {
517
600
  blocksBehind: height === null ? null : Math.max(0, tipHeight - height)
518
601
  };
519
602
  }
603
+ var MAX_RETRY_AFTER_MS = 300000;
604
+ function errRetryable(err) {
605
+ if (err && typeof err === "object" && "retryable" in err) {
606
+ return err.retryable === true;
607
+ }
608
+ return err instanceof TypeError;
609
+ }
610
+ function errRetryAfterMs(err) {
611
+ if (err && typeof err === "object" && "retryAfterSeconds" in err) {
612
+ const seconds = err.retryAfterSeconds;
613
+ if (typeof seconds === "number" && Number.isFinite(seconds)) {
614
+ return Math.min(seconds * 1000, MAX_RETRY_AFTER_MS);
615
+ }
616
+ }
617
+ return;
618
+ }
619
+ async function fetchPageWithRetry(fetchPage, opts) {
620
+ const retryCount = opts.retryCount ?? 3;
621
+ const retryDelay = opts.retryDelay ?? 1000;
622
+ for (let attempt = 0;; attempt++) {
623
+ try {
624
+ return await fetchPage();
625
+ } catch (err) {
626
+ const retriesLeft = retryCount - attempt;
627
+ if (retriesLeft <= 0 || !errRetryable(err) || opts.signal?.aborted) {
628
+ throw err;
629
+ }
630
+ const delayMs = errRetryAfterMs(err) ?? retryDelay * (attempt + 1);
631
+ opts.onError?.(err, { attempt, retriesLeft, delayMs });
632
+ await opts.sleep(delayMs, opts.signal);
633
+ if (opts.signal?.aborted)
634
+ throw err;
635
+ }
636
+ }
637
+ }
520
638
  async function defaultSleep(ms, signal) {
521
639
  if (signal?.aborted)
522
640
  return;
@@ -543,7 +661,7 @@ async function consumeStreamsEvents(opts) {
543
661
  let emptyPolls = 0;
544
662
  let height = null;
545
663
  while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
546
- const envelope = await opts.fetchEvents({
664
+ const envelope = await fetchPageWithRetry(() => opts.fetchEvents({
547
665
  cursor,
548
666
  limit: opts.batchSize,
549
667
  types: opts.types,
@@ -552,6 +670,12 @@ async function consumeStreamsEvents(opts) {
552
670
  sender: opts.sender,
553
671
  recipient: opts.recipient,
554
672
  assetIdentifier: opts.assetIdentifier
673
+ }), {
674
+ retryCount: opts.retryCount,
675
+ retryDelay: opts.retryDelay,
676
+ onError: opts.onError,
677
+ sleep,
678
+ signal: opts.signal
555
679
  });
556
680
  pages++;
557
681
  if (!finalizedOnly && opts.onReorg) {
@@ -682,10 +806,16 @@ async function consumeIndexFeed(opts) {
682
806
  let emptyPolls = 0;
683
807
  let height = null;
684
808
  while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
685
- const envelope = await opts.fetchPage({
809
+ const envelope = await fetchPageWithRetry(() => opts.fetchPage({
686
810
  cursor,
687
811
  fromHeight: cursor === null ? opts.fromHeight : undefined,
688
812
  limit: batchSize
813
+ }), {
814
+ retryCount: opts.retryCount,
815
+ retryDelay: opts.retryDelay,
816
+ onError: opts.onError,
817
+ sleep,
818
+ signal: opts.signal
689
819
  });
690
820
  pages++;
691
821
  if (!finalizedOnly && opts.onReorg) {
@@ -1574,7 +1704,10 @@ function createStreamsClient(options) {
1574
1704
  emptyBackoffMs: params.emptyBackoffMs,
1575
1705
  maxPages: params.maxPages,
1576
1706
  maxEmptyPolls: params.maxEmptyPolls,
1577
- signal: params.signal
1707
+ signal: params.signal,
1708
+ retryCount: params.retryCount,
1709
+ retryDelay: params.retryDelay,
1710
+ onError: params.onError
1578
1711
  });
1579
1712
  },
1580
1713
  stream(params = {}) {
@@ -2472,6 +2605,7 @@ export {
2472
2605
  readX402Receipt,
2473
2606
  readX402Challenge,
2474
2607
  payAndRetry,
2608
+ parseRetryAfter,
2475
2609
  isStxTransfer,
2476
2610
  isStxMint,
2477
2611
  isStxLock,
@@ -2509,6 +2643,7 @@ export {
2509
2643
  Subgraphs,
2510
2644
  StreamsSignatureError,
2511
2645
  StreamsServerError,
2646
+ SecondLayerError,
2512
2647
  SecondLayer,
2513
2648
  RateLimitError,
2514
2649
  Projects,
@@ -2522,5 +2657,5 @@ export {
2522
2657
  ApiError
2523
2658
  };
2524
2659
 
2525
- //# debugId=7D05343D5E23B9E764756E2164756E21
2660
+ //# debugId=D57E218C0E8C77C464756E2164756E21
2526
2661
  //# sourceMappingURL=index.js.map