@secondlayer/sdk 16.2.1 → 16.3.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 +49 -3
- package/dist/index.js +178 -62
- package/dist/index.js.map +11 -10
- package/dist/streams/index.d.ts +17 -1
- package/dist/streams/index.js +171 -59
- package/dist/streams/index.js.map +9 -8
- package/dist/subgraphs/index.d.ts +12 -0
- package/dist/subgraphs/index.js +171 -59
- package/dist/subgraphs/index.js.map +9 -8
- package/dist/webhooks/doctor.d.ts +2 -2
- package/dist/webhooks/doctor.js +6 -4
- package/dist/webhooks/doctor.js.map +3 -3
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -324,6 +324,33 @@ declare function resolveApiKey(apiKey?: string, baseUrl?: string): string | unde
|
|
|
324
324
|
* Precedence: explicit `accountKey` → `SECONDLAYER_API_KEY`. Does not read
|
|
325
325
|
* `INSTANCE_TOKEN`. */
|
|
326
326
|
declare function resolveAccountKey(accountKey?: string): string | undefined;
|
|
327
|
+
/** Hosted account API for credits, archive fetches and login. Not the
|
|
328
|
+
* operator's loopback box. `SL_CREDITS_API_URL` (or the older
|
|
329
|
+
* `ARCHIVE_OPS_API_URL`) points it elsewhere, e.g. at a staging stack. */
|
|
330
|
+
declare function resolveAccountUrl(): string;
|
|
331
|
+
/** Where a resolved credential came from. `none` = nothing usable was found. */
|
|
332
|
+
type IdentitySource = "env" | "session" | "none";
|
|
333
|
+
interface Identity {
|
|
334
|
+
source: IdentitySource;
|
|
335
|
+
/** Bearer token, `undefined` when `source` is `none`. */
|
|
336
|
+
token: string | undefined;
|
|
337
|
+
/** The server this credential is for. */
|
|
338
|
+
url: string;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* The one credential resolver the CLI and MCP share. One precedence, highest
|
|
342
|
+
* first: an env key, then the stored login session (`session`, supplied by
|
|
343
|
+
* callers that have one; the SDK itself never touches the filesystem).
|
|
344
|
+
*
|
|
345
|
+
* target "account" env = `SECONDLAYER_API_KEY` when it is an account
|
|
346
|
+
* credential (`sk-sl_` / `ss-sl_`); url = {@link resolveAccountUrl}
|
|
347
|
+
* target "instance" env = `INSTANCE_TOKEN`; url = {@link resolveBaseUrl}
|
|
348
|
+
*
|
|
349
|
+
* An env key of the wrong kind is ignored rather than sent to the wrong host.
|
|
350
|
+
*/
|
|
351
|
+
declare function resolveIdentity(target: "account" | "instance", options?: {
|
|
352
|
+
session?: string | null;
|
|
353
|
+
}): Identity;
|
|
327
354
|
declare abstract class BaseClient {
|
|
328
355
|
protected baseUrl: string;
|
|
329
356
|
protected apiKey?: string;
|
|
@@ -832,6 +859,8 @@ type StreamsEventsStreamBitcoinParams = StreamsEventsStreamCommon & {
|
|
|
832
859
|
address?: string;
|
|
833
860
|
};
|
|
834
861
|
type StreamsEventsStreamParams = StreamsEventsStreamStacksParams | StreamsEventsStreamBitcoinParams;
|
|
862
|
+
/** Where a `subscribe` connection is in its lifecycle. */
|
|
863
|
+
type StreamsSubscriptionState = "connecting" | "open" | "reconnecting" | "closed";
|
|
835
864
|
type StreamsEventsSubscribeCommon = {
|
|
836
865
|
/** Resume strictly after this cursor; omit to live-tail from the tip. */
|
|
837
866
|
fromCursor?: string | null;
|
|
@@ -845,6 +874,13 @@ type StreamsEventsSubscribeCommon = {
|
|
|
845
874
|
*/
|
|
846
875
|
onError?: (err: unknown) => void;
|
|
847
876
|
/**
|
|
877
|
+
* Lifecycle observer. `connecting` before each connection attempt, `open`
|
|
878
|
+
* once the server answers, `reconnecting` while backing off after a drop
|
|
879
|
+
* or error, `closed` once, when the subscription ends (unsubscribed,
|
|
880
|
+
* aborted, or stopped by an error a retry cannot fix).
|
|
881
|
+
*/
|
|
882
|
+
onState?: (state: StreamsSubscriptionState) => void;
|
|
883
|
+
/**
|
|
848
884
|
* First reconnect pause in ms (default 1000). Doubles per consecutive
|
|
849
885
|
* failure up to 30 s with jitter, resets once a frame arrives, and never
|
|
850
886
|
* undercuts a `Retry-After`.
|
|
@@ -2378,6 +2414,9 @@ type IndexSbtcWithdrawal = {
|
|
|
2378
2414
|
btc_block_height: number | null;
|
|
2379
2415
|
/** When the sweep crossed the confirmation threshold (ISO), null otherwise. */
|
|
2380
2416
|
confirmed_at: string | null;
|
|
2417
|
+
/** Monotonic stamp taken when the sweep became confirmed; resume a scan
|
|
2418
|
+
* from it with `confirmed_after_seq`. Null while unsettled. */
|
|
2419
|
+
settlement_seq: number | null;
|
|
2381
2420
|
requested_at?: string | null;
|
|
2382
2421
|
resolved_at?: string | null;
|
|
2383
2422
|
};
|
|
@@ -3985,11 +4024,11 @@ declare function buildDoctorReport(input: {
|
|
|
3985
4024
|
* The list page's own reduced detector: computed from `WebhookSummary` alone
|
|
3986
4025
|
* (no deliveries, no dead-letter rows — the list endpoint returns neither,
|
|
3987
4026
|
* and fetching per-row detail or deliveries here would fan out one request
|
|
3988
|
-
* per row). Only `status` and `
|
|
4027
|
+
* per row). Only `status` and `pauseReason` distinguish a real problem
|
|
3989
4028
|
* from a manual pause at this level; deliveries-based rules (rate limits,
|
|
3990
4029
|
* downtime, rejects, slowness, lag) only ever show on the detail page.
|
|
3991
4030
|
*/
|
|
3992
|
-
declare function buildListIssue(webhook: Pick<WebhookSummary3, "status" | "circuitOpenedAt" | "lastSuccessAt">): DoctorIssue | null;
|
|
4031
|
+
declare function buildListIssue(webhook: Pick<WebhookSummary3, "status" | "pauseReason" | "circuitOpenedAt" | "lastSuccessAt">): DoctorIssue | null;
|
|
3993
4032
|
/**
|
|
3994
4033
|
* The two pieces every "deploy a consumer" guide leaves out, packaged:
|
|
3995
4034
|
* a liveness endpoint and a graceful-shutdown signal. Both are
|
|
@@ -4325,6 +4364,13 @@ type CreateStreamsClientOptions = {
|
|
|
4325
4364
|
origin?: "cli" | "mcp" | "session";
|
|
4326
4365
|
fetchImpl?: FetchLike2;
|
|
4327
4366
|
/**
|
|
4367
|
+
* Give up on a request that has not connected and returned response headers
|
|
4368
|
+
* within this many ms (default 30000; `0` disables). Retryable: the consume
|
|
4369
|
+
* loops retry it and `subscribe` reconnects. Body reads are not covered, so
|
|
4370
|
+
* a healthy long-lived stream is never cut off.
|
|
4371
|
+
*/
|
|
4372
|
+
connectTimeoutMs?: number;
|
|
4373
|
+
/**
|
|
4328
4374
|
* Public base URL for bulk parquet dumps (the R2/CDN bucket root). Required
|
|
4329
4375
|
* to use `client.dumps`. See `GET /public/streams/dumps/manifest`.
|
|
4330
4376
|
*/
|
|
@@ -4423,4 +4469,4 @@ declare const Cursor: {
|
|
|
4423
4469
|
};
|
|
4424
4470
|
};
|
|
4425
4471
|
import { decodeClarityValue, toJsonSafe } from "@secondlayer/shared/streams-rows";
|
|
4426
|
-
export { ACCOUNT_KEY_ENV, ActiveSubgraphOperation, ApiError, ArchiveAuthError, ArchiveClient, ArchiveCreditsBalance, ArchiveDataset, ArchiveFetchItem, ArchiveFetchResult, ArchiveFlow, ArchiveGateNotConfiguredError, ArchiveLoadOptions, ArchiveManifest, ArchivePartition, ArchiveQuote, ArchiveSignatureError, ArchiveStatus, ArchiveVerifyInput, ArchiveVerifyRangeStatus, ArchiveVerifyResult, AuthError, BitcoinOutputSpent, BitcoinOutputUnspent, BitcoinOutspend, BitcoinResource, 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, IndexBitcoinTip, IndexBlock, IndexBtcReorg, IndexCanonicalBlock, IndexConsumeOptions, IndexContractCall, IndexDiscovery, IndexEvent, IndexEventFields, IndexEventOf, IndexEventType, IndexEventTypeFilters, IndexEventsResource, IndexFeedEnvelope, IndexFeedFetcher, IndexFeedItem, IndexFtBurn, IndexFtMint, IndexFtTransfer, IndexMapDelete, IndexMapInsert, IndexMapSet, IndexMempoolTransaction, IndexNestedContractCall, IndexNftBurn, IndexNftMint, IndexNftTransfer, IndexOrder, IndexPostCondition, IndexPox5Event, IndexPox5EventTopic, IndexPoxCycle, IndexPoxCycleSigner, IndexPrint, IndexReorg, IndexRuneBalance, IndexRuneEntry, IndexRuneEvent, IndexRuneEventKind, IndexRuneRefSummary, IndexRuneTerms, IndexSbtcDeposit, IndexSbtcDepositDetail, IndexSbtcEvent, IndexSbtcSummary, IndexSbtcWithdrawal, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawalPhase, IndexStackingAction, IndexStateWrite, 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, Pox5EventsConsumeParams, Pox5EventsEnvelope, Pox5EventsListParams, Pox5EventsWalkParams, Pox5Resource, PoxCycleEnvelope, PoxCyclesEnvelope, PoxCyclesListParams, PoxCyclesWalkParams, PoxResource, PrintSchemaResponse, PublicStatus2 as PublicStatus, RateLimitError, ReplayResult2 as ReplayResult, RequestOptions, RewardSet2 as RewardSet, RotateSecretResponse2 as RotateSecretResponse, RuneActivityEnvelope, RuneActivityListParams, RuneActivityWalkParams, RuneApplyDeliveryOf, RuneApplyEnvelope, RuneBalancesEnvelope, RuneBalancesListParams, RuneEnvelope, RuneEtchEntry, RuneEventPayload, RuneEventType, RuneId, RuneRef, RuneStreamsEvent, RunesEnvelope, RunesListParams, RunesResource, 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, StateWritesEnvelope, StateWritesListParams, StateWritesWalkParams, StreamsBatch, StreamsBitcoinCanonicalBlock, StreamsBitcoinTip, StreamsCanonicalBlock, StreamsClient, StreamsConsumeBitcoinParams, StreamsConsumeParams, StreamsConsumeStacksParams, StreamsDumpFile, StreamsDumps, StreamsDumpsManifest, StreamsEvent, StreamsEventPayload, StreamsEventType, StreamsEventsBitcoinListParams, StreamsEventsConsumeBitcoinParams, StreamsEventsConsumeParams, StreamsEventsConsumeResult, StreamsEventsEnvelope, StreamsEventsListEnvelope, StreamsEventsListParams, StreamsEventsStacksListParams, StreamsEventsStreamBitcoinParams, StreamsEventsStreamParams, StreamsEventsStreamStacksParams, StreamsEventsSubscribeBitcoinParams, StreamsEventsSubscribeParams, StreamsEventsSubscribeStacksParams, 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, WebhookAuth, WebhookDeliveryDetail2 as WebhookDeliveryDetail, WebhookDetail2 as WebhookDetail, WebhookFormat, WebhookHeaderInput, WebhookKind, WebhookStatus, WebhookSummary2 as WebhookSummary, WebhookTestResult2 as WebhookTestResult, Webhooks, WithSinkTx, buildDoctorReport, buildListIssue, consumeIndexFeed, consumerHealth, contextField, createArchiveClient, createStreamsClient, decode, decodeChainWebhook, decodeClarityValue, fetchRewardSet, getSubgraph, isHostedApiUrl, isSuccessDelivery, parseRetryAfter, resolveAccountKey, resolveApiKey, resolveBaseUrl, shutdownSignal, toJsonSafe, trigger, verifySecondlayerSignature, verify as verifyStandardWebhooksHeaders, verifyTransactionProof, verifyWebhookSignature };
|
|
4472
|
+
export { ACCOUNT_KEY_ENV, ActiveSubgraphOperation, ApiError, ArchiveAuthError, ArchiveClient, ArchiveCreditsBalance, ArchiveDataset, ArchiveFetchItem, ArchiveFetchResult, ArchiveFlow, ArchiveGateNotConfiguredError, ArchiveLoadOptions, ArchiveManifest, ArchivePartition, ArchiveQuote, ArchiveSignatureError, ArchiveStatus, ArchiveVerifyInput, ArchiveVerifyRangeStatus, ArchiveVerifyResult, AuthError, BitcoinOutputSpent, BitcoinOutputUnspent, BitcoinOutspend, BitcoinResource, 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, Identity, IdentitySource, Index, IndexAlwaysFields, IndexBitcoinTip, IndexBlock, IndexBtcReorg, IndexCanonicalBlock, IndexConsumeOptions, IndexContractCall, IndexDiscovery, IndexEvent, IndexEventFields, IndexEventOf, IndexEventType, IndexEventTypeFilters, IndexEventsResource, IndexFeedEnvelope, IndexFeedFetcher, IndexFeedItem, IndexFtBurn, IndexFtMint, IndexFtTransfer, IndexMapDelete, IndexMapInsert, IndexMapSet, IndexMempoolTransaction, IndexNestedContractCall, IndexNftBurn, IndexNftMint, IndexNftTransfer, IndexOrder, IndexPostCondition, IndexPox5Event, IndexPox5EventTopic, IndexPoxCycle, IndexPoxCycleSigner, IndexPrint, IndexReorg, IndexRuneBalance, IndexRuneEntry, IndexRuneEvent, IndexRuneEventKind, IndexRuneRefSummary, IndexRuneTerms, IndexSbtcDeposit, IndexSbtcDepositDetail, IndexSbtcEvent, IndexSbtcSummary, IndexSbtcWithdrawal, IndexSbtcWithdrawalDetail, IndexSbtcWithdrawalPhase, IndexStackingAction, IndexStateWrite, 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, Pox5EventsConsumeParams, Pox5EventsEnvelope, Pox5EventsListParams, Pox5EventsWalkParams, Pox5Resource, PoxCycleEnvelope, PoxCyclesEnvelope, PoxCyclesListParams, PoxCyclesWalkParams, PoxResource, PrintSchemaResponse, PublicStatus2 as PublicStatus, RateLimitError, ReplayResult2 as ReplayResult, RequestOptions, RewardSet2 as RewardSet, RotateSecretResponse2 as RotateSecretResponse, RuneActivityEnvelope, RuneActivityListParams, RuneActivityWalkParams, RuneApplyDeliveryOf, RuneApplyEnvelope, RuneBalancesEnvelope, RuneBalancesListParams, RuneEnvelope, RuneEtchEntry, RuneEventPayload, RuneEventType, RuneId, RuneRef, RuneStreamsEvent, RunesEnvelope, RunesListParams, RunesResource, 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, StateWritesEnvelope, StateWritesListParams, StateWritesWalkParams, StreamsBatch, StreamsBitcoinCanonicalBlock, StreamsBitcoinTip, StreamsCanonicalBlock, StreamsClient, StreamsConsumeBitcoinParams, StreamsConsumeParams, StreamsConsumeStacksParams, StreamsDumpFile, StreamsDumps, StreamsDumpsManifest, StreamsEvent, StreamsEventPayload, StreamsEventType, StreamsEventsBitcoinListParams, StreamsEventsConsumeBitcoinParams, StreamsEventsConsumeParams, StreamsEventsConsumeResult, StreamsEventsEnvelope, StreamsEventsListEnvelope, StreamsEventsListParams, StreamsEventsStacksListParams, StreamsEventsStreamBitcoinParams, StreamsEventsStreamParams, StreamsEventsStreamStacksParams, StreamsEventsSubscribeBitcoinParams, StreamsEventsSubscribeParams, StreamsEventsSubscribeStacksParams, StreamsReorg, StreamsReorgContext, StreamsReorgsListEnvelope, StreamsReorgsListParams, StreamsServerError, StreamsSignatureError, StreamsSubscription, StreamsSubscriptionState, 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, WebhookAuth, WebhookDeliveryDetail2 as WebhookDeliveryDetail, WebhookDetail2 as WebhookDetail, WebhookFormat, WebhookHeaderInput, WebhookKind, WebhookStatus, WebhookSummary2 as WebhookSummary, WebhookTestResult2 as WebhookTestResult, Webhooks, WithSinkTx, buildDoctorReport, buildListIssue, consumeIndexFeed, consumerHealth, contextField, createArchiveClient, createStreamsClient, decode, decodeChainWebhook, decodeClarityValue, fetchRewardSet, getSubgraph, isHostedApiUrl, isSuccessDelivery, parseRetryAfter, resolveAccountKey, resolveAccountUrl, resolveApiKey, resolveBaseUrl, resolveIdentity, shutdownSignal, toJsonSafe, trigger, verifySecondlayerSignature, verify as verifyStandardWebhooksHeaders, verifyTransactionProof, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -251,6 +251,22 @@ function resolveAccountKey(accountKey) {
|
|
|
251
251
|
return;
|
|
252
252
|
return process.env?.SECONDLAYER_API_KEY || undefined;
|
|
253
253
|
}
|
|
254
|
+
function resolveAccountUrl() {
|
|
255
|
+
const env = typeof process !== "undefined" ? process.env : undefined;
|
|
256
|
+
return (env?.SL_CREDITS_API_URL || env?.ARCHIVE_OPS_API_URL || HOSTED_API_URL).replace(/\/+$/, "");
|
|
257
|
+
}
|
|
258
|
+
var ACCOUNT_CREDENTIAL_RE = /^s[ks]-sl_/;
|
|
259
|
+
function resolveIdentity(target, options = {}) {
|
|
260
|
+
const url = target === "account" ? resolveAccountUrl() : resolveBaseUrl();
|
|
261
|
+
const envKey = target === "account" ? resolveAccountKey() : typeof process !== "undefined" ? process.env?.[INSTANCE_TOKEN_ENV] || undefined : undefined;
|
|
262
|
+
if (envKey && (target === "instance" || ACCOUNT_CREDENTIAL_RE.test(envKey))) {
|
|
263
|
+
return { source: "env", token: envKey, url };
|
|
264
|
+
}
|
|
265
|
+
if (options.session) {
|
|
266
|
+
return { source: "session", token: options.session, url };
|
|
267
|
+
}
|
|
268
|
+
return { source: "none", token: undefined, url };
|
|
269
|
+
}
|
|
254
270
|
function seg(value) {
|
|
255
271
|
return encodeURIComponent(String(value));
|
|
256
272
|
}
|
|
@@ -1006,13 +1022,70 @@ async function consumeStreamsEvents(opts) {
|
|
|
1006
1022
|
}
|
|
1007
1023
|
return { cursor, pages, emptyPolls };
|
|
1008
1024
|
}
|
|
1025
|
+
async function* pullFromLoop(start, external) {
|
|
1026
|
+
const controller = new AbortController;
|
|
1027
|
+
if (external) {
|
|
1028
|
+
if (external.aborted)
|
|
1029
|
+
controller.abort();
|
|
1030
|
+
else
|
|
1031
|
+
external.addEventListener("abort", () => controller.abort(), {
|
|
1032
|
+
once: true
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
const state = {
|
|
1036
|
+
delivered: null,
|
|
1037
|
+
held: null,
|
|
1038
|
+
finished: false,
|
|
1039
|
+
failure: null,
|
|
1040
|
+
wake: null
|
|
1041
|
+
};
|
|
1042
|
+
const notify = () => {
|
|
1043
|
+
const resolve = state.wake;
|
|
1044
|
+
state.wake = null;
|
|
1045
|
+
resolve?.();
|
|
1046
|
+
};
|
|
1047
|
+
const loop = start((value) => new Promise((release) => {
|
|
1048
|
+
state.delivered = { value, release };
|
|
1049
|
+
notify();
|
|
1050
|
+
}), controller.signal).then(() => {
|
|
1051
|
+
state.finished = true;
|
|
1052
|
+
}, (error) => {
|
|
1053
|
+
state.failure = { error };
|
|
1054
|
+
state.finished = true;
|
|
1055
|
+
}).finally(notify);
|
|
1056
|
+
try {
|
|
1057
|
+
while (true) {
|
|
1058
|
+
if (state.delivered) {
|
|
1059
|
+
const { value, release } = state.delivered;
|
|
1060
|
+
state.delivered = null;
|
|
1061
|
+
state.held = release;
|
|
1062
|
+
yield value;
|
|
1063
|
+
state.held = null;
|
|
1064
|
+
release();
|
|
1065
|
+
continue;
|
|
1066
|
+
}
|
|
1067
|
+
if (state.finished)
|
|
1068
|
+
break;
|
|
1069
|
+
await new Promise((resolve) => {
|
|
1070
|
+
state.wake = resolve;
|
|
1071
|
+
if (state.delivered || state.finished)
|
|
1072
|
+
notify();
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
if (state.failure)
|
|
1076
|
+
throw state.failure.error;
|
|
1077
|
+
} finally {
|
|
1078
|
+
controller.abort();
|
|
1079
|
+
state.held?.();
|
|
1080
|
+
state.delivered?.release();
|
|
1081
|
+
await loop;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1009
1084
|
async function* iterateStreamsBatches(opts) {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
cursor,
|
|
1015
|
-
limit: opts.batchSize,
|
|
1085
|
+
yield* pullFromLoop(async (deliver, signal) => {
|
|
1086
|
+
const result = await consumeStreamsEvents({
|
|
1087
|
+
fromCursor: opts.fromCursor,
|
|
1088
|
+
batchSize: opts.batchSize,
|
|
1016
1089
|
chain: opts.chain,
|
|
1017
1090
|
types: opts.types,
|
|
1018
1091
|
notTypes: opts.notTypes,
|
|
@@ -1022,38 +1095,41 @@ async function* iterateStreamsBatches(opts) {
|
|
|
1022
1095
|
assetIdentifier: opts.assetIdentifier,
|
|
1023
1096
|
rune: opts.rune,
|
|
1024
1097
|
address: opts.address,
|
|
1025
|
-
filters: opts.filters
|
|
1098
|
+
filters: opts.filters,
|
|
1099
|
+
fetchEvents: opts.fetchEvents,
|
|
1100
|
+
sleep: opts.sleep,
|
|
1101
|
+
emptyBackoffMs: opts.intervalMs,
|
|
1102
|
+
signal,
|
|
1103
|
+
onBatch: async (events, ctx) => {
|
|
1104
|
+
if (events.length === 0 && ctx.reorgs.length === 0)
|
|
1105
|
+
return;
|
|
1106
|
+
await deliver({
|
|
1107
|
+
events,
|
|
1108
|
+
cursor: ctx.cursor,
|
|
1109
|
+
tip: ctx.tip,
|
|
1110
|
+
reorgs: [...ctx.reorgs]
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1026
1113
|
});
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
if (!advanced && envelope.events.length === 0) {
|
|
1039
|
-
if (opts.signal?.aborted)
|
|
1040
|
-
return;
|
|
1041
|
-
await sleep(opts.intervalMs, opts.signal);
|
|
1042
|
-
}
|
|
1114
|
+
assertNotStalled(result, signal);
|
|
1115
|
+
}, opts.signal);
|
|
1116
|
+
}
|
|
1117
|
+
function assertNotStalled(result, signal, bounds = {}) {
|
|
1118
|
+
if (signal.aborted)
|
|
1119
|
+
return;
|
|
1120
|
+
if (bounds.maxPages !== undefined && (bounds.pages ?? 0) >= bounds.maxPages) {
|
|
1121
|
+
return;
|
|
1122
|
+
}
|
|
1123
|
+
if (bounds.maxEmptyPolls !== undefined && result.emptyPolls >= bounds.maxEmptyPolls) {
|
|
1124
|
+
return;
|
|
1043
1125
|
}
|
|
1126
|
+
throw new StreamsServerError(`Streams returned events at cursor ${result.cursor ?? "(start)"} but the cursor did not advance, so the stream stopped instead of re-reading the same page.`, 0, undefined, "CURSOR_STALLED");
|
|
1044
1127
|
}
|
|
1045
1128
|
async function* streamStreamsEvents(opts) {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
let cursor = opts.fromCursor ?? null;
|
|
1051
|
-
let pages = 0;
|
|
1052
|
-
let emptyPolls = 0;
|
|
1053
|
-
while (pages < maxPages && emptyPolls < maxEmptyPolls && !opts.signal?.aborted) {
|
|
1054
|
-
const envelope = await opts.fetchEvents({
|
|
1055
|
-
cursor,
|
|
1056
|
-
limit: opts.batchSize,
|
|
1129
|
+
yield* pullFromLoop(async (deliver, signal) => {
|
|
1130
|
+
const result = await consumeStreamsEvents({
|
|
1131
|
+
fromCursor: opts.fromCursor,
|
|
1132
|
+
batchSize: opts.batchSize,
|
|
1057
1133
|
chain: opts.chain,
|
|
1058
1134
|
types: opts.types,
|
|
1059
1135
|
notTypes: opts.notTypes,
|
|
@@ -1063,29 +1139,27 @@ async function* streamStreamsEvents(opts) {
|
|
|
1063
1139
|
assetIdentifier: opts.assetIdentifier,
|
|
1064
1140
|
rune: opts.rune,
|
|
1065
1141
|
address: opts.address,
|
|
1066
|
-
filters: opts.filters
|
|
1142
|
+
filters: opts.filters,
|
|
1143
|
+
fetchEvents: opts.fetchEvents,
|
|
1144
|
+
sleep: opts.sleep,
|
|
1145
|
+
emptyBackoffMs: opts.emptyBackoffMs,
|
|
1146
|
+
maxPages: opts.maxPages,
|
|
1147
|
+
maxEmptyPolls: opts.maxEmptyPolls,
|
|
1148
|
+
signal,
|
|
1149
|
+
onBatch: async (events) => {
|
|
1150
|
+
for (const event of events) {
|
|
1151
|
+
if (signal.aborted)
|
|
1152
|
+
return;
|
|
1153
|
+
await deliver(event);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1067
1156
|
});
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
const nextCursor = envelope.next_cursor;
|
|
1075
|
-
if (nextCursor && nextCursor !== cursor) {
|
|
1076
|
-
cursor = nextCursor;
|
|
1077
|
-
emptyPolls = 0;
|
|
1078
|
-
continue;
|
|
1079
|
-
}
|
|
1080
|
-
if (envelope.events.length === 0) {
|
|
1081
|
-
emptyPolls++;
|
|
1082
|
-
if (emptyPolls >= maxEmptyPolls || pages >= maxPages)
|
|
1083
|
-
return;
|
|
1084
|
-
await sleep(emptyBackoffMs, opts.signal);
|
|
1085
|
-
continue;
|
|
1086
|
-
}
|
|
1087
|
-
return;
|
|
1088
|
-
}
|
|
1157
|
+
assertNotStalled(result, signal, {
|
|
1158
|
+
maxPages: opts.maxPages,
|
|
1159
|
+
maxEmptyPolls: opts.maxEmptyPolls,
|
|
1160
|
+
pages: result.pages
|
|
1161
|
+
});
|
|
1162
|
+
}, opts.signal);
|
|
1089
1163
|
}
|
|
1090
1164
|
|
|
1091
1165
|
// src/index-api/consumer.ts
|
|
@@ -1878,8 +1952,14 @@ function subscribeStreamsEvents(opts) {
|
|
|
1878
1952
|
const baseDelayMs = opts.reconnectDelayMs ?? params.reconnectDelayMs ?? 1000;
|
|
1879
1953
|
const staleAfterMs = opts.staleAfterMs ?? params.staleAfterMs ?? SUBSCRIBE_DEFAULT_STALE_AFTER_MS;
|
|
1880
1954
|
let attempt = 0;
|
|
1955
|
+
const emit = (state) => {
|
|
1956
|
+
try {
|
|
1957
|
+
params.onState?.(state);
|
|
1958
|
+
} catch {}
|
|
1959
|
+
};
|
|
1881
1960
|
const run = async () => {
|
|
1882
1961
|
while (!controller.signal.aborted) {
|
|
1962
|
+
emit("connecting");
|
|
1883
1963
|
try {
|
|
1884
1964
|
const url = `${opts.baseUrl}/v1/streams/events/stream${buildQuery({
|
|
1885
1965
|
chain: params.chain === "bitcoin" ? "bitcoin" : undefined,
|
|
@@ -1901,6 +1981,7 @@ function subscribeStreamsEvents(opts) {
|
|
|
1901
1981
|
fetchImpl: opts.fetchImpl,
|
|
1902
1982
|
staleAfterMs,
|
|
1903
1983
|
mapError: mapStreamsError,
|
|
1984
|
+
onOpen: () => emit("open"),
|
|
1904
1985
|
onFrame: async (frame) => {
|
|
1905
1986
|
attempt = 0;
|
|
1906
1987
|
if (frame.event === "ping" || !frame.data)
|
|
@@ -1929,6 +2010,8 @@ function subscribeStreamsEvents(opts) {
|
|
|
1929
2010
|
cursor = parsed.event.cursor ?? cursor;
|
|
1930
2011
|
}
|
|
1931
2012
|
});
|
|
2013
|
+
if (!controller.signal.aborted)
|
|
2014
|
+
emit("reconnecting");
|
|
1932
2015
|
await sleep(reconnectDelay(attempt, baseDelayMs, undefined, opts.random), controller.signal);
|
|
1933
2016
|
attempt += 1;
|
|
1934
2017
|
} catch (err) {
|
|
@@ -1937,13 +2020,14 @@ function subscribeStreamsEvents(opts) {
|
|
|
1937
2020
|
params.onError?.(err);
|
|
1938
2021
|
if (isTerminal(err))
|
|
1939
2022
|
throw err;
|
|
2023
|
+
emit("reconnecting");
|
|
1940
2024
|
const retryAfterSeconds = err.retryAfterSeconds;
|
|
1941
2025
|
await sleep(reconnectDelay(attempt, baseDelayMs, retryAfterSeconds, opts.random), controller.signal);
|
|
1942
2026
|
attempt += 1;
|
|
1943
2027
|
}
|
|
1944
2028
|
}
|
|
1945
2029
|
};
|
|
1946
|
-
const done = run();
|
|
2030
|
+
const done = run().finally(() => emit("closed"));
|
|
1947
2031
|
done.catch(() => {});
|
|
1948
2032
|
const unsubscribe = () => controller.abort();
|
|
1949
2033
|
return Object.assign(unsubscribe, { done });
|
|
@@ -1961,6 +2045,7 @@ async function readSse(opts) {
|
|
|
1961
2045
|
if (!res.body) {
|
|
1962
2046
|
throw new StreamsServerError("Streams SSE response has no body.", 0);
|
|
1963
2047
|
}
|
|
2048
|
+
opts.onOpen?.();
|
|
1964
2049
|
for await (const frame of parseSseFrames(res.body, opts.signal, opts.staleAfterMs)) {
|
|
1965
2050
|
await opts.onFrame(frame);
|
|
1966
2051
|
}
|
|
@@ -2036,6 +2121,33 @@ function parseFrame(raw) {
|
|
|
2036
2121
|
`) : undefined };
|
|
2037
2122
|
}
|
|
2038
2123
|
|
|
2124
|
+
// src/streams/timeout-fetch.ts
|
|
2125
|
+
var STREAMS_CONNECT_TIMEOUT_MS = 30000;
|
|
2126
|
+
function withConnectTimeout(fetchImpl, timeoutMs) {
|
|
2127
|
+
if (!(timeoutMs > 0) || !Number.isFinite(timeoutMs))
|
|
2128
|
+
return fetchImpl;
|
|
2129
|
+
return async (input, init) => {
|
|
2130
|
+
const callerSignal = init?.signal ?? undefined;
|
|
2131
|
+
const timeout = new AbortController;
|
|
2132
|
+
let timedOut = false;
|
|
2133
|
+
const timer = setTimeout(() => {
|
|
2134
|
+
timedOut = true;
|
|
2135
|
+
timeout.abort();
|
|
2136
|
+
}, timeoutMs);
|
|
2137
|
+
const signal = callerSignal ? AbortSignal.any([callerSignal, timeout.signal]) : timeout.signal;
|
|
2138
|
+
try {
|
|
2139
|
+
return await fetchImpl(input, { ...init, signal });
|
|
2140
|
+
} catch (err) {
|
|
2141
|
+
if (timedOut && !callerSignal?.aborted) {
|
|
2142
|
+
throw new StreamsServerError(`No response headers within ${timeoutMs}ms. Retryable.`, 0, undefined, "REQUEST_TIMEOUT");
|
|
2143
|
+
}
|
|
2144
|
+
throw err;
|
|
2145
|
+
} finally {
|
|
2146
|
+
clearTimeout(timer);
|
|
2147
|
+
}
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2039
2151
|
// src/streams/client.ts
|
|
2040
2152
|
function cursorTuple(cursor) {
|
|
2041
2153
|
if (!cursor)
|
|
@@ -2081,7 +2193,7 @@ function createStreamsClient(options) {
|
|
|
2081
2193
|
"x-sl-origin": origin,
|
|
2082
2194
|
...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
|
|
2083
2195
|
});
|
|
2084
|
-
const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
|
|
2196
|
+
const fetchImpl = withConnectTimeout(options.fetchImpl ?? ((input, init) => fetch(input, init)), options.connectTimeoutMs ?? STREAMS_CONNECT_TIMEOUT_MS);
|
|
2085
2197
|
const verify = options.verify;
|
|
2086
2198
|
const verifyMode = verify === false ? "off" : verify === undefined ? "lenient" : "strict";
|
|
2087
2199
|
if (verify === true && baseUrl.startsWith("http:") && !isLoopbackUrl(baseUrl)) {
|
|
@@ -2856,6 +2968,7 @@ import {
|
|
|
2856
2968
|
SLOW_TIMEOUT_RATIO,
|
|
2857
2969
|
SLOW_WINDOW
|
|
2858
2970
|
} from "@secondlayer/shared/insights/thresholds";
|
|
2971
|
+
import { pauseReasonOf } from "@secondlayer/shared/webhooks/health";
|
|
2859
2972
|
function isSuccessDelivery(row) {
|
|
2860
2973
|
return row.statusCode !== null && row.statusCode >= 200 && row.statusCode < 300;
|
|
2861
2974
|
}
|
|
@@ -3142,16 +3255,17 @@ function buildDoctorReport(input) {
|
|
|
3142
3255
|
};
|
|
3143
3256
|
}
|
|
3144
3257
|
function buildListIssue(webhook) {
|
|
3145
|
-
|
|
3258
|
+
const reason = pauseReasonOf(webhook);
|
|
3259
|
+
if (reason === null)
|
|
3146
3260
|
return null;
|
|
3147
|
-
if (
|
|
3261
|
+
if (reason === "circuit") {
|
|
3148
3262
|
return {
|
|
3149
3263
|
code: "circuit",
|
|
3150
3264
|
severity: "bad",
|
|
3151
3265
|
evidence: [
|
|
3152
3266
|
{
|
|
3153
3267
|
label: "circuit opened",
|
|
3154
|
-
value: formatShortDate(webhook.circuitOpenedAt)
|
|
3268
|
+
value: webhook.circuitOpenedAt ? formatShortDate(webhook.circuitOpenedAt) : "unknown"
|
|
3155
3269
|
},
|
|
3156
3270
|
{
|
|
3157
3271
|
label: "last success",
|
|
@@ -3410,8 +3524,10 @@ export {
|
|
|
3410
3524
|
isSuccessDelivery,
|
|
3411
3525
|
parseRetryAfter,
|
|
3412
3526
|
resolveAccountKey,
|
|
3527
|
+
resolveAccountUrl,
|
|
3413
3528
|
resolveApiKey,
|
|
3414
3529
|
resolveBaseUrl,
|
|
3530
|
+
resolveIdentity,
|
|
3415
3531
|
shutdownSignal,
|
|
3416
3532
|
toJsonSafe,
|
|
3417
3533
|
trigger,
|
|
@@ -3421,5 +3537,5 @@ export {
|
|
|
3421
3537
|
verifyWebhookSignature
|
|
3422
3538
|
};
|
|
3423
3539
|
|
|
3424
|
-
//# debugId=
|
|
3540
|
+
//# debugId=7941E39982D460D764756E2164756E21
|
|
3425
3541
|
//# sourceMappingURL=index.js.map
|