@secondlayer/sdk 7.0.0 → 8.0.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/README.md +1 -5
- package/dist/index.d.ts +1 -158
- package/dist/index.js +1 -230
- package/dist/index.js.map +3 -4
- package/package.json +4 -8
- package/dist/x402.d.ts +0 -160
- package/dist/x402.js +0 -506
- package/dist/x402.js.map +0 -12
package/README.md
CHANGED
|
@@ -370,12 +370,8 @@ const spec = await sl.subgraphs.openapi("my-subgraph");
|
|
|
370
370
|
const source = await sl.subgraphs.getSource("my-subgraph");
|
|
371
371
|
const gaps = await sl.subgraphs.gaps("my-subgraph");
|
|
372
372
|
|
|
373
|
-
// Deploy —
|
|
373
|
+
// Deploy — deploys default visibility "public" (409 PUBLIC_NAME_TAKEN if the name is claimed)
|
|
374
374
|
const result = await sl.subgraphs.deploy({ name, sources, schema, handlerCode, visibility: "public" });
|
|
375
|
-
|
|
376
|
-
// Flip visibility — publish claims the global public name (409 PUBLIC_NAME_TAKEN if claimed)
|
|
377
|
-
await sl.subgraphs.publish("my-subgraph");
|
|
378
|
-
await sl.subgraphs.unpublish("my-subgraph");
|
|
379
375
|
```
|
|
380
376
|
|
|
381
377
|
Stream rows live with the typed client — each table exposes `subscribe`
|
package/dist/index.d.ts
CHANGED
|
@@ -2606,163 +2606,6 @@ declare const Cursor: {
|
|
|
2606
2606
|
eventIndex: number;
|
|
2607
2607
|
};
|
|
2608
2608
|
};
|
|
2609
|
-
import { X402TokenSymbol } from "@secondlayer/shared/x402";
|
|
2610
|
-
import { LocalAccount } from "@secondlayer/stacks/accounts";
|
|
2611
|
-
import { StacksChain } from "@secondlayer/stacks/chains";
|
|
2612
|
-
/**
|
|
2613
|
-
* Client for the x402 pay-per-request rail. Turns a 402 challenge into a signed
|
|
2614
|
-
* `PAYMENT-SIGNATURE` and retries — gasless (the agent signs origin-only; the
|
|
2615
|
-
* facilitator sponsors the STX fee) and accountless (no key/Stripe/session).
|
|
2616
|
-
*
|
|
2617
|
-
* Three layers:
|
|
2618
|
-
* - `withX402(fetch, opts)` — drop-in fetch that auto-pays on 402.
|
|
2619
|
-
* - `createX402Client(opts)` — `.get/.post` returning `{ data, payment }`.
|
|
2620
|
-
* - `buildSignedX402Payment` / `readX402Challenge` — primitives for custom transports.
|
|
2621
|
-
*/
|
|
2622
|
-
type X402Accept = {
|
|
2623
|
-
scheme: "exact";
|
|
2624
|
-
network: string;
|
|
2625
|
-
asset: string;
|
|
2626
|
-
/** Atomic units. */
|
|
2627
|
-
amount: string;
|
|
2628
|
-
payTo: string;
|
|
2629
|
-
maxTimeoutSeconds: number;
|
|
2630
|
-
extra: {
|
|
2631
|
-
nonce: string;
|
|
2632
|
-
};
|
|
2633
|
-
};
|
|
2634
|
-
type X402Challenge = {
|
|
2635
|
-
x402Version: number;
|
|
2636
|
-
accepts: X402Accept[];
|
|
2637
|
-
error?: string;
|
|
2638
|
-
};
|
|
2639
|
-
/** Decoded `PAYMENT-RESPONSE` settlement receipt. */
|
|
2640
|
-
type X402Receipt = {
|
|
2641
|
-
success: boolean;
|
|
2642
|
-
/** Settlement tier: `optimistic` (served on broadcast-accept, reconciled
|
|
2643
|
-
* async) or `confirmed` (canonical). Absent on older deployments. */
|
|
2644
|
-
state?: "optimistic" | "confirmed";
|
|
2645
|
-
txid: string;
|
|
2646
|
-
payer: string;
|
|
2647
|
-
network: string;
|
|
2648
|
-
};
|
|
2649
|
-
/** Bitcoin-native first — sBTC is the compelling micropay asset; USDCx the
|
|
2650
|
-
* dollar peg; STX the fallback. Override via `preferAssets`. */
|
|
2651
|
-
declare const DEFAULT_PREFER_ASSETS: X402TokenSymbol[];
|
|
2652
|
-
/** Thrown when no offered asset is within the caller's spend guard / preferences. */
|
|
2653
|
-
declare class X402SpendGuardError extends Error {
|
|
2654
|
-
constructor(message: string);
|
|
2655
|
-
}
|
|
2656
|
-
/** Read the x402 challenge from a 402 response — prefer the wire header, fall
|
|
2657
|
-
* back to the JSON body. */
|
|
2658
|
-
declare function readX402Challenge(res: Response): Promise<X402Challenge | null>;
|
|
2659
|
-
/** Read the settlement receipt from a paid 200 response. */
|
|
2660
|
-
declare function readX402Receipt(res: Response): X402Receipt | null;
|
|
2661
|
-
type SelectOfferOptions = {
|
|
2662
|
-
preferAssets?: X402TokenSymbol[];
|
|
2663
|
-
maxAmountPerCall?: Partial<Record<X402TokenSymbol, bigint>>;
|
|
2664
|
-
};
|
|
2665
|
-
/** Choose an `accepts[]` entry by preference order, skipping any that exceed the
|
|
2666
|
-
* per-asset spend cap. Throws {@link X402SpendGuardError} if none qualify. */
|
|
2667
|
-
declare function selectOffer(challenge: X402Challenge, opts?: SelectOfferOptions): {
|
|
2668
|
-
accept: X402Accept;
|
|
2669
|
-
symbol: X402TokenSymbol;
|
|
2670
|
-
};
|
|
2671
|
-
/** Fetch the payer account's next nonce from a Stacks node (`/v2/accounts`). */
|
|
2672
|
-
declare function resolveAccountNonce(address: string, nodeUrl?: string): Promise<number>;
|
|
2673
|
-
type BuildSignedX402PaymentOptions = {
|
|
2674
|
-
challenge: X402Challenge;
|
|
2675
|
-
account: LocalAccount;
|
|
2676
|
-
/** The payer account's next nonce. */
|
|
2677
|
-
accountNonce: bigint | number | string;
|
|
2678
|
-
/** Preferred asset string (e.g. an sBTC/USDCx id). Defaults to the first offer. */
|
|
2679
|
-
asset?: string;
|
|
2680
|
-
chain?: StacksChain;
|
|
2681
|
-
};
|
|
2682
|
-
/** Build a signed, base64 `PAYMENT-SIGNATURE` header for one `accepts[]` entry. */
|
|
2683
|
-
declare function buildSignedX402Payment(opts: BuildSignedX402PaymentOptions): Promise<{
|
|
2684
|
-
header: string;
|
|
2685
|
-
accept: X402Accept;
|
|
2686
|
-
}>;
|
|
2687
|
-
type WithX402Options = SelectOfferOptions & {
|
|
2688
|
-
account: LocalAccount;
|
|
2689
|
-
/** Prepaid-credit token (PAYMENT-BALANCE) from a prior deposit — calls
|
|
2690
|
-
* debit the tab server-side instead of settling on-chain per call. */
|
|
2691
|
-
balanceToken?: string;
|
|
2692
|
-
/** Autonomous treasury policy: when the tab's remaining balance (read from
|
|
2693
|
-
* X-BALANCE-REMAINING-USD) drops below `whenBelow`, deposit `usd` more in
|
|
2694
|
-
* the background (one on-chain payment) and adopt the fresh token. */
|
|
2695
|
-
topUp?: {
|
|
2696
|
-
usd: number;
|
|
2697
|
-
whenBelow: number;
|
|
2698
|
-
};
|
|
2699
|
-
/** Override the payer nonce; auto-resolved from `nodeUrl` when omitted. */
|
|
2700
|
-
accountNonce?: bigint | number | string;
|
|
2701
|
-
/** Node for auto-nonce lookup. Defaults to {@link DEFAULT_NONCE_NODE_URL}. */
|
|
2702
|
-
nodeUrl?: string;
|
|
2703
|
-
chain?: StacksChain;
|
|
2704
|
-
/** Fired just before the paid retry (the call then blocks on confirmed-tier
|
|
2705
|
-
* settle, or returns near-instantly on an optimistic surface). */
|
|
2706
|
-
onSettling?: (info: {
|
|
2707
|
-
asset: string;
|
|
2708
|
-
amount: string;
|
|
2709
|
-
}) => void;
|
|
2710
|
-
/** Abort the paid retry after this long. */
|
|
2711
|
-
timeoutMs?: number;
|
|
2712
|
-
};
|
|
2713
|
-
type X402Fetch = (input: string | URL, init?: RequestInit) => Promise<Response>;
|
|
2714
|
-
/**
|
|
2715
|
-
* Wrap a `fetch` so requests transparently pay on 402: select an offer (by
|
|
2716
|
-
* `preferAssets` + `maxAmountPerCall`), resolve the nonce, sign origin-only, and
|
|
2717
|
-
* retry once with `PAYMENT-SIGNATURE`. Returns the final `Response` (read the
|
|
2718
|
-
* receipt with {@link readX402Receipt}).
|
|
2719
|
-
*
|
|
2720
|
-
* @example
|
|
2721
|
-
* const x402fetch = withX402(fetch, { account });
|
|
2722
|
-
* const res = await x402fetch("http://127.0.0.1:3800/v1/index/events?event_type=ft_transfer");
|
|
2723
|
-
*/
|
|
2724
|
-
declare function withX402(baseFetch: typeof fetch, opts: WithX402Options): X402Fetch;
|
|
2725
|
-
type X402ClientOptions = WithX402Options & {
|
|
2726
|
-
/** Instance API. Defaults to {@link resolveBaseUrl}. */
|
|
2727
|
-
baseUrl?: string;
|
|
2728
|
-
/** Override the underlying fetch (tests). */
|
|
2729
|
-
fetch?: typeof fetch;
|
|
2730
|
-
};
|
|
2731
|
-
type X402Result<T = unknown> = {
|
|
2732
|
-
data: T;
|
|
2733
|
-
/** Settlement receipt, or null if the response carried none. */
|
|
2734
|
-
payment: X402Receipt | null;
|
|
2735
|
-
response: Response;
|
|
2736
|
-
};
|
|
2737
|
-
type X402Client = {
|
|
2738
|
-
get<T = unknown>(path: string, o?: {
|
|
2739
|
-
query?: Record<string, string>;
|
|
2740
|
-
}): Promise<X402Result<T>>;
|
|
2741
|
-
post<T = unknown>(path: string, o?: {
|
|
2742
|
-
body?: unknown;
|
|
2743
|
-
}): Promise<X402Result<T>>;
|
|
2744
|
-
};
|
|
2745
|
-
/**
|
|
2746
|
-
* A small client over {@link withX402}: `.get/.post` against `baseUrl`, returning
|
|
2747
|
-
* parsed JSON plus the settlement receipt.
|
|
2748
|
-
*
|
|
2749
|
-
* @example
|
|
2750
|
-
* const sl = createX402Client({ account, baseUrl: "http://127.0.0.1:3800" });
|
|
2751
|
-
* const { data, payment } = await sl.get("/v1/index/events", { query: { event_type: "ft_transfer" } });
|
|
2752
|
-
*/
|
|
2753
|
-
declare function createX402Client(opts: X402ClientOptions): X402Client;
|
|
2754
|
-
/** Caller-supplied fetch that re-runs the request with the given extra headers. */
|
|
2755
|
-
type X402FetchFn = (extraHeaders: Record<string, string>) => Promise<Response>;
|
|
2756
|
-
type PayAndRetryOptions = Omit<WithX402Options, never> & {
|
|
2757
|
-
/** Required here (use `withX402` for auto-nonce). */
|
|
2758
|
-
accountNonce: bigint | number | string;
|
|
2759
|
-
};
|
|
2760
|
-
/**
|
|
2761
|
-
* Low-level: run a request via a caller-controlled fetch; if it 402s, pay and
|
|
2762
|
-
* retry once. Prefer {@link withX402} for the common case (it auto-resolves the
|
|
2763
|
-
* nonce + selects the asset). Kept for custom transports.
|
|
2764
|
-
*/
|
|
2765
|
-
declare function payAndRetry(doFetch: X402FetchFn, opts: PayAndRetryOptions): Promise<Response>;
|
|
2766
2609
|
import { SubgraphAgentSchema as SubgraphAgentSchema3, SubgraphSpecFormat as SubgraphSpecFormat2, SubgraphSpecOptions as SubgraphSpecOptions3 } from "@secondlayer/shared/subgraphs/spec";
|
|
2767
2610
|
/**
|
|
2768
2611
|
* The two pieces every "deploy a consumer" guide leaves out, packaged:
|
|
@@ -2963,4 +2806,4 @@ declare function verifySecondlayerSignature(rawBody: string, headers: WebhookHea
|
|
|
2963
2806
|
declare function decodeChainWebhook(rawBody: string): ChainWebhookDelivery;
|
|
2964
2807
|
import { RewardSet as RewardSet2 } from "@secondlayer/shared/node/consensus";
|
|
2965
2808
|
import { decodeClarityValue, toJsonSafe } from "@secondlayer/shared/streams-rows";
|
|
2966
|
-
export {
|
|
2809
|
+
export { verifyWebhookSignature, verifyTransactionProof, verify as verifyStandardWebhooksHeaders, verifySecondlayerSignature, trigger, toJsonSafe, shutdownSignal, resolveBaseUrl, resolveApiKey, 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, decode, createStreamsClient, consumerHealth, consumeIndexFeed, WithSinkTx, WebhookHeaderInput, VersionConflictError, ValidationError, UpdateSubscriptionRequest2 as UpdateSubscriptionRequest, TransactionsWalkParams, TransactionsListParams, TransactionsEnvelope, TransactionProofVerifyResult, TransactionProof, TransactionEnvelope, Subscriptions, SubscriptionSummary2 as SubscriptionSummary, SubscriptionStatus, SubscriptionRuntime, SubscriptionKind, SubscriptionFormat, SubscriptionDetail2 as SubscriptionDetail, Subgraphs, SubgraphSpecOptions3 as SubgraphSpecOptions, SubgraphSpecFormat2 as SubgraphSpecFormat, SubgraphOperationStatus, SubgraphAgentSchema3 as SubgraphAgentSchema, 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, SinkTx, SecondLayerOptions, SecondLayerErrorOptions, SecondLayerError, SecondLayer, 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, PrintSchemaResponse, PoxResource, PoxCyclesWalkParams, PoxCyclesListParams, PoxCyclesEnvelope, PoxCycleEnvelope, Pox5Resource, Pox5EventsWalkParams, Pox5EventsListParams, Pox5EventsEnvelope, NftTransfersWalkParams, NftTransfersResource, NftTransfersListParams, NftTransfersEnvelope, NftTransferPayload2 as NftTransferPayload, NftTransferEvent, NftTransfer, MempoolWalkParams, MempoolTransactionEnvelope, MempoolListParams, MempoolEnvelope, LOCAL_API_URL, 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, IndexEventFields, IndexEvent, IndexDiscovery, IndexContractCall, IndexConsumeOptions, IndexCanonicalBlock, IndexBlock, IndexAlwaysFields, Index, FtTransfersWalkParams, FtTransfersResource, FtTransfersListParams, FtTransfersEnvelope, FtTransferPayload2 as 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, Cursor, CreateSubscriptionResponse2 as CreateSubscriptionResponse, CreateSubscriptionRequest2 as CreateSubscriptionRequest, ContractsListParams, ContractsEnvelope, Contracts, ContractSummary, ContractConformance, ContractCallsWalkParams, ContractCallsListParams, ContractCallsEnvelope, ContractCallsConsumeParams, ContextSnapshot, ContextAccount, ConsumerSink, ConsumerHealth, 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, BlocksWalkParams, BlocksListParams, BlocksEnvelope, BlockEnvelope, AuthError, ApiError, ActiveSubgraphOperation };
|
package/dist/index.js
CHANGED
|
@@ -2008,225 +2008,6 @@ import {
|
|
|
2008
2008
|
import {
|
|
2009
2009
|
STREAMS_EVENT_TYPES
|
|
2010
2010
|
} from "@secondlayer/shared/streams-rows";
|
|
2011
|
-
// src/x402.ts
|
|
2012
|
-
import {
|
|
2013
|
-
X402_TOKENS,
|
|
2014
|
-
findX402TokenByAsset
|
|
2015
|
-
} from "@secondlayer/shared/x402";
|
|
2016
|
-
import { http, createPublicClient } from "@secondlayer/stacks";
|
|
2017
|
-
import { getNonce } from "@secondlayer/stacks/actions";
|
|
2018
|
-
import {
|
|
2019
|
-
serializeTransactionHex,
|
|
2020
|
-
signTransactionWithAccount
|
|
2021
|
-
} from "@secondlayer/stacks/transactions";
|
|
2022
|
-
import { buildExactTransfer } from "@secondlayer/stacks/x402";
|
|
2023
|
-
var DEFAULT_PREFER_ASSETS = [
|
|
2024
|
-
"sBTC",
|
|
2025
|
-
"USDCx",
|
|
2026
|
-
"STX"
|
|
2027
|
-
];
|
|
2028
|
-
var DEFAULT_NONCE_NODE_URL = "https://api.hiro.so";
|
|
2029
|
-
|
|
2030
|
-
class X402SpendGuardError extends Error {
|
|
2031
|
-
constructor(message) {
|
|
2032
|
-
super(message);
|
|
2033
|
-
this.name = "X402SpendGuardError";
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
function b64encode(value) {
|
|
2037
|
-
const utf8 = new TextEncoder().encode(JSON.stringify(value));
|
|
2038
|
-
let binary = "";
|
|
2039
|
-
for (const byte of utf8)
|
|
2040
|
-
binary += String.fromCharCode(byte);
|
|
2041
|
-
return btoa(binary);
|
|
2042
|
-
}
|
|
2043
|
-
function b64decodeJson(value) {
|
|
2044
|
-
try {
|
|
2045
|
-
const binary = atob(value);
|
|
2046
|
-
const utf8 = Uint8Array.from(binary, (ch) => ch.charCodeAt(0));
|
|
2047
|
-
return JSON.parse(new TextDecoder().decode(utf8));
|
|
2048
|
-
} catch {
|
|
2049
|
-
return null;
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
async function readX402Challenge(res) {
|
|
2053
|
-
const header = res.headers.get("PAYMENT-REQUIRED");
|
|
2054
|
-
if (header) {
|
|
2055
|
-
const decoded = b64decodeJson(header);
|
|
2056
|
-
if (decoded)
|
|
2057
|
-
return decoded;
|
|
2058
|
-
}
|
|
2059
|
-
try {
|
|
2060
|
-
return await res.clone().json();
|
|
2061
|
-
} catch {
|
|
2062
|
-
return null;
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
function readX402Receipt(res) {
|
|
2066
|
-
const header = res.headers.get("PAYMENT-RESPONSE");
|
|
2067
|
-
return header ? b64decodeJson(header) : null;
|
|
2068
|
-
}
|
|
2069
|
-
function selectOffer(challenge, opts = {}) {
|
|
2070
|
-
const prefer = opts.preferAssets ?? DEFAULT_PREFER_ASSETS;
|
|
2071
|
-
for (const symbol of prefer) {
|
|
2072
|
-
const token = X402_TOKENS[symbol];
|
|
2073
|
-
const accept = challenge.accepts.find((a) => a.asset === token.asset);
|
|
2074
|
-
if (!accept)
|
|
2075
|
-
continue;
|
|
2076
|
-
const cap = opts.maxAmountPerCall?.[symbol];
|
|
2077
|
-
if (cap !== undefined && BigInt(accept.amount) > cap)
|
|
2078
|
-
continue;
|
|
2079
|
-
return { accept, symbol };
|
|
2080
|
-
}
|
|
2081
|
-
throw new X402SpendGuardError("no x402 offer matched preferAssets within maxAmountPerCall");
|
|
2082
|
-
}
|
|
2083
|
-
async function resolveAccountNonce(address, nodeUrl = DEFAULT_NONCE_NODE_URL) {
|
|
2084
|
-
const client = createPublicClient({ transport: http(nodeUrl) });
|
|
2085
|
-
return Number(await getNonce(client, { address }));
|
|
2086
|
-
}
|
|
2087
|
-
async function buildSignedX402Payment(opts) {
|
|
2088
|
-
const accept = opts.asset ? opts.challenge.accepts.find((a) => a.asset === opts.asset) : opts.challenge.accepts[0];
|
|
2089
|
-
if (!accept) {
|
|
2090
|
-
throw new Error(`No x402 offer${opts.asset ? ` for asset ${opts.asset}` : ""}`);
|
|
2091
|
-
}
|
|
2092
|
-
const token = findX402TokenByAsset(accept.asset);
|
|
2093
|
-
if (!token)
|
|
2094
|
-
throw new Error(`Unknown x402 asset: ${accept.asset}`);
|
|
2095
|
-
const asset = token.contractId && token.assetName ? {
|
|
2096
|
-
kind: "sip010",
|
|
2097
|
-
contractId: token.contractId,
|
|
2098
|
-
assetName: token.assetName
|
|
2099
|
-
} : { kind: "stx" };
|
|
2100
|
-
const tx = buildExactTransfer({
|
|
2101
|
-
asset,
|
|
2102
|
-
amount: BigInt(accept.amount),
|
|
2103
|
-
payTo: accept.payTo,
|
|
2104
|
-
payer: opts.account.address,
|
|
2105
|
-
payerPublicKey: opts.account.publicKey,
|
|
2106
|
-
accountNonce: opts.accountNonce,
|
|
2107
|
-
nonce: accept.extra.nonce,
|
|
2108
|
-
chain: opts.chain
|
|
2109
|
-
});
|
|
2110
|
-
const signed = await signTransactionWithAccount(tx, opts.account);
|
|
2111
|
-
const header = b64encode({
|
|
2112
|
-
x402Version: opts.challenge.x402Version ?? 2,
|
|
2113
|
-
scheme: "exact",
|
|
2114
|
-
network: accept.network,
|
|
2115
|
-
asset: accept.asset,
|
|
2116
|
-
payload: { transaction: serializeTransactionHex(signed) },
|
|
2117
|
-
extra: { nonce: accept.extra.nonce }
|
|
2118
|
-
});
|
|
2119
|
-
return { header, accept };
|
|
2120
|
-
}
|
|
2121
|
-
function withX402(baseFetch, opts) {
|
|
2122
|
-
const sessions = new Map;
|
|
2123
|
-
let balanceToken = opts.balanceToken ?? null;
|
|
2124
|
-
let toppingUp = false;
|
|
2125
|
-
const originOf = (input) => {
|
|
2126
|
-
try {
|
|
2127
|
-
return new URL(String(input)).origin;
|
|
2128
|
-
} catch {
|
|
2129
|
-
return "";
|
|
2130
|
-
}
|
|
2131
|
-
};
|
|
2132
|
-
const wrapped = async (input, init) => {
|
|
2133
|
-
const origin = originOf(input);
|
|
2134
|
-
const run = (extra, signal2) => baseFetch(input, {
|
|
2135
|
-
...init,
|
|
2136
|
-
headers: { ...init?.headers, ...extra },
|
|
2137
|
-
...signal2 ? { signal: signal2 } : {}
|
|
2138
|
-
});
|
|
2139
|
-
const maybeTopUp = (res) => {
|
|
2140
|
-
const policy = opts.topUp;
|
|
2141
|
-
if (!policy || toppingUp || !origin)
|
|
2142
|
-
return;
|
|
2143
|
-
const remaining = res.headers.get("X-BALANCE-REMAINING-USD");
|
|
2144
|
-
if (remaining === null || Number(remaining) >= policy.whenBelow)
|
|
2145
|
-
return;
|
|
2146
|
-
toppingUp = true;
|
|
2147
|
-
(async () => {
|
|
2148
|
-
try {
|
|
2149
|
-
const dep = await wrapped(`${origin}/v1/x402/deposit?usd=${policy.usd}`, { method: "POST" });
|
|
2150
|
-
if (dep.ok) {
|
|
2151
|
-
const body = await dep.json();
|
|
2152
|
-
if (body.balance_token)
|
|
2153
|
-
balanceToken = body.balance_token;
|
|
2154
|
-
}
|
|
2155
|
-
} catch {} finally {
|
|
2156
|
-
toppingUp = false;
|
|
2157
|
-
}
|
|
2158
|
-
})();
|
|
2159
|
-
};
|
|
2160
|
-
const remember = (res) => {
|
|
2161
|
-
const voucher = res.headers.get("PAYMENT-SESSION");
|
|
2162
|
-
if (voucher && origin)
|
|
2163
|
-
sessions.set(origin, voucher);
|
|
2164
|
-
maybeTopUp(res);
|
|
2165
|
-
return res;
|
|
2166
|
-
};
|
|
2167
|
-
const cached = origin ? sessions.get(origin) : undefined;
|
|
2168
|
-
const first = await run({
|
|
2169
|
-
...cached ? { "PAYMENT-SESSION": cached } : {},
|
|
2170
|
-
...balanceToken ? { "PAYMENT-BALANCE": balanceToken } : {}
|
|
2171
|
-
});
|
|
2172
|
-
if (first.status !== 402)
|
|
2173
|
-
return remember(first);
|
|
2174
|
-
if (cached && origin)
|
|
2175
|
-
sessions.delete(origin);
|
|
2176
|
-
const challenge = await readX402Challenge(first);
|
|
2177
|
-
if (!challenge)
|
|
2178
|
-
return first;
|
|
2179
|
-
const { accept } = selectOffer(challenge, opts);
|
|
2180
|
-
const accountNonce = opts.accountNonce ?? await resolveAccountNonce(opts.account.address, opts.nodeUrl);
|
|
2181
|
-
const { header } = await buildSignedX402Payment({
|
|
2182
|
-
challenge,
|
|
2183
|
-
account: opts.account,
|
|
2184
|
-
accountNonce,
|
|
2185
|
-
asset: accept.asset,
|
|
2186
|
-
chain: opts.chain
|
|
2187
|
-
});
|
|
2188
|
-
opts.onSettling?.({ asset: accept.asset, amount: accept.amount });
|
|
2189
|
-
const signal = opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined;
|
|
2190
|
-
return remember(await run({ "PAYMENT-SIGNATURE": header }, signal));
|
|
2191
|
-
};
|
|
2192
|
-
return wrapped;
|
|
2193
|
-
}
|
|
2194
|
-
function createX402Client(opts) {
|
|
2195
|
-
const f = withX402(opts.fetch ?? fetch, opts);
|
|
2196
|
-
const base = resolveBaseUrl(opts.baseUrl);
|
|
2197
|
-
async function request(method, path, o = {}) {
|
|
2198
|
-
const qs = o.query ? `?${new URLSearchParams(o.query).toString()}` : "";
|
|
2199
|
-
const init = { method };
|
|
2200
|
-
if (o.body !== undefined) {
|
|
2201
|
-
init.body = JSON.stringify(o.body);
|
|
2202
|
-
init.headers = { "content-type": "application/json" };
|
|
2203
|
-
}
|
|
2204
|
-
const response = await f(`${base}${path}${qs}`, init);
|
|
2205
|
-
const data = await response.json().catch(() => null);
|
|
2206
|
-
return { data, payment: readX402Receipt(response), response };
|
|
2207
|
-
}
|
|
2208
|
-
return {
|
|
2209
|
-
get: (path, o) => request("GET", path, o),
|
|
2210
|
-
post: (path, o) => request("POST", path, o)
|
|
2211
|
-
};
|
|
2212
|
-
}
|
|
2213
|
-
async function payAndRetry(doFetch, opts) {
|
|
2214
|
-
const first = await doFetch({});
|
|
2215
|
-
if (first.status !== 402)
|
|
2216
|
-
return first;
|
|
2217
|
-
const challenge = await readX402Challenge(first);
|
|
2218
|
-
if (!challenge)
|
|
2219
|
-
return first;
|
|
2220
|
-
const { accept } = selectOffer(challenge, opts);
|
|
2221
|
-
const { header } = await buildSignedX402Payment({
|
|
2222
|
-
challenge,
|
|
2223
|
-
account: opts.account,
|
|
2224
|
-
accountNonce: opts.accountNonce,
|
|
2225
|
-
asset: accept.asset,
|
|
2226
|
-
chain: opts.chain
|
|
2227
|
-
});
|
|
2228
|
-
return doFetch({ "PAYMENT-SIGNATURE": header });
|
|
2229
|
-
}
|
|
2230
2011
|
// src/consumer-ops.ts
|
|
2231
2012
|
function consumerHealth(options = {}) {
|
|
2232
2013
|
const staleAfterMs = options.staleAfterMs ?? 120000;
|
|
@@ -2426,7 +2207,6 @@ import {
|
|
|
2426
2207
|
toJsonSafe
|
|
2427
2208
|
} from "@secondlayer/shared/streams-rows";
|
|
2428
2209
|
export {
|
|
2429
|
-
withX402,
|
|
2430
2210
|
verifyWebhookSignature,
|
|
2431
2211
|
verifyTransactionProof,
|
|
2432
2212
|
verify2 as verifyStandardWebhooksHeaders,
|
|
@@ -2434,13 +2214,8 @@ export {
|
|
|
2434
2214
|
trigger,
|
|
2435
2215
|
toJsonSafe,
|
|
2436
2216
|
shutdownSignal,
|
|
2437
|
-
selectOffer,
|
|
2438
2217
|
resolveBaseUrl,
|
|
2439
2218
|
resolveApiKey,
|
|
2440
|
-
resolveAccountNonce,
|
|
2441
|
-
readX402Receipt,
|
|
2442
|
-
readX402Challenge,
|
|
2443
|
-
payAndRetry,
|
|
2444
2219
|
parseRetryAfter,
|
|
2445
2220
|
isStxTransfer,
|
|
2446
2221
|
isStxMint,
|
|
@@ -2469,12 +2244,9 @@ export {
|
|
|
2469
2244
|
decodeClarityValue,
|
|
2470
2245
|
decodeChainWebhook,
|
|
2471
2246
|
decode,
|
|
2472
|
-
createX402Client,
|
|
2473
2247
|
createStreamsClient,
|
|
2474
2248
|
consumerHealth,
|
|
2475
2249
|
consumeIndexFeed,
|
|
2476
|
-
buildSignedX402Payment,
|
|
2477
|
-
X402SpendGuardError,
|
|
2478
2250
|
VersionConflictError,
|
|
2479
2251
|
ValidationError,
|
|
2480
2252
|
Subscriptions,
|
|
@@ -2486,12 +2258,11 @@ export {
|
|
|
2486
2258
|
RateLimitError,
|
|
2487
2259
|
LOCAL_API_URL,
|
|
2488
2260
|
Index,
|
|
2489
|
-
DEFAULT_PREFER_ASSETS,
|
|
2490
2261
|
Cursor,
|
|
2491
2262
|
Contracts,
|
|
2492
2263
|
AuthError,
|
|
2493
2264
|
ApiError
|
|
2494
2265
|
};
|
|
2495
2266
|
|
|
2496
|
-
//# debugId=
|
|
2267
|
+
//# debugId=E54023F57B45037464756E2164756E21
|
|
2497
2268
|
//# sourceMappingURL=index.js.map
|