@secondlayer/sdk 12.2.0 → 12.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2655,8 +2655,8 @@ declare class Subgraphs extends BaseClient {
2655
2655
  */
2656
2656
  private createTableClient;
2657
2657
  }
2658
- import { CreateWebhookRequest, CreateWebhookResponse, DeadRow, DeliveryRow, ReplayResult, RotateSecretResponse, UpdateWebhookRequest, WebhookDetail, WebhookSummary, WebhookTestResult } from "@secondlayer/shared/schemas/webhooks";
2659
- import { ChainTrigger, ChainTriggerType, CreateWebhookRequest as CreateWebhookRequest2, CreateWebhookResponse as CreateWebhookResponse2, DeadRow as DeadRow2, DeliveryRow as DeliveryRow2, ReplayResult as ReplayResult2, RotateSecretResponse as RotateSecretResponse2, WebhookDetail as WebhookDetail2, WebhookFormat, WebhookKind, WebhookRuntime, WebhookStatus, WebhookSummary as WebhookSummary2, WebhookTestResult as WebhookTestResult2, UpdateWebhookRequest as UpdateWebhookRequest2 } from "@secondlayer/shared/schemas/webhooks";
2658
+ import { CreateWebhookRequest, CreateWebhookResponse, DeadRow, DeliveryRow, ReplayResult, RotateSecretResponse, UpdateWebhookRequest, WebhookActivity, WebhookDeliveryDetail, WebhookDetail, WebhookSummary, WebhookTestResult } from "@secondlayer/shared/schemas/webhooks";
2659
+ import { ChainTrigger, ChainTriggerType, CreateWebhookRequest as CreateWebhookRequest2, CreateWebhookResponse as CreateWebhookResponse2, DeadRow as DeadRow2, DeliveryRow as DeliveryRow2, ReplayResult as ReplayResult2, RotateSecretResponse as RotateSecretResponse2, WebhookActivity as WebhookActivity2, WebhookActivityHour, WebhookDeliveryDetail as WebhookDeliveryDetail2, WebhookDetail as WebhookDetail2, WebhookFormat, WebhookKind, WebhookRuntime, WebhookStatus, WebhookSummary as WebhookSummary2, WebhookTestResult as WebhookTestResult2, UpdateWebhookRequest as UpdateWebhookRequest2 } from "@secondlayer/shared/schemas/webhooks";
2660
2660
  import { trigger } from "@secondlayer/shared/schemas/webhooks";
2661
2661
  declare class Webhooks extends BaseClient {
2662
2662
  list(): Promise<{
@@ -2679,6 +2679,12 @@ declare class Webhooks extends BaseClient {
2679
2679
  deliveries(id: string): Promise<{
2680
2680
  data: DeliveryRow[];
2681
2681
  }>;
2682
+ /** Hourly delivered/waiting/gave-up counts for the last 7 days, plus the
2683
+ * current queue depth — the events chart on the detail page. */
2684
+ activity(id: string): Promise<WebhookActivity>;
2685
+ /** One delivery attempt with its outbox context (payload, response
2686
+ * headers) — the delivery card on the detail page. */
2687
+ delivery(id: string, deliveryId: string): Promise<WebhookDeliveryDetail>;
2682
2688
  replay(id: string, range: {
2683
2689
  fromBlock: number;
2684
2690
  toBlock: number;
@@ -2800,17 +2806,40 @@ declare function getSubgraph<T extends {
2800
2806
  }>(def: T, options?: Partial<SecondLayerOptions> | SecondLayer | Subgraphs): InferSubgraphClient2<T>;
2801
2807
  import { SubgraphAgentSchema as SubgraphAgentSchema3, SubgraphSpecFormat as SubgraphSpecFormat2, SubgraphSpecOptions as SubgraphSpecOptions3 } from "@secondlayer/shared/subgraphs/spec";
2802
2808
  import { SubgraphDetail as SubgraphDetail2 } from "@secondlayer/shared/schemas/subgraphs";
2803
- import { DeadRow as DeadRow3, DeliveryRow as DeliveryRow3, WebhookDetail as WebhookDetail3 } from "@secondlayer/shared/schemas/webhooks";
2809
+ import { DeadRow as DeadRow3, DeliveryRow as DeliveryRow3, WebhookDetail as WebhookDetail3, WebhookSummary as WebhookSummary3 } from "@secondlayer/shared/schemas/webhooks";
2804
2810
  /**
2805
2811
  * Webhook diagnosis, shared by `secondlayer webhooks doctor` and the
2806
2812
  * dashboard's webhook detail page. Moved out of the CLI (unchanged behavior)
2807
2813
  * so the web can build the same judgment without printing CLI-command text.
2814
+ *
2815
+ * Plan 068 adds five deterministic, numbers-only detectors on top of the
2816
+ * existing flag checks: no model, no history beyond the deliveries window
2817
+ * already fetched. Thresholds are named constants below, conservative on
2818
+ * purpose — a wrong insight costs more trust than a missed one.
2808
2819
  */
2809
2820
  declare function isSuccessDelivery(row: DeliveryRow3): boolean;
2810
- type DoctorIssueCode = "warning" | "paused" | "last_error" | "circuit" | "dead_letters" | "subgraph_gaps" | "subgraph_catching_up" | "no_deliveries";
2821
+ type DoctorSeverity = "bad" | "warn" | "calm";
2822
+ interface DoctorEvidence {
2823
+ label: string;
2824
+ value: string;
2825
+ }
2826
+ interface DoctorFix {
2827
+ text: string;
2828
+ /** A `secondlayer webhooks ...` command the reader can copy. */
2829
+ command?: string;
2830
+ /** Anchor into the docs' webhooks troubleshooting section. */
2831
+ docsPath?: string;
2832
+ }
2833
+ type DoctorIssueCode = "warning" | "paused" | "last_error" | "circuit" | "dead_letters" | "subgraph_gaps" | "subgraph_catching_up" | "no_deliveries" | "receiver_rate_limited" | "receiver_down" | "receiver_rejects" | "receiver_slow" | "delivery_lag";
2811
2834
  interface DoctorIssue {
2812
2835
  code: DoctorIssueCode;
2813
2836
  detail?: string;
2837
+ severity: DoctorSeverity;
2838
+ /** 2-4 numbers-only facts backing the issue. Only the five new detectors
2839
+ * and the list-summary circuit issue carry this — the older flag checks
2840
+ * keep their plain `detail` string. */
2841
+ evidence?: DoctorEvidence[];
2842
+ fix?: DoctorFix;
2814
2843
  }
2815
2844
  interface DoctorReport {
2816
2845
  webhook: WebhookDetail3;
@@ -2833,7 +2862,12 @@ interface DoctorReport {
2833
2862
  /** CLI-facing next steps, one per issue, in the same order as `issues`. */
2834
2863
  hints: string[];
2835
2864
  issues: DoctorIssue[];
2865
+ /** The single most severe issue (bad > warn > calm, then rule priority),
2866
+ * or `null` when there are none. The UI leads with this and collapses
2867
+ * the rest underneath. */
2868
+ primary: DoctorIssue | null;
2836
2869
  }
2870
+ declare const DOWN_MIN_CONSECUTIVE = 5;
2837
2871
  declare function buildDoctorReport(input: {
2838
2872
  webhook: WebhookDetail3;
2839
2873
  deliveries: DeliveryRow3[];
@@ -2841,6 +2875,15 @@ declare function buildDoctorReport(input: {
2841
2875
  subgraph?: SubgraphDetail2 | null;
2842
2876
  }): DoctorReport;
2843
2877
  /**
2878
+ * The list page's own reduced detector: computed from `WebhookSummary` alone
2879
+ * (no deliveries, no dead-letter rows — the list endpoint returns neither,
2880
+ * and fetching per-row detail or deliveries here would fan out one request
2881
+ * per row). Only `status` and `circuitOpenedAt` distinguish a real problem
2882
+ * from a manual pause at this level; deliveries-based rules (rate limits,
2883
+ * downtime, rejects, slowness, lag) only ever show on the detail page.
2884
+ */
2885
+ declare function buildListIssue(webhook: Pick<WebhookSummary3, "status" | "circuitOpenedAt" | "lastSuccessAt">): DoctorIssue | null;
2886
+ /**
2844
2887
  * The two pieces every "deploy a consumer" guide leaves out, packaged:
2845
2888
  * a liveness endpoint and a graceful-shutdown signal. Both are
2846
2889
  * runtime-agnostic — the SDK never binds a port or assumes Bun/Node.
@@ -3269,4 +3312,4 @@ declare const Cursor: {
3269
3312
  };
3270
3313
  };
3271
3314
  import { decodeClarityValue, toJsonSafe } from "@secondlayer/shared/streams-rows";
3272
- export { ACCOUNT_KEY_ENV, ActiveSubgraphOperation, ApiError, ArchiveAuthError, ArchiveClient, ArchiveCreditsBalance, ArchiveDataset, ArchiveFetchItem, ArchiveFetchResult, ArchiveFlow, ArchiveGateNotConfiguredError, ArchiveLoadOptions, ArchiveManifest, ArchivePartition, ArchiveQuote, ArchiveSignatureError, ArchiveStatus, ArchiveVerifyInput, ArchiveVerifyRangeStatus, ArchiveVerifyResult, AuthError, BlockEnvelope, BlocksEnvelope, BlocksListParams, BlocksWalkParams, CanonicalEnvelope, CanonicalListParams, CanonicalWalkParams, ChainApplyDeliveryOf, ChainApplyEnvelope, ChainApplyEnvelopeOf, ChainEventEnvelope, ChainFtBurnData, ChainFtMintData, ChainFtTransferData, ChainNftBurnData, ChainNftMintData, ChainNftTransferData, ChainPrintEventData, ChainReorgOrphanedEntry, ChainReorgRollbackDelivery, ChainReorgRollbackEnvelope, ChainStxBurnData, ChainStxLockData, ChainStxMintData, ChainStxTransferData, ChainTestDelivery, ChainTrigger, ChainTriggerType, ChainTxLevelEvent, ChainWebhookDelivery2 as ChainWebhookDelivery, ChainWebhookEnvelope, ConsumerBatchContext, ConsumerHealth, ConsumerSink, ContextAccount, ContextField, ContextFieldError, ContextSnapshot, ContractCallsConsumeParams, ContractCallsEnvelope, ContractCallsListParams, ContractCallsWalkParams, ContractConformance, ContractSummary, Contracts, ContractsEnvelope, ContractsListParams, CreateArchiveClientOptions, CreateWebhookRequest2 as CreateWebhookRequest, CreateWebhookResponse2 as CreateWebhookResponse, Cursor, DEFAULT_REQUEST_TIMEOUT_MS, DeadRow2 as DeadRow, DecodedEventColumns, DecodedEventRow, DecodedFtBurn, DecodedFtBurnPayload, DecodedFtMint, DecodedFtMintPayload, DecodedFtTransfer, DecodedFtTransferPayload, DecodedNftBurn, DecodedNftBurnPayload, DecodedNftMint, DecodedNftMintPayload, DecodedNftTransfer, DecodedNftTransferPayload, DecodedPrint, DecodedPrintPayload, DecodedPrintValue, DecodedStxBurn, DecodedStxBurnPayload, DecodedStxLock, DecodedStxLockPayload, DecodedStxMint, DecodedStxMintPayload, DecodedStxTransfer, DecodedStxTransferPayload, DeliveryRow2 as DeliveryRow, DoctorIssue, DoctorIssueCode, DoctorReport, EtagCache, EtagEntry, EventsConsumeParams, EventsEnvelope, EventsListParams, EventsWalkParams, FetchLike2 as FetchLike, FtTransfer, FtTransferEvent, FtTransferPayload2 as FtTransferPayload, FtTransfersEnvelope, FtTransfersListParams, FtTransfersResource, FtTransfersWalkParams, INDEX_MAX_PAGE_SIZE, INSTANCE_TOKEN_ENV, Index, IndexAlwaysFields, IndexBlock, IndexCanonicalBlock, IndexConsumeOptions, IndexContractCall, IndexDiscovery, IndexEvent, IndexEventFields, IndexEventOf, IndexEventType, IndexEventTypeFilters, IndexEventsResource, IndexFeedEnvelope, IndexFeedFetcher, IndexFeedItem, IndexFtBurn, IndexFtMint, IndexFtTransfer, IndexMapDelete, IndexMapInsert, IndexMapSet, IndexMempoolTransaction, IndexNestedContractCall, IndexNftBurn, IndexNftMint, IndexNftTransfer, IndexPostCondition, IndexPox5Event, IndexPox5EventTopic, IndexPoxCycle, IndexPoxFunctionCount, IndexPrint, IndexReorg, IndexSbtcDeposit, IndexSbtcDepositDetail, IndexSbtcEvent, IndexSbtcSummary, IndexSbtcWithdrawal, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawalPhase, IndexStackingAction, IndexStxBurn, IndexStxLock, IndexStxMint, IndexStxTransfer, IndexTip, IndexTransaction, IndexVarSet, InstanceClient, InstanceDiagnosis3 as InstanceDiagnosis, InstanceIssue, InstanceState, InstanceStatus, InsufficientArchiveCreditsError, LOCAL_API_URL, LoadedArchive, MemoryEtagCache, MempoolEnvelope, MempoolListParams, MempoolTransactionEnvelope, MempoolWalkParams, NftTransfer, NftTransferEvent, NftTransferPayload2 as NftTransferPayload, NftTransfersEnvelope, NftTransfersListParams, NftTransfersResource, NftTransfersWalkParams, Pox5EventsEnvelope, Pox5EventsListParams, Pox5EventsWalkParams, Pox5Resource, PoxCycleEnvelope, PoxCyclesEnvelope, PoxCyclesListParams, PoxCyclesWalkParams, PoxResource, PrintSchemaResponse, PublicStatus2 as PublicStatus, RateLimitError, ReplayResult2 as ReplayResult, RequestOptions, RewardSet2 as RewardSet, RotateSecretResponse2 as RotateSecretResponse, SbtcDepositEnvelope, SbtcDepositEvent, SbtcDepositsConsumeParams, SbtcDepositsEnvelope, SbtcDepositsListParams, SbtcDepositsWalkParams, SbtcEventTopic2 as SbtcEventTopic, SbtcEventsConsumeParams, SbtcEventsEnvelope, SbtcEventsListParams, SbtcEventsWalkParams, SbtcResource, SbtcSummaryEnvelope, SbtcWithdrawalEnvelope, SbtcWithdrawalEvent, SbtcWithdrawalStatus, SbtcWithdrawalSweptConfirmedEvent, SbtcWithdrawalsEnvelope, SbtcWithdrawalsListParams, SbtcWithdrawalsWalkParams, SecondLayer, SecondLayerArchive, SecondLayerError, SecondLayerErrorOptions, SecondLayerOptions, SinkTx, StackingEnvelope, StackingListParams, StackingWalkParams, StandardWebhooksHeaders2 as StandardWebhooksHeaders, StreamsBatch, StreamsBatchContext, StreamsCanonicalBlock, StreamsClient, StreamsConsumeParams, StreamsDumpFile, StreamsDumps, StreamsDumpsManifest, StreamsEvent, StreamsEventPayload, StreamsEventType, StreamsEventsConsumeParams, StreamsEventsConsumeResult, StreamsEventsEnvelope, StreamsEventsListEnvelope, StreamsEventsListParams, StreamsEventsStreamParams, StreamsEventsSubscribeParams, StreamsReorg, StreamsReorgContext, StreamsReorgsListEnvelope, StreamsReorgsListParams, StreamsServerError, StreamsSignatureError, StreamsSubscription, StreamsTip, StreamsWireEvent2 as StreamsWireEvent, SubgraphAgentSchema3 as SubgraphAgentSchema, SubgraphOperationStatus, SubgraphSpecFormat2 as SubgraphSpecFormat, SubgraphSpecOptions3 as SubgraphSpecOptions, Subgraphs, TransactionEnvelope, TransactionProof, TransactionProofVerifyResult, TransactionsEnvelope, TransactionsListParams, TransactionsWalkParams, UpdateWebhookRequest2 as UpdateWebhookRequest, ValidationError, VmStreamsEvent, WalkOptions, WebhookDetail2 as WebhookDetail, WebhookFormat, WebhookHeaderInput, WebhookKind, WebhookRuntime, WebhookStatus, WebhookSummary2 as WebhookSummary, WebhookTestResult2 as WebhookTestResult, Webhooks, WithSinkTx, buildDoctorReport, consumeIndexFeed, consumerHealth, contextField, createArchiveClient, createStreamsClient, decode, decodeChainWebhook, decodeClarityValue, decodeFtBurn, decodeFtMint, decodeFtTransfer, decodeNftBurn, decodeNftMint, decodeNftTransfer, decodePrint, decodeStxBurn, decodeStxLock, decodeStxMint, decodeStxTransfer, fetchRewardSet, getSubgraph, isFtBurn, isFtMint, isFtTransfer, isNftBurn, isNftMint, isNftTransfer, isPrint, isStxBurn, isStxLock, isStxMint, isStxTransfer, isSuccessDelivery, parseRetryAfter, resolveAccountKey, resolveApiKey, resolveBaseUrl, shutdownSignal, toJsonSafe, trigger, verifySecondlayerSignature, verify as verifyStandardWebhooksHeaders, verifyTransactionProof, verifyWebhookSignature };
3315
+ export { ACCOUNT_KEY_ENV, ActiveSubgraphOperation, ApiError, ArchiveAuthError, ArchiveClient, ArchiveCreditsBalance, ArchiveDataset, ArchiveFetchItem, ArchiveFetchResult, ArchiveFlow, ArchiveGateNotConfiguredError, ArchiveLoadOptions, ArchiveManifest, ArchivePartition, ArchiveQuote, ArchiveSignatureError, ArchiveStatus, ArchiveVerifyInput, ArchiveVerifyRangeStatus, ArchiveVerifyResult, AuthError, BlockEnvelope, BlocksEnvelope, BlocksListParams, BlocksWalkParams, CanonicalEnvelope, CanonicalListParams, CanonicalWalkParams, ChainApplyDeliveryOf, ChainApplyEnvelope, ChainApplyEnvelopeOf, ChainEventEnvelope, ChainFtBurnData, ChainFtMintData, ChainFtTransferData, ChainNftBurnData, ChainNftMintData, ChainNftTransferData, ChainPrintEventData, ChainReorgOrphanedEntry, ChainReorgRollbackDelivery, ChainReorgRollbackEnvelope, ChainStxBurnData, ChainStxLockData, ChainStxMintData, ChainStxTransferData, ChainTestDelivery, ChainTrigger, ChainTriggerType, ChainTxLevelEvent, ChainWebhookDelivery2 as ChainWebhookDelivery, ChainWebhookEnvelope, ConsumerBatchContext, ConsumerHealth, ConsumerSink, ContextAccount, ContextField, ContextFieldError, ContextSnapshot, ContractCallsConsumeParams, ContractCallsEnvelope, ContractCallsListParams, ContractCallsWalkParams, ContractConformance, ContractSummary, Contracts, ContractsEnvelope, ContractsListParams, CreateArchiveClientOptions, CreateWebhookRequest2 as CreateWebhookRequest, CreateWebhookResponse2 as CreateWebhookResponse, Cursor, DEFAULT_REQUEST_TIMEOUT_MS, DOWN_MIN_CONSECUTIVE, DeadRow2 as DeadRow, DecodedEventColumns, DecodedEventRow, DecodedFtBurn, DecodedFtBurnPayload, DecodedFtMint, DecodedFtMintPayload, DecodedFtTransfer, DecodedFtTransferPayload, DecodedNftBurn, DecodedNftBurnPayload, DecodedNftMint, DecodedNftMintPayload, DecodedNftTransfer, DecodedNftTransferPayload, DecodedPrint, DecodedPrintPayload, DecodedPrintValue, DecodedStxBurn, DecodedStxBurnPayload, DecodedStxLock, DecodedStxLockPayload, DecodedStxMint, DecodedStxMintPayload, DecodedStxTransfer, DecodedStxTransferPayload, DeliveryRow2 as DeliveryRow, DoctorEvidence, DoctorFix, DoctorIssue, DoctorIssueCode, DoctorReport, DoctorSeverity, EtagCache, EtagEntry, EventsConsumeParams, EventsEnvelope, EventsListParams, EventsWalkParams, FetchLike2 as FetchLike, FtTransfer, FtTransferEvent, FtTransferPayload2 as FtTransferPayload, FtTransfersEnvelope, FtTransfersListParams, FtTransfersResource, FtTransfersWalkParams, INDEX_MAX_PAGE_SIZE, INSTANCE_TOKEN_ENV, Index, IndexAlwaysFields, IndexBlock, IndexCanonicalBlock, IndexConsumeOptions, IndexContractCall, IndexDiscovery, IndexEvent, IndexEventFields, IndexEventOf, IndexEventType, IndexEventTypeFilters, IndexEventsResource, IndexFeedEnvelope, IndexFeedFetcher, IndexFeedItem, IndexFtBurn, IndexFtMint, IndexFtTransfer, IndexMapDelete, IndexMapInsert, IndexMapSet, IndexMempoolTransaction, IndexNestedContractCall, IndexNftBurn, IndexNftMint, IndexNftTransfer, IndexPostCondition, IndexPox5Event, IndexPox5EventTopic, IndexPoxCycle, IndexPoxFunctionCount, IndexPrint, IndexReorg, IndexSbtcDeposit, IndexSbtcDepositDetail, IndexSbtcEvent, IndexSbtcSummary, IndexSbtcWithdrawal, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawalPhase, IndexStackingAction, IndexStxBurn, IndexStxLock, IndexStxMint, IndexStxTransfer, IndexTip, IndexTransaction, IndexVarSet, InstanceClient, InstanceDiagnosis3 as InstanceDiagnosis, InstanceIssue, InstanceState, InstanceStatus, InsufficientArchiveCreditsError, LOCAL_API_URL, LoadedArchive, MemoryEtagCache, MempoolEnvelope, MempoolListParams, MempoolTransactionEnvelope, MempoolWalkParams, NftTransfer, NftTransferEvent, NftTransferPayload2 as NftTransferPayload, NftTransfersEnvelope, NftTransfersListParams, NftTransfersResource, NftTransfersWalkParams, Pox5EventsEnvelope, Pox5EventsListParams, Pox5EventsWalkParams, Pox5Resource, PoxCycleEnvelope, PoxCyclesEnvelope, PoxCyclesListParams, PoxCyclesWalkParams, PoxResource, PrintSchemaResponse, PublicStatus2 as PublicStatus, RateLimitError, ReplayResult2 as ReplayResult, RequestOptions, RewardSet2 as RewardSet, RotateSecretResponse2 as RotateSecretResponse, SbtcDepositEnvelope, SbtcDepositEvent, SbtcDepositsConsumeParams, SbtcDepositsEnvelope, SbtcDepositsListParams, SbtcDepositsWalkParams, SbtcEventTopic2 as SbtcEventTopic, SbtcEventsConsumeParams, SbtcEventsEnvelope, SbtcEventsListParams, SbtcEventsWalkParams, SbtcResource, SbtcSummaryEnvelope, SbtcWithdrawalEnvelope, SbtcWithdrawalEvent, SbtcWithdrawalStatus, SbtcWithdrawalSweptConfirmedEvent, SbtcWithdrawalsEnvelope, SbtcWithdrawalsListParams, SbtcWithdrawalsWalkParams, SecondLayer, SecondLayerArchive, SecondLayerError, SecondLayerErrorOptions, SecondLayerOptions, SinkTx, StackingEnvelope, StackingListParams, StackingWalkParams, StandardWebhooksHeaders2 as StandardWebhooksHeaders, StreamsBatch, StreamsBatchContext, StreamsCanonicalBlock, StreamsClient, StreamsConsumeParams, StreamsDumpFile, StreamsDumps, StreamsDumpsManifest, StreamsEvent, StreamsEventPayload, StreamsEventType, StreamsEventsConsumeParams, StreamsEventsConsumeResult, StreamsEventsEnvelope, StreamsEventsListEnvelope, StreamsEventsListParams, StreamsEventsStreamParams, StreamsEventsSubscribeParams, StreamsReorg, StreamsReorgContext, StreamsReorgsListEnvelope, StreamsReorgsListParams, StreamsServerError, StreamsSignatureError, StreamsSubscription, StreamsTip, StreamsWireEvent2 as StreamsWireEvent, SubgraphAgentSchema3 as SubgraphAgentSchema, SubgraphOperationStatus, SubgraphSpecFormat2 as SubgraphSpecFormat, SubgraphSpecOptions3 as SubgraphSpecOptions, Subgraphs, TransactionEnvelope, TransactionProof, TransactionProofVerifyResult, TransactionsEnvelope, TransactionsListParams, TransactionsWalkParams, UpdateWebhookRequest2 as UpdateWebhookRequest, ValidationError, VmStreamsEvent, WalkOptions, WebhookActivity2 as WebhookActivity, WebhookActivityHour, WebhookDeliveryDetail2 as WebhookDeliveryDetail, WebhookDetail2 as WebhookDetail, WebhookFormat, WebhookHeaderInput, WebhookKind, WebhookRuntime, WebhookStatus, WebhookSummary2 as WebhookSummary, WebhookTestResult2 as WebhookTestResult, Webhooks, WithSinkTx, buildDoctorReport, buildListIssue, consumeIndexFeed, consumerHealth, contextField, createArchiveClient, createStreamsClient, decode, decodeChainWebhook, decodeClarityValue, decodeFtBurn, decodeFtMint, decodeFtTransfer, decodeNftBurn, decodeNftMint, decodeNftTransfer, decodePrint, decodeStxBurn, decodeStxLock, decodeStxMint, decodeStxTransfer, fetchRewardSet, getSubgraph, isFtBurn, isFtMint, isFtTransfer, isNftBurn, isNftMint, isNftTransfer, isPrint, isStxBurn, isStxLock, isStxMint, isStxTransfer, isSuccessDelivery, parseRetryAfter, resolveAccountKey, resolveApiKey, resolveBaseUrl, shutdownSignal, toJsonSafe, trigger, verifySecondlayerSignature, verify as verifyStandardWebhooksHeaders, verifyTransactionProof, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -2521,6 +2521,12 @@ class Webhooks extends BaseClient {
2521
2521
  async deliveries(id) {
2522
2522
  return this.request("GET", `/api/webhooks/${seg(id)}/deliveries`);
2523
2523
  }
2524
+ async activity(id) {
2525
+ return this.request("GET", `/api/webhooks/${seg(id)}/activity`);
2526
+ }
2527
+ async delivery(id, deliveryId) {
2528
+ return this.request("GET", `/api/webhooks/${seg(id)}/deliveries/${seg(deliveryId)}`);
2529
+ }
2524
2530
  async replay(id, range) {
2525
2531
  return this.request("POST", `/api/webhooks/${seg(id)}/replay`, range);
2526
2532
  }
@@ -2674,6 +2680,229 @@ function getSubgraph(def, options = {}) {
2674
2680
  function isSuccessDelivery(row) {
2675
2681
  return row.statusCode !== null && row.statusCode >= 200 && row.statusCode < 300;
2676
2682
  }
2683
+ var RATE_LIMITED_MIN_ATTEMPTS = 10;
2684
+ var RATE_LIMITED_MIN_RATIO = 0.5;
2685
+ var DOWN_MIN_CONSECUTIVE = 5;
2686
+ var REJECTS_MIN_CONSECUTIVE = 5;
2687
+ var SLOW_WINDOW = 20;
2688
+ var SLOW_MIN_SAMPLES = 5;
2689
+ var SLOW_TIMEOUT_RATIO = 0.5;
2690
+ var LAG_WINDOW = 20;
2691
+ var LAG_MIN_SAMPLES = 5;
2692
+ var LAG_THRESHOLD_MS = 60000;
2693
+ var ERROR_SNIPPET_MAX = 200;
2694
+ function median(values) {
2695
+ if (values.length === 0)
2696
+ return 0;
2697
+ const sorted = [...values].sort((a, b) => a - b);
2698
+ return sorted[Math.floor(sorted.length / 2)] ?? 0;
2699
+ }
2700
+ function percentile(values, p) {
2701
+ if (values.length === 0)
2702
+ return 0;
2703
+ const sorted = [...values].sort((a, b) => a - b);
2704
+ const idx = Math.min(sorted.length - 1, Math.floor(p * sorted.length));
2705
+ return sorted[idx] ?? 0;
2706
+ }
2707
+ function formatMs(ms) {
2708
+ return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${Math.round(ms)}ms`;
2709
+ }
2710
+ function formatShortDate(iso) {
2711
+ return `${iso.slice(0, 10)} ${iso.slice(11, 16)} UTC`;
2712
+ }
2713
+ function consecutiveFromStart(rows, predicate) {
2714
+ const out = [];
2715
+ for (const row of rows) {
2716
+ if (!predicate(row))
2717
+ break;
2718
+ out.push(row);
2719
+ }
2720
+ return out;
2721
+ }
2722
+ function summarizeStatusBreakdown(rows) {
2723
+ const counts = new Map;
2724
+ for (const row of rows) {
2725
+ const key = row.statusCode === null ? "timeout/no response" : String(row.statusCode);
2726
+ counts.set(key, (counts.get(key) ?? 0) + 1);
2727
+ }
2728
+ return [...counts.entries()].map(([key, n]) => `${n}× ${key}`).join(", ");
2729
+ }
2730
+ var RETRY_AFTER_RE = /retry-after:?\s*(\d+)/i;
2731
+ function extractRetryAfterSeconds(rows) {
2732
+ for (const row of rows) {
2733
+ if (row.statusCode !== 429 || !row.errorMessage)
2734
+ continue;
2735
+ const match = row.errorMessage.match(RETRY_AFTER_RE);
2736
+ if (match?.[1])
2737
+ return match[1];
2738
+ }
2739
+ return null;
2740
+ }
2741
+ function detectReceiverRateLimited(webhook, deliveries) {
2742
+ if (deliveries.length < RATE_LIMITED_MIN_ATTEMPTS)
2743
+ return null;
2744
+ const count429 = deliveries.filter((d) => d.statusCode === 429).length;
2745
+ if (count429 / deliveries.length < RATE_LIMITED_MIN_RATIO)
2746
+ return null;
2747
+ const oldest = deliveries[deliveries.length - 1];
2748
+ const newest = deliveries[0];
2749
+ const evidence = [
2750
+ {
2751
+ label: "429 responses",
2752
+ value: `${count429} of ${deliveries.length} attempts`
2753
+ },
2754
+ {
2755
+ label: "window",
2756
+ value: oldest && newest ? `${formatShortDate(oldest.dispatchedAt)} → ${formatShortDate(newest.dispatchedAt)}` : "unknown"
2757
+ }
2758
+ ];
2759
+ const retryAfter = extractRetryAfterSeconds(deliveries);
2760
+ if (retryAfter) {
2761
+ evidence.push({ label: "latest Retry-After", value: `${retryAfter}s` });
2762
+ }
2763
+ const suggestedConcurrency = Math.max(1, Math.floor(webhook.concurrency / 2));
2764
+ return {
2765
+ code: "receiver_rate_limited",
2766
+ severity: "warn",
2767
+ evidence,
2768
+ fix: {
2769
+ text: "Lower concurrency, or honor the Retry-After header on your receiver.",
2770
+ command: `secondlayer webhooks update ${webhook.id} --concurrency ${suggestedConcurrency}`,
2771
+ docsPath: "/docs/webhooks#receiver-rate-limited"
2772
+ }
2773
+ };
2774
+ }
2775
+ function detectReceiverDown(webhook, deliveries) {
2776
+ const streak = consecutiveFromStart(deliveries, (d) => d.statusCode === null || d.statusCode >= 500);
2777
+ if (streak.length < DOWN_MIN_CONSECUTIVE)
2778
+ return null;
2779
+ return {
2780
+ code: "receiver_down",
2781
+ severity: "bad",
2782
+ evidence: [
2783
+ { label: "consecutive failures", value: String(streak.length) },
2784
+ { label: "breakdown", value: summarizeStatusBreakdown(streak) },
2785
+ {
2786
+ label: "last success",
2787
+ value: webhook.lastSuccessAt ? formatShortDate(webhook.lastSuccessAt) : "never"
2788
+ }
2789
+ ],
2790
+ fix: {
2791
+ text: "Check your receiver's health and logs, then send a test event.",
2792
+ command: `secondlayer webhooks test ${webhook.id}`,
2793
+ docsPath: "/docs/webhooks#receiver-down"
2794
+ }
2795
+ };
2796
+ }
2797
+ function detectReceiverRejects(webhook, deliveries) {
2798
+ const streak = consecutiveFromStart(deliveries, (d) => d.statusCode !== null && d.statusCode >= 400 && d.statusCode < 500 && d.statusCode !== 429);
2799
+ if (streak.length < REJECTS_MIN_CONSECUTIVE)
2800
+ return null;
2801
+ const evidence = [
2802
+ { label: "consecutive rejects", value: String(streak.length) },
2803
+ { label: "breakdown", value: summarizeStatusBreakdown(streak) }
2804
+ ];
2805
+ const withText = streak.find((d) => d.errorMessage || d.responseBody);
2806
+ const snippet = withText ? (withText.errorMessage ?? withText.responseBody ?? "").slice(0, ERROR_SNIPPET_MAX) : null;
2807
+ if (snippet)
2808
+ evidence.push({ label: "first error", value: snippet });
2809
+ return {
2810
+ code: "receiver_rejects",
2811
+ severity: "bad",
2812
+ evidence,
2813
+ fix: {
2814
+ text: "Check your receiver's auth config or signature verification.",
2815
+ command: `secondlayer webhooks test ${webhook.id}`,
2816
+ docsPath: "/docs/webhooks#receiver-rejects"
2817
+ }
2818
+ };
2819
+ }
2820
+ function detectReceiverSlow(webhook, deliveries) {
2821
+ const durations = deliveries.slice(0, SLOW_WINDOW).map((d) => d.durationMs).filter((d) => d !== null);
2822
+ if (durations.length < SLOW_MIN_SAMPLES)
2823
+ return null;
2824
+ const med = median(durations);
2825
+ if (med < webhook.timeoutMs * SLOW_TIMEOUT_RATIO)
2826
+ return null;
2827
+ return {
2828
+ code: "receiver_slow",
2829
+ severity: "warn",
2830
+ evidence: [
2831
+ { label: "median response time", value: formatMs(med) },
2832
+ {
2833
+ label: "p95 response time",
2834
+ value: formatMs(percentile(durations, 0.95))
2835
+ },
2836
+ { label: "timeout", value: formatMs(webhook.timeoutMs) }
2837
+ ],
2838
+ fix: {
2839
+ text: "Speed up your receiver, or raise the timeout (up to 30s hosted).",
2840
+ command: `secondlayer webhooks update ${webhook.id} --timeout-ms 30000`,
2841
+ docsPath: "/docs/webhooks#receiver-slow"
2842
+ }
2843
+ };
2844
+ }
2845
+ function detectDeliveryLag(deliveries) {
2846
+ const window = deliveries.slice(0, LAG_WINDOW).filter((d) => d.blockTime !== null);
2847
+ if (window.length < LAG_MIN_SAMPLES)
2848
+ return null;
2849
+ const lags = window.map((d) => new Date(d.dispatchedAt).getTime() - new Date(d.blockTime).getTime());
2850
+ const med = median(lags);
2851
+ if (med <= LAG_THRESHOLD_MS)
2852
+ return null;
2853
+ const blockTimes = window.map((d) => d.blockTime).sort();
2854
+ const oldest = blockTimes[0];
2855
+ const newest = blockTimes[blockTimes.length - 1];
2856
+ return {
2857
+ code: "delivery_lag",
2858
+ severity: "warn",
2859
+ evidence: [
2860
+ { label: "median lag", value: formatMs(med) },
2861
+ {
2862
+ label: "block time range",
2863
+ value: oldest && newest ? `${formatShortDate(oldest)} → ${formatShortDate(newest)}` : "unknown"
2864
+ }
2865
+ ],
2866
+ fix: {
2867
+ text: "We're behind on delivery; no action needed on your end."
2868
+ }
2869
+ };
2870
+ }
2871
+ var SEVERITY_RANK = {
2872
+ bad: 0,
2873
+ warn: 1,
2874
+ calm: 2
2875
+ };
2876
+ var CODE_PRIORITY = [
2877
+ "circuit",
2878
+ "receiver_down",
2879
+ "receiver_rejects",
2880
+ "dead_letters",
2881
+ "paused",
2882
+ "last_error",
2883
+ "warning",
2884
+ "receiver_rate_limited",
2885
+ "receiver_slow",
2886
+ "delivery_lag",
2887
+ "no_deliveries",
2888
+ "subgraph_gaps",
2889
+ "subgraph_catching_up"
2890
+ ];
2891
+ function pickPrimary(issues) {
2892
+ if (issues.length === 0)
2893
+ return null;
2894
+ return [...issues].sort((a, b) => {
2895
+ const sevDiff = SEVERITY_RANK[a.severity] - SEVERITY_RANK[b.severity];
2896
+ if (sevDiff !== 0)
2897
+ return sevDiff;
2898
+ return CODE_PRIORITY.indexOf(a.code) - CODE_PRIORITY.indexOf(b.code);
2899
+ })[0] ?? null;
2900
+ }
2901
+ function hintFor(issue) {
2902
+ if (!issue.fix)
2903
+ return issue.detail ?? issue.code;
2904
+ return issue.fix.command ? `${issue.fix.text} ${issue.fix.command}` : issue.fix.text;
2905
+ }
2677
2906
  function buildDoctorReport(input) {
2678
2907
  const successful = input.deliveries.filter(isSuccessDelivery).length;
2679
2908
  const failed = input.deliveries.length - successful;
@@ -2690,35 +2919,60 @@ function buildDoctorReport(input) {
2690
2919
  const issues = [];
2691
2920
  if (input.webhook.warning) {
2692
2921
  hints.push(input.webhook.warning);
2693
- issues.push({ code: "warning", detail: input.webhook.warning });
2922
+ issues.push({
2923
+ code: "warning",
2924
+ detail: input.webhook.warning,
2925
+ severity: "warn"
2926
+ });
2694
2927
  }
2695
2928
  if (input.webhook.status === "paused") {
2696
2929
  hints.push(`Resume when the receiver is healthy: secondlayer webhooks resume ${input.webhook.id}`);
2697
- issues.push({ code: "paused" });
2930
+ issues.push({ code: "paused", severity: "warn" });
2698
2931
  }
2699
2932
  if (input.webhook.lastError) {
2700
2933
  hints.push("Run secondlayer webhooks test to reproduce the receiver request.");
2701
- issues.push({ code: "last_error", detail: input.webhook.lastError });
2934
+ issues.push({
2935
+ code: "last_error",
2936
+ detail: input.webhook.lastError,
2937
+ severity: "warn"
2938
+ });
2702
2939
  }
2703
2940
  if (input.webhook.circuitOpenedAt || input.webhook.circuitFailures > 0) {
2704
2941
  hints.push("Circuit breaker has failures; inspect receiver logs and delivery status codes.");
2705
- issues.push({ code: "circuit" });
2942
+ issues.push({ code: "circuit", severity: "bad" });
2706
2943
  }
2707
2944
  if (input.dead.length > 0) {
2708
2945
  hints.push(`Dead-letter rows exist; inspect with secondlayer webhooks dead ${input.webhook.id} and requeue selected rows.`);
2709
- issues.push({ code: "dead_letters" });
2946
+ issues.push({ code: "dead_letters", severity: "bad" });
2710
2947
  }
2711
2948
  if (subgraph?.gapCount && subgraph.gapCount > 0) {
2712
2949
  hints.push(`Linked subgraph has gaps; run secondlayer subgraphs gaps ${input.webhook.subgraphName}.`);
2713
- issues.push({ code: "subgraph_gaps" });
2950
+ issues.push({ code: "subgraph_gaps", severity: "calm" });
2714
2951
  }
2715
2952
  if (subgraph?.syncStatus === "catching_up") {
2716
2953
  hints.push("Linked subgraph is still catching up; new matching rows may arrive later.");
2717
- issues.push({ code: "subgraph_catching_up" });
2954
+ issues.push({ code: "subgraph_catching_up", severity: "calm" });
2955
+ }
2956
+ for (const detector of [
2957
+ detectReceiverRateLimited,
2958
+ detectReceiverDown,
2959
+ detectReceiverRejects,
2960
+ detectReceiverSlow
2961
+ ]) {
2962
+ const issue = detector(input.webhook, input.deliveries);
2963
+ if (issue) {
2964
+ issues.push(issue);
2965
+ hints.push(hintFor(issue));
2966
+ }
2967
+ }
2968
+ const lagIssue = detectDeliveryLag(input.deliveries);
2969
+ if (lagIssue) {
2970
+ issues.push(lagIssue);
2971
+ hints.push(hintFor(lagIssue));
2718
2972
  }
2719
2973
  if (input.deliveries.length === 0) {
2720
2974
  hints.push("No deliveries yet; confirm the table is receiving inserted rows that match the filter.");
2721
- issues.push({ code: "no_deliveries" });
2975
+ issues.push({ code: "no_deliveries", severity: "calm" });
2722
2976
  }
2723
2977
  if (hints.length === 0) {
2724
2978
  hints.push("No immediate action needed.");
@@ -2734,9 +2988,35 @@ function buildDoctorReport(input) {
2734
2988
  deadCount: input.dead.length,
2735
2989
  subgraph,
2736
2990
  hints,
2737
- issues
2991
+ issues,
2992
+ primary: pickPrimary(issues)
2738
2993
  };
2739
2994
  }
2995
+ function buildListIssue(webhook) {
2996
+ if (webhook.status !== "paused")
2997
+ return null;
2998
+ if (webhook.circuitOpenedAt) {
2999
+ return {
3000
+ code: "circuit",
3001
+ severity: "bad",
3002
+ evidence: [
3003
+ {
3004
+ label: "circuit opened",
3005
+ value: formatShortDate(webhook.circuitOpenedAt)
3006
+ },
3007
+ {
3008
+ label: "last success",
3009
+ value: webhook.lastSuccessAt ? formatShortDate(webhook.lastSuccessAt) : "never"
3010
+ }
3011
+ ],
3012
+ fix: {
3013
+ text: "Check your receiver's health and logs, then send a test event.",
3014
+ docsPath: "/docs/webhooks#receiver-down"
3015
+ }
3016
+ };
3017
+ }
3018
+ return { code: "paused", severity: "warn" };
3019
+ }
2740
3020
  // src/consumer-ops.ts
2741
3021
  function consumerHealth(options = {}) {
2742
3022
  const staleAfterMs = options.staleAfterMs ?? 120000;
@@ -2975,6 +3255,7 @@ export {
2975
3255
  Contracts,
2976
3256
  Cursor,
2977
3257
  DEFAULT_REQUEST_TIMEOUT_MS,
3258
+ DOWN_MIN_CONSECUTIVE,
2978
3259
  INDEX_MAX_PAGE_SIZE,
2979
3260
  INSTANCE_TOKEN_ENV,
2980
3261
  Index,
@@ -2990,6 +3271,7 @@ export {
2990
3271
  ValidationError,
2991
3272
  Webhooks,
2992
3273
  buildDoctorReport,
3274
+ buildListIssue,
2993
3275
  consumeIndexFeed,
2994
3276
  consumerHealth,
2995
3277
  contextField,
@@ -3036,5 +3318,5 @@ export {
3036
3318
  verifyWebhookSignature
3037
3319
  };
3038
3320
 
3039
- //# debugId=0DD763C5B88AC34564756E2164756E21
3321
+ //# debugId=2EAB2350044234C964756E2164756E21
3040
3322
  //# sourceMappingURL=index.js.map