@lunora/x402 1.0.0-alpha.6 → 1.0.0-alpha.8

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.
@@ -1,7 +1 @@
1
- export { DEFAULT_FACILITATOR_URL, resolveFacilitatorUrl } from '../packem_shared/DEFAULT_FACILITATOR_URL-Cbz6kIqa.mjs';
2
- export { createFacilitatorClient } from '../packem_shared/createFacilitatorClient-rXHBnCZm.mjs';
3
- export { isEvmNetwork, isSvmNetwork, toCaip2 } from '../packem_shared/EVM_NETWORKS-BhnYWUQ4.mjs';
4
- export { withX402 } from '../packem_shared/withX402-DILL2DvD.mjs';
5
- export { createChargeMiddleware } from '../packem_shared/createChargeMiddleware-D3yhOpFs.mjs';
6
- export { createProcedureChargeGate } from '../packem_shared/createProcedureChargeGate-eh9yv36U.mjs';
7
- export { toPaymentEventRow, toReceipt } from '../packem_shared/toPaymentEventRow-DW4O9N7Y.mjs';
1
+ import{DEFAULT_FACILITATOR_URL as t,resolveFacilitatorUrl as o}from"../packem_shared/DEFAULT_FACILITATOR_URL-lUtljfJI.mjs";import{createFacilitatorClient as i}from"../packem_shared/createFacilitatorClient-Dj4Ll9xQ.mjs";import{isEvmNetwork as p,isSvmNetwork as c,toCaip2 as f}from"../packem_shared/EVM_NETWORKS-XOms9Rtk.mjs";import{withX402 as l}from"../packem_shared/withX402-D10895ct.mjs";import{createChargeMiddleware as C}from"../packem_shared/createChargeMiddleware-MQhSA6Wt.mjs";import{createProcedureChargeGate as F}from"../packem_shared/createProcedureChargeGate-Cfm5mD2y.mjs";import{toPaymentEventRow as d,toReceipt as h}from"../packem_shared/toPaymentEventRow-D_kRVcb3.mjs";export{t as DEFAULT_FACILITATOR_URL,C as createChargeMiddleware,i as createFacilitatorClient,F as createProcedureChargeGate,p as isEvmNetwork,c as isSvmNetwork,o as resolveFacilitatorUrl,f as toCaip2,d as toPaymentEventRow,h as toReceipt,l as withX402};
package/dist/index.mjs CHANGED
@@ -1,2 +1 @@
1
- export { DEFAULT_FACILITATOR_URL, resolveFacilitatorUrl } from './packem_shared/DEFAULT_FACILITATOR_URL-Cbz6kIqa.mjs';
2
- export { EVM_NETWORKS, NETWORK_TO_CAIP2, SVM_NETWORKS, isEvmNetwork, isSvmNetwork, toCaip2 } from './packem_shared/EVM_NETWORKS-BhnYWUQ4.mjs';
1
+ import{DEFAULT_FACILITATOR_URL as t,resolveFacilitatorUrl as T}from"./packem_shared/DEFAULT_FACILITATOR_URL-lUtljfJI.mjs";import{EVM_NETWORKS as E,NETWORK_TO_CAIP2 as _,SVM_NETWORKS as i,isEvmNetwork as N,isSvmNetwork as O,toCaip2 as R}from"./packem_shared/EVM_NETWORKS-XOms9Rtk.mjs";export{t as DEFAULT_FACILITATOR_URL,E as EVM_NETWORKS,_ as NETWORK_TO_CAIP2,i as SVM_NETWORKS,N as isEvmNetwork,O as isSvmNetwork,T as resolveFacilitatorUrl,R as toCaip2};
@@ -0,0 +1 @@
1
+ const r="https://x402.org/facilitator",o=t=>t?.url??r;export{r as DEFAULT_FACILITATOR_URL,o as resolveFacilitatorUrl};
@@ -0,0 +1 @@
1
+ import{LunoraError as l}from"@lunora/errors";import{toCaip2 as w}from"./EVM_NETWORKS-XOms9Rtk.mjs";const y=/^\d+(?:\.\d+)?$/,u=(e,t)=>t.startsWith("eip155:")?e.toLowerCase():e,d=6,R=()=>{let e=0n;return{add:t=>{e+=t},release:t=>{e=e>t?e-t:0n},get spentAtomic(){return e}}},m=(e,t=d)=>{if(!Number.isInteger(t)||t<0)throw new l("BAD_REQUEST",`x402 policy: decimals must be a non-negative integer, got ${String(t)}.`);const n=(typeof e=="number"?e.toString():e).trim(),o=n.startsWith("$")?n.slice(1):n;if(!y.test(o))throw new l("BAD_REQUEST",`x402 policy: "${String(e)}" is not a valid USD amount (use a plain decimal like "0.01").`);const[a="0",r=""]=o.split("."),i=r.slice(0,t).padEnd(t,"0");return BigInt(a)*10n**BigInt(t)+BigInt(i===""?"0":i)},v=e=>{const t=e.decimals??d,n=e.maxPerCall===void 0?void 0:m(e.maxPerCall,t),o=e.allowedNetworks?.map(r=>w(r)),{allowedRecipients:a}=e;return(r,i)=>i.filter(s=>{if(n!==void 0&&BigInt(s.amount)>n||o!==void 0&&!o.includes(s.network))return!1;if(a!==void 0){const c=u(s.payTo,s.network);return a.some(p=>u(p,s.network)===c)}return!0})},x=(e,t)=>{const n=e.decimals??d,o=e.maxPerRun===void 0?void 0:m(e.maxPerRun,n);return async a=>{const r=a.selectedRequirements,i=BigInt(r.amount);if(o!==void 0&&t.spentAtomic+i>o)return{abort:!0,reason:`x402 policy: this payment (${r.amount}) would exceed the per-run cap (already spent ${t.spentAtomic.toString()}, cap ${o.toString()}, in atomic base units).`};if(t.add(i),e.onPaymentRequired!==void 0&&!await e.onPaymentRequired(r))return t.release(i),{abort:!0,reason:"x402 policy: payment was declined by onPaymentRequired."}}},S=e=>t=>(e.release(BigInt(t.selectedRequirements.amount)),Promise.resolve()),f=e=>{if(!(e.maxPerCall!==void 0||e.maxPerRun!==void 0||e.onPaymentRequired!==void 0))throw new l("FORBIDDEN","x402 pay: refusing to build a wallet with an unbounded spend policy. Set at least one of maxPerCall, maxPerRun, or onPaymentRequired (allowedNetworks/allowedRecipients narrow but do not bound spend).")};export{d as DEFAULT_STABLECOIN_DECIMALS,f as assertBoundedPolicy,x as buildPaymentGuard,v as buildSpendPolicy,R as createSpendState,S as releaseSpendOnFailure,m as usdToAtomic};
@@ -0,0 +1 @@
1
+ const i={arbitrum:"eip155:42161","arbitrum-sepolia":"eip155:421614",base:"eip155:8453","base-sepolia":"eip155:84532",ethereum:"eip155:1",polygon:"eip155:137",solana:"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp","solana-devnet":"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"},r=["arbitrum","arbitrum-sepolia","base","base-sepolia","ethereum","polygon"],s=["solana","solana-devnet"],o=a=>{const e=i[a];if(e!==void 0)return e;if(a.includes(":"))return a;throw new Error(`Unknown x402 network "${a}". Use a friendly name (${r.join(", ")}, ${s.join(", ")}) or a raw CAIP-2 id.`)},t=a=>o(a).startsWith("eip155:"),n=a=>o(a).startsWith("solana:");export{r as EVM_NETWORKS,i as NETWORK_TO_CAIP2,s as SVM_NETWORKS,t as isEvmNetwork,n as isSvmNetwork,o as toCaip2};
@@ -0,0 +1 @@
1
+ import{x402HTTPResourceServer as P}from"@x402/core/http";import{toCaip2 as v,isEvmNetwork as x}from"./EVM_NETWORKS-XOms9Rtk.mjs";import{toReceipt as H}from"./toPaymentEventRow-D_kRVcb3.mjs";import{createFacilitatorClient as k}from"./createFacilitatorClient-Dj4Ll9xQ.mjs";const T=async e=>{const{x402ResourceServer:r}=await import("@x402/core/server"),t=new r(k(e.facilitator)),s=v(e.network);if(x(e.network)){const{registerExactEvmScheme:a}=await import("@x402/evm/exact/server");a(t,{networks:[s]})}else{const{registerExactSvmScheme:a}=await import("@x402/svm/exact/server");a(t,{networks:[s]})}return t},S="X-PAYMENT",E=e=>{const r=Object.create(null);for(const[t,s]of e)r[t]=s;return r},g=(e,r,t,s)=>{if(e!==void 0)try{const a=Promise.resolve(e(H(r,{resource:t,ts:Date.now()}))).catch(()=>{});s?.(a)}catch{}},b=e=>{const r=x(e.network),t=r?e.recipient.evm:e.recipient.svm;if(t===void 0||t.length===0)throw new Error(`x402 charge on "${e.network}" needs recipient.${r?"evm":"svm"} set.`);return t},q=e=>({accepts:{network:v(e.network),payTo:b(e),price:e.price,scheme:"exact"}}),A=(e,r)=>({getAcceptHeader:()=>e.headers.get("accept")??"",getHeader:t=>e.headers.get(t)??void 0,getMethod:()=>e.method,getPath:()=>r.pathname,getQueryParam:t=>{const s=r.searchParams.getAll(t);if(s.length!==0)return s.length===1?s[0]:s},getQueryParams:()=>{const t=Object.create(null);for(const s of new Set(r.searchParams.keys())){const a=r.searchParams.getAll(s),[i,...o]=a;i!==void 0&&(t[s]=o.length>0?a:i)}return t},getUrl:()=>e.url,getUserAgent:()=>e.headers.get("user-agent")??""}),m=e=>{const r=new Headers(e.headers),{body:t}=e;return t==null?new Response(void 0,{headers:r,status:e.status}):typeof t=="string"?(e.isHtml&&!r.has("content-type")&&r.set("content-type","text/html; charset=utf-8"),new Response(t,{headers:r,status:e.status})):Response.json(t,{headers:r,status:e.status})},R=(e,r)=>{const t=new Headers(e.headers);for(const[s,a]of Object.entries(r))t.set(s,a);return new Response(e.body,{headers:t,status:e.status,statusText:e.statusText})},O=async(e,r,t)=>{const s=await T(e),a=new P(s,{...q(e),...r});await a.initialize();const i=t?.settleBeforeHandler??!1;return{handle:async(o,h,w)=>{const y=new URL(o.url),l={adapter:A(o,y),method:o.method,path:y.pathname,paymentHeader:o.headers.get(S)??void 0},n=await a.processHTTPRequest(l);if(n.type==="no-payment-required")return h();if(n.type==="payment-error")return m(n.response);const f=r?.resource??o.url;if(i){const c=await a.processSettlement(n.paymentPayload,n.paymentRequirements,n.declaredExtensions,{request:l});if(!c.success)return m(c.response);g(e.onReceipt,c,f,w?.waitUntil);const d=await h();return R(d,c.headers)}let u;try{u=await h()}catch(c){try{await n.cancellationDispatcher.cancel({error:c,reason:"handler_threw"})}catch(d){console.error("x402 charge: failed to cancel payment after the handler threw",d)}throw c}const p=await a.processSettlement(n.paymentPayload,n.paymentRequirements,n.declaredExtensions,{request:l,responseHeaders:E(u.headers)});return p.success?(g(e.onReceipt,p,f,w?.waitUntil),R(u,p.headers)):m(p.response)}}};export{q as buildRoute,O as createChargeMiddleware,A as createRequestAdapter,g as reportReceipt,b as resolvePayTo,m as toResponse,R as withHeaders};
@@ -0,0 +1 @@
1
+ import{HTTPFacilitatorClient as o}from"@x402/core/server";import{resolveFacilitatorUrl as i}from"./DEFAULT_FACILITATOR_URL-lUtljfJI.mjs";const s=r=>{const t=i(r);if(r?.headers===void 0)return new o({url:t});const e={...r.headers};return new o({createAuthHeaders:()=>Promise.resolve({settle:e,supported:e,verify:e}),url:t})};export{s as createFacilitatorClient};
@@ -0,0 +1 @@
1
+ import{x402Client as i}from"@x402/core/client";import{wrapFetchWithPayment as a}from"@x402/fetch";import{assertBoundedPolicy as n,buildSpendPolicy as c,buildPaymentGuard as l,releaseSpendOnFailure as m,createSpendState as p}from"./DEFAULT_STABLECOIN_DECIMALS-dzQLLL1Z.mjs";import{registerWallet as y}from"./registerWallet-Cu4qF5tj.mjs";const u=async(r,t)=>{n(r.policy);const e=new i;await y(e,r,t);const o=p();return e.registerPolicy(c(r.policy)),e.onBeforePaymentCreation(l(r.policy,o)),e.onPaymentCreationFailure(m(o)),a(t.fetch??globalThis.fetch,e)};export{u as createPayFetch};
@@ -0,0 +1 @@
1
+ import{createChargeMiddleware as h}from"./createChargeMiddleware-MQhSA6Wt.mjs";const d=a=>{const r=new Map;return async(n,e,c,o)=>{let t=r.get(e.functionPath);return t===void 0&&(t=h({...a,price:e.price},{resource:e.functionPath},{settleBeforeHandler:!0}).catch(i=>{throw r.delete(e.functionPath),i}),r.set(e.functionPath,t)),(await t).handle(n,c,o)}};export{d as createProcedureChargeGate};
@@ -0,0 +1 @@
1
+ import{LunoraError as i}from"@lunora/errors";import{toCaip2 as l,isEvmNetwork as w}from"./EVM_NETWORKS-XOms9Rtk.mjs";const p=/^0x[0-9a-fA-F]{64}$/,y=async(t,e)=>{const a=await t(e);if(a===void 0||a.length===0)throw new i("ENV_INVALID",`x402 pay: secret "${e}" is not set — the agent wallet has no key to sign with.`);return a},d=(t,e)=>{const a=t.address.startsWith("0x");if(e&&!a)throw new i("ENV_INVALID",`x402 pay: the supplied signer address "${t.address}" is not an EVM (0x…) address, but the network is EVM.`);if(!e&&a)throw new i("ENV_INVALID",`x402 pay: the supplied signer address "${t.address}" is an EVM (0x…) address, but the network is Solana.`)},h=async(t,e)=>{let a;try{a=await import("@coinbase/cdp-sdk")}catch{throw new i("ENV_INVALID",'x402 pay: CDP-managed custody needs the optional @coinbase/cdp-sdk peer — install it, or use "raw-key"/"signer" custody instead.')}const[c,s,r]=await Promise.all([y(e,t.apiKeyIdSecretName??"CDP_API_KEY_ID"),y(e,t.apiKeySecretName??"CDP_API_KEY_SECRET"),y(e,t.walletSecretName??"CDP_WALLET_SECRET")]);return new a.CdpClient({apiKeyId:c,apiKeySecret:s,walletSecret:r}).evm.getOrCreateAccount({name:t.account})},m=async t=>{const e=t.startsWith("0x")?t:`0x${t}`;if(!p.test(e))throw new i("ENV_INVALID","x402 pay: the EVM wallet key must be a 32-byte hex private key (64 hex chars, optional 0x prefix).");const{privateKeyToAccount:a}=await import("viem/accounts");return a(e)},g=async t=>{const e=t.trim(),{createKeyPairSignerFromBytes:a,createKeyPairSignerFromPrivateKeyBytes:c,getBase58Encoder:s}=await import("@solana/kit");let r;if(e.startsWith("[")){let n;try{n=JSON.parse(e)}catch{throw new i("ENV_INVALID","x402 pay: the Solana wallet key looks like a JSON byte array but is not valid JSON.")}if(!Array.isArray(n)||n.some(o=>typeof o!="number"))throw new i("ENV_INVALID","x402 pay: the Solana wallet key JSON must be an array of byte values.");r=Uint8Array.from(n)}else try{r=Uint8Array.from(s().encode(e))}catch{throw new i("ENV_INVALID","x402 pay: the Solana wallet key must be a base58 secret key or a JSON byte array.")}if(r.length===64)return a(r);if(r.length===32)return c(r);throw new i("ENV_INVALID",`x402 pay: the Solana wallet key must decode to 32 or 64 bytes (got ${String(r.length)}). Provide a base58 secret key or a JSON byte array.`)},E=async(t,e,a)=>{const c=l(e.network),{signer:s}=e,r=w(e.network);let n;if(s.type==="signer")d(s.signer,r),n=s.signer;else if(s.type==="cdp"){if(!r)throw new i("NOT_IMPLEMENTED",`x402 pay: CDP-managed Solana custody (account "${s.account}") is not wired — a CDP Solana account is not a @solana/kit signer. Build a @solana/kit signer around it and pass it via the { type: "signer" } escape hatch, or use "raw-key".`);n=await h(s,a.getSecret)}else{const o=await y(a.getSecret,s.secretName);n=r?await m(o):await g(o)}if(r){const{registerExactEvmScheme:o}=await import("@x402/evm/exact/client");o(t,{networks:[c],signer:n})}else{const{registerExactSvmScheme:o}=await import("@x402/svm/exact/client");o(t,{networks:[c],signer:n})}};export{E as registerWallet,m as resolveEvmAccount,g as resolveSvmSigner};
@@ -0,0 +1 @@
1
+ const r=(t,e)=>({amount:t.amount??t.requirements.amount,asset:t.requirements.asset,from:t.payer,network:t.network,resource:e.resource,to:t.requirements.payTo,ts:e.ts,tx:t.transaction}),o=t=>({processedAt:t.ts,provider:"x402",providerEventId:t.tx,type:"x402.settled"});export{o as toPaymentEventRow,r as toReceipt};
@@ -0,0 +1 @@
1
+ import{createChargeMiddleware as h}from"./createChargeMiddleware-MQhSA6Wt.mjs";const d=(t,a)=>{let e;return async(o,r)=>(e??=h(t).catch(c=>{throw e=void 0,c}),(await e).handle(r,()=>a(o,r)))};export{d as withX402};
@@ -1,21 +1 @@
1
- import { createPayFetch } from '../packem_shared/createPayFetch-BeT05njL.mjs';
2
- export { DEFAULT_FACILITATOR_URL, resolveFacilitatorUrl } from '../packem_shared/DEFAULT_FACILITATOR_URL-Cbz6kIqa.mjs';
3
- export { isEvmNetwork, isSvmNetwork, toCaip2 } from '../packem_shared/EVM_NETWORKS-BhnYWUQ4.mjs';
4
- export { DEFAULT_STABLECOIN_DECIMALS, assertBoundedPolicy, buildPaymentGuard, buildSpendPolicy, createSpendState, releaseSpendOnFailure, usdToAtomic } from '../packem_shared/DEFAULT_STABLECOIN_DECIMALS-CpW619nu.mjs';
5
- export { registerWallet, resolveEvmAccount, resolveSvmSigner } from '../packem_shared/registerWallet-I4pVwq65.mjs';
6
-
7
- const createX402Pay = async (config, deps) => {
8
- const fetch = await createPayFetch(config, deps);
9
- return { fetch };
10
- };
11
- const lazyX402Pay = (config, deps) => {
12
- let railPromise;
13
- const fetch = async (input, init) => {
14
- railPromise ??= createX402Pay(config, deps);
15
- const rail = await railPromise;
16
- return rail.fetch(input, init);
17
- };
18
- return { fetch };
19
- };
20
-
21
- export { createPayFetch, createX402Pay, lazyX402Pay };
1
+ import{createPayFetch as c}from"../packem_shared/createPayFetch-C4UrAY7P.mjs";import{DEFAULT_FACILITATOR_URL as p,resolveFacilitatorUrl as d}from"../packem_shared/DEFAULT_FACILITATOR_URL-lUtljfJI.mjs";import{isEvmNetwork as S,isSvmNetwork as f,toCaip2 as u}from"../packem_shared/EVM_NETWORKS-XOms9Rtk.mjs";import{DEFAULT_STABLECOIN_DECIMALS as v,assertBoundedPolicy as E,buildPaymentGuard as F,buildSpendPolicy as L,createSpendState as P,releaseSpendOnFailure as T,usdToAtomic as x}from"../packem_shared/DEFAULT_STABLECOIN_DECIMALS-dzQLLL1Z.mjs";import{registerWallet as w,resolveEvmAccount as C,resolveSvmSigner as I}from"../packem_shared/registerWallet-Cu4qF5tj.mjs";const i=async(e,r)=>({fetch:await c(e,r)}),s=(e,r)=>{let t;return{fetch:async(o,a)=>(t??=i(e,r),(await t).fetch(o,a))}};export{p as DEFAULT_FACILITATOR_URL,v as DEFAULT_STABLECOIN_DECIMALS,E as assertBoundedPolicy,F as buildPaymentGuard,L as buildSpendPolicy,c as createPayFetch,P as createSpendState,i as createX402Pay,S as isEvmNetwork,f as isSvmNetwork,s as lazyX402Pay,w as registerWallet,T as releaseSpendOnFailure,C as resolveEvmAccount,d as resolveFacilitatorUrl,I as resolveSvmSigner,u as toCaip2,x as usdToAtomic};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/x402",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "Agentic payments (x402) for Lunora: charge agents per request (charge rail) and let your agents pay x402-gated resources (pay rail)",
5
5
  "keywords": [
6
6
  "agents",
@@ -58,7 +58,7 @@
58
58
  "@x402/evm": "2.19.0",
59
59
  "@x402/fetch": "2.19.0",
60
60
  "@x402/svm": "2.19.0",
61
- "viem": "2.55.2"
61
+ "viem": "2.55.8"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@coinbase/cdp-sdk": ">=1.0.0",
@@ -1,4 +0,0 @@
1
- const DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
2
- const resolveFacilitatorUrl = (facilitator) => facilitator?.url ?? DEFAULT_FACILITATOR_URL;
3
-
4
- export { DEFAULT_FACILITATOR_URL, resolveFacilitatorUrl };
@@ -1,90 +0,0 @@
1
- import { LunoraError } from '@lunora/errors';
2
- import { toCaip2 } from './EVM_NETWORKS-BhnYWUQ4.mjs';
3
-
4
- const USD_AMOUNT = /^\d+(?:\.\d+)?$/;
5
- const normaliseAddress = (address, network) => network.startsWith("eip155:") ? address.toLowerCase() : address;
6
- const DEFAULT_STABLECOIN_DECIMALS = 6;
7
- const createSpendState = () => {
8
- let spent = 0n;
9
- return {
10
- add: (amount) => {
11
- spent += amount;
12
- },
13
- release: (amount) => {
14
- spent = spent > amount ? spent - amount : 0n;
15
- },
16
- get spentAtomic() {
17
- return spent;
18
- }
19
- };
20
- };
21
- const usdToAtomic = (usd, decimals = DEFAULT_STABLECOIN_DECIMALS) => {
22
- if (!Number.isInteger(decimals) || decimals < 0) {
23
- throw new LunoraError("BAD_REQUEST", `x402 policy: decimals must be a non-negative integer, got ${String(decimals)}.`);
24
- }
25
- const raw = (typeof usd === "number" ? usd.toString() : usd).trim();
26
- const unsigned = raw.startsWith("$") ? raw.slice(1) : raw;
27
- if (!USD_AMOUNT.test(unsigned)) {
28
- throw new LunoraError("BAD_REQUEST", `x402 policy: "${String(usd)}" is not a valid USD amount (use a plain decimal like "0.01").`);
29
- }
30
- const [whole = "0", fraction = ""] = unsigned.split(".");
31
- const scaled = fraction.slice(0, decimals).padEnd(decimals, "0");
32
- return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(scaled === "" ? "0" : scaled);
33
- };
34
- const buildSpendPolicy = (policy) => {
35
- const decimals = policy.decimals ?? DEFAULT_STABLECOIN_DECIMALS;
36
- const maxPerCall = policy.maxPerCall === void 0 ? void 0 : usdToAtomic(policy.maxPerCall, decimals);
37
- const allowedNetworks = policy.allowedNetworks?.map((network) => toCaip2(network));
38
- const { allowedRecipients } = policy;
39
- return (_version, requirements) => requirements.filter((requirement) => {
40
- if (maxPerCall !== void 0 && BigInt(requirement.amount) > maxPerCall) {
41
- return false;
42
- }
43
- if (allowedNetworks !== void 0 && !allowedNetworks.includes(requirement.network)) {
44
- return false;
45
- }
46
- if (allowedRecipients !== void 0) {
47
- const payTo = normaliseAddress(requirement.payTo, requirement.network);
48
- return allowedRecipients.some((allowed) => normaliseAddress(allowed, requirement.network) === payTo);
49
- }
50
- return true;
51
- });
52
- };
53
- const buildPaymentGuard = (policy, state) => {
54
- const decimals = policy.decimals ?? DEFAULT_STABLECOIN_DECIMALS;
55
- const maxPerRun = policy.maxPerRun === void 0 ? void 0 : usdToAtomic(policy.maxPerRun, decimals);
56
- return async (context) => {
57
- const requirement = context.selectedRequirements;
58
- const amount = BigInt(requirement.amount);
59
- if (maxPerRun !== void 0 && state.spentAtomic + amount > maxPerRun) {
60
- return {
61
- abort: true,
62
- reason: `x402 policy: this payment (${requirement.amount}) would exceed the per-run cap (already spent ${state.spentAtomic.toString()}, cap ${maxPerRun.toString()}, in atomic base units).`
63
- };
64
- }
65
- state.add(amount);
66
- if (policy.onPaymentRequired !== void 0) {
67
- const approved = await policy.onPaymentRequired(requirement);
68
- if (!approved) {
69
- state.release(amount);
70
- return { abort: true, reason: "x402 policy: payment was declined by onPaymentRequired." };
71
- }
72
- }
73
- return void 0;
74
- };
75
- };
76
- const releaseSpendOnFailure = (state) => (context) => {
77
- state.release(BigInt(context.selectedRequirements.amount));
78
- return Promise.resolve();
79
- };
80
- const assertBoundedPolicy = (policy) => {
81
- const bounded = policy.maxPerCall !== void 0 || policy.maxPerRun !== void 0 || policy.onPaymentRequired !== void 0;
82
- if (!bounded) {
83
- throw new LunoraError(
84
- "FORBIDDEN",
85
- "x402 pay: refusing to build a wallet with an unbounded spend policy. Set at least one of maxPerCall, maxPerRun, or onPaymentRequired (allowedNetworks/allowedRecipients narrow but do not bound spend)."
86
- );
87
- }
88
- };
89
-
90
- export { DEFAULT_STABLECOIN_DECIMALS, assertBoundedPolicy, buildPaymentGuard, buildSpendPolicy, createSpendState, releaseSpendOnFailure, usdToAtomic };
@@ -1,26 +0,0 @@
1
- const NETWORK_TO_CAIP2 = {
2
- arbitrum: "eip155:42161",
3
- "arbitrum-sepolia": "eip155:421614",
4
- base: "eip155:8453",
5
- "base-sepolia": "eip155:84532",
6
- ethereum: "eip155:1",
7
- polygon: "eip155:137",
8
- solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
9
- "solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
10
- };
11
- const EVM_NETWORKS = ["arbitrum", "arbitrum-sepolia", "base", "base-sepolia", "ethereum", "polygon"];
12
- const SVM_NETWORKS = ["solana", "solana-devnet"];
13
- const toCaip2 = (network) => {
14
- const mapped = NETWORK_TO_CAIP2[network];
15
- if (mapped !== void 0) {
16
- return mapped;
17
- }
18
- if (network.includes(":")) {
19
- return network;
20
- }
21
- throw new Error(`Unknown x402 network "${network}". Use a friendly name (${EVM_NETWORKS.join(", ")}, ${SVM_NETWORKS.join(", ")}) or a raw CAIP-2 id.`);
22
- };
23
- const isEvmNetwork = (network) => toCaip2(network).startsWith("eip155:");
24
- const isSvmNetwork = (network) => toCaip2(network).startsWith("solana:");
25
-
26
- export { EVM_NETWORKS, NETWORK_TO_CAIP2, SVM_NETWORKS, isEvmNetwork, isSvmNetwork, toCaip2 };
@@ -1,162 +0,0 @@
1
- import { x402HTTPResourceServer } from '@x402/core/http';
2
- import { toCaip2, isEvmNetwork } from './EVM_NETWORKS-BhnYWUQ4.mjs';
3
- import { toReceipt } from './toPaymentEventRow-DW4O9N7Y.mjs';
4
- import { createFacilitatorClient } from './createFacilitatorClient-rXHBnCZm.mjs';
5
-
6
- const buildResourceServer = async (config) => {
7
- const { x402ResourceServer: ResourceServer } = await import('@x402/core/server');
8
- const server = new ResourceServer(createFacilitatorClient(config.facilitator));
9
- const network = toCaip2(config.network);
10
- if (isEvmNetwork(config.network)) {
11
- const { registerExactEvmScheme } = await import('@x402/evm/exact/server');
12
- registerExactEvmScheme(server, { networks: [network] });
13
- } else {
14
- const { registerExactSvmScheme } = await import('@x402/svm/exact/server');
15
- registerExactSvmScheme(server, { networks: [network] });
16
- }
17
- return server;
18
- };
19
-
20
- const PAYMENT_HEADER = "X-PAYMENT";
21
- const headerRecord = (headers) => {
22
- const record = /* @__PURE__ */ Object.create(null);
23
- for (const [key, value] of headers) {
24
- record[key] = value;
25
- }
26
- return record;
27
- };
28
- const reportReceipt = (sink, settlement, resource, waitUntil) => {
29
- if (sink === void 0) {
30
- return;
31
- }
32
- try {
33
- const sent = Promise.resolve(sink(toReceipt(settlement, { resource, ts: Date.now() }))).catch(() => {
34
- });
35
- waitUntil?.(sent);
36
- } catch {
37
- }
38
- };
39
- const resolvePayTo = (config) => {
40
- const evm = isEvmNetwork(config.network);
41
- const address = evm ? config.recipient.evm : config.recipient.svm;
42
- if (address === void 0 || address.length === 0) {
43
- throw new Error(`x402 charge on "${config.network}" needs recipient.${evm ? "evm" : "svm"} set.`);
44
- }
45
- return address;
46
- };
47
- const buildRoute = (config) => {
48
- const accepts = {
49
- network: toCaip2(config.network),
50
- payTo: resolvePayTo(config),
51
- price: config.price,
52
- scheme: "exact"
53
- };
54
- return { accepts };
55
- };
56
- const createRequestAdapter = (request, url) => {
57
- return {
58
- getAcceptHeader: () => request.headers.get("accept") ?? "",
59
- getHeader: (name) => request.headers.get(name) ?? void 0,
60
- getMethod: () => request.method,
61
- getPath: () => url.pathname,
62
- getQueryParam: (name) => {
63
- const values = url.searchParams.getAll(name);
64
- if (values.length === 0) {
65
- return void 0;
66
- }
67
- return values.length === 1 ? values[0] : values;
68
- },
69
- getQueryParams: () => {
70
- const params = /* @__PURE__ */ Object.create(null);
71
- for (const key of new Set(url.searchParams.keys())) {
72
- const values = url.searchParams.getAll(key);
73
- const [first, ...rest] = values;
74
- if (first === void 0) {
75
- continue;
76
- }
77
- params[key] = rest.length > 0 ? values : first;
78
- }
79
- return params;
80
- },
81
- getUrl: () => request.url,
82
- getUserAgent: () => request.headers.get("user-agent") ?? ""
83
- };
84
- };
85
- const toResponse = (instructions) => {
86
- const headers = new Headers(instructions.headers);
87
- const { body } = instructions;
88
- if (body === void 0 || body === null) {
89
- return new Response(void 0, { headers, status: instructions.status });
90
- }
91
- if (typeof body === "string") {
92
- if (instructions.isHtml && !headers.has("content-type")) {
93
- headers.set("content-type", "text/html; charset=utf-8");
94
- }
95
- return new Response(body, { headers, status: instructions.status });
96
- }
97
- return Response.json(body, { headers, status: instructions.status });
98
- };
99
- const withHeaders = (response, extra) => {
100
- const headers = new Headers(response.headers);
101
- for (const [key, value] of Object.entries(extra)) {
102
- headers.set(key, value);
103
- }
104
- return new Response(response.body, { headers, status: response.status, statusText: response.statusText });
105
- };
106
- const createChargeMiddleware = async (config, routeOverrides, options) => {
107
- const server = await buildResourceServer(config);
108
- const http = new x402HTTPResourceServer(server, { ...buildRoute(config), ...routeOverrides });
109
- await http.initialize();
110
- const settleBeforeHandler = options?.settleBeforeHandler ?? false;
111
- const handle = async (request, runHandler, deps) => {
112
- const url = new URL(request.url);
113
- const context = {
114
- adapter: createRequestAdapter(request, url),
115
- method: request.method,
116
- path: url.pathname,
117
- paymentHeader: request.headers.get(PAYMENT_HEADER) ?? void 0
118
- };
119
- const result = await http.processHTTPRequest(context);
120
- if (result.type === "no-payment-required") {
121
- return runHandler();
122
- }
123
- if (result.type === "payment-error") {
124
- return toResponse(result.response);
125
- }
126
- const resource = routeOverrides?.resource ?? request.url;
127
- if (settleBeforeHandler) {
128
- const settlement2 = await http.processSettlement(result.paymentPayload, result.paymentRequirements, result.declaredExtensions, {
129
- request: context
130
- });
131
- if (!settlement2.success) {
132
- return toResponse(settlement2.response);
133
- }
134
- reportReceipt(config.onReceipt, settlement2, resource, deps?.waitUntil);
135
- const response2 = await runHandler();
136
- return withHeaders(response2, settlement2.headers);
137
- }
138
- let response;
139
- try {
140
- response = await runHandler();
141
- } catch (error) {
142
- try {
143
- await result.cancellationDispatcher.cancel({ error, reason: "handler_threw" });
144
- } catch (cancelError) {
145
- console.error("x402 charge: failed to cancel payment after the handler threw", cancelError);
146
- }
147
- throw error;
148
- }
149
- const settlement = await http.processSettlement(result.paymentPayload, result.paymentRequirements, result.declaredExtensions, {
150
- request: context,
151
- responseHeaders: headerRecord(response.headers)
152
- });
153
- if (settlement.success) {
154
- reportReceipt(config.onReceipt, settlement, resource, deps?.waitUntil);
155
- return withHeaders(response, settlement.headers);
156
- }
157
- return toResponse(settlement.response);
158
- };
159
- return { handle };
160
- };
161
-
162
- export { buildRoute, createChargeMiddleware, createRequestAdapter, reportReceipt, resolvePayTo, toResponse, withHeaders };
@@ -1,16 +0,0 @@
1
- import { HTTPFacilitatorClient } from '@x402/core/server';
2
- import { resolveFacilitatorUrl } from './DEFAULT_FACILITATOR_URL-Cbz6kIqa.mjs';
3
-
4
- const createFacilitatorClient = (config) => {
5
- const url = resolveFacilitatorUrl(config);
6
- if (config?.headers === void 0) {
7
- return new HTTPFacilitatorClient({ url });
8
- }
9
- const headers = { ...config.headers };
10
- return new HTTPFacilitatorClient({
11
- createAuthHeaders: () => Promise.resolve({ settle: headers, supported: headers, verify: headers }),
12
- url
13
- });
14
- };
15
-
16
- export { createFacilitatorClient };
@@ -1,17 +0,0 @@
1
- import { x402Client } from '@x402/core/client';
2
- import { wrapFetchWithPayment } from '@x402/fetch';
3
- import { assertBoundedPolicy, buildSpendPolicy, buildPaymentGuard, releaseSpendOnFailure, createSpendState } from './DEFAULT_STABLECOIN_DECIMALS-CpW619nu.mjs';
4
- import { registerWallet } from './registerWallet-I4pVwq65.mjs';
5
-
6
- const createPayFetch = async (config, deps) => {
7
- assertBoundedPolicy(config.policy);
8
- const client = new x402Client();
9
- await registerWallet(client, config, deps);
10
- const state = createSpendState();
11
- client.registerPolicy(buildSpendPolicy(config.policy));
12
- client.onBeforePaymentCreation(buildPaymentGuard(config.policy, state));
13
- client.onPaymentCreationFailure(releaseSpendOnFailure(state));
14
- return wrapFetchWithPayment(deps.fetch ?? globalThis.fetch, client);
15
- };
16
-
17
- export { createPayFetch };
@@ -1,21 +0,0 @@
1
- import { createChargeMiddleware } from './createChargeMiddleware-D3yhOpFs.mjs';
2
-
3
- const createProcedureChargeGate = (config) => {
4
- const middlewareByFunction = /* @__PURE__ */ new Map();
5
- return async (request, spec, dispatch, deps) => {
6
- let pending = middlewareByFunction.get(spec.functionPath);
7
- if (pending === void 0) {
8
- pending = createChargeMiddleware({ ...config, price: spec.price }, { resource: spec.functionPath }, { settleBeforeHandler: true }).catch(
9
- (error) => {
10
- middlewareByFunction.delete(spec.functionPath);
11
- throw error;
12
- }
13
- );
14
- middlewareByFunction.set(spec.functionPath, pending);
15
- }
16
- const middleware = await pending;
17
- return middleware.handle(request, dispatch, deps);
18
- };
19
- };
20
-
21
- export { createProcedureChargeGate };
@@ -1,109 +0,0 @@
1
- import { LunoraError } from '@lunora/errors';
2
- import { toCaip2, isEvmNetwork } from './EVM_NETWORKS-BhnYWUQ4.mjs';
3
-
4
- const HEX_PRIVATE_KEY = /^0x[0-9a-fA-F]{64}$/;
5
- const requireSecret = async (getSecret, name) => {
6
- const value = await getSecret(name);
7
- if (value === void 0 || value.length === 0) {
8
- throw new LunoraError("ENV_INVALID", `x402 pay: secret "${name}" is not set — the agent wallet has no key to sign with.`);
9
- }
10
- return value;
11
- };
12
- const assertSignerFamily = (signer, evm) => {
13
- const looksEvm = signer.address.startsWith("0x");
14
- if (evm && !looksEvm) {
15
- throw new LunoraError("ENV_INVALID", `x402 pay: the supplied signer address "${signer.address}" is not an EVM (0x…) address, but the network is EVM.`);
16
- }
17
- if (!evm && looksEvm) {
18
- throw new LunoraError("ENV_INVALID", `x402 pay: the supplied signer address "${signer.address}" is an EVM (0x…) address, but the network is Solana.`);
19
- }
20
- };
21
- const resolveCdpEvmAccount = async (signer, getSecret) => {
22
- let cdpModule;
23
- try {
24
- cdpModule = await import('@coinbase/cdp-sdk');
25
- } catch {
26
- throw new LunoraError(
27
- "ENV_INVALID",
28
- 'x402 pay: CDP-managed custody needs the optional @coinbase/cdp-sdk peer — install it, or use "raw-key"/"signer" custody instead.'
29
- );
30
- }
31
- const [apiKeyId, apiKeySecret, walletSecret] = await Promise.all([
32
- requireSecret(getSecret, signer.apiKeyIdSecretName ?? "CDP_API_KEY_ID"),
33
- requireSecret(getSecret, signer.apiKeySecretName ?? "CDP_API_KEY_SECRET"),
34
- requireSecret(getSecret, signer.walletSecretName ?? "CDP_WALLET_SECRET")
35
- ]);
36
- const cdp = new cdpModule.CdpClient({ apiKeyId, apiKeySecret, walletSecret });
37
- return cdp.evm.getOrCreateAccount({ name: signer.account });
38
- };
39
- const resolveEvmAccount = async (privateKey) => {
40
- const key = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
41
- if (!HEX_PRIVATE_KEY.test(key)) {
42
- throw new LunoraError("ENV_INVALID", "x402 pay: the EVM wallet key must be a 32-byte hex private key (64 hex chars, optional 0x prefix).");
43
- }
44
- const { privateKeyToAccount } = await import('viem/accounts');
45
- return privateKeyToAccount(key);
46
- };
47
- const resolveSvmSigner = async (secret) => {
48
- const trimmed = secret.trim();
49
- const { createKeyPairSignerFromBytes, createKeyPairSignerFromPrivateKeyBytes, getBase58Encoder } = await import('@solana/kit');
50
- let bytes;
51
- if (trimmed.startsWith("[")) {
52
- let parsed;
53
- try {
54
- parsed = JSON.parse(trimmed);
55
- } catch {
56
- throw new LunoraError("ENV_INVALID", "x402 pay: the Solana wallet key looks like a JSON byte array but is not valid JSON.");
57
- }
58
- if (!Array.isArray(parsed) || parsed.some((entry) => typeof entry !== "number")) {
59
- throw new LunoraError("ENV_INVALID", "x402 pay: the Solana wallet key JSON must be an array of byte values.");
60
- }
61
- bytes = Uint8Array.from(parsed);
62
- } else {
63
- try {
64
- bytes = Uint8Array.from(getBase58Encoder().encode(trimmed));
65
- } catch {
66
- throw new LunoraError("ENV_INVALID", "x402 pay: the Solana wallet key must be a base58 secret key or a JSON byte array.");
67
- }
68
- }
69
- if (bytes.length === 64) {
70
- return createKeyPairSignerFromBytes(bytes);
71
- }
72
- if (bytes.length === 32) {
73
- return createKeyPairSignerFromPrivateKeyBytes(bytes);
74
- }
75
- throw new LunoraError(
76
- "ENV_INVALID",
77
- `x402 pay: the Solana wallet key must decode to 32 or 64 bytes (got ${String(bytes.length)}). Provide a base58 secret key or a JSON byte array.`
78
- );
79
- };
80
- const registerWallet = async (client, config, deps) => {
81
- const network = toCaip2(config.network);
82
- const { signer } = config;
83
- const evm = isEvmNetwork(config.network);
84
- let account;
85
- if (signer.type === "signer") {
86
- assertSignerFamily(signer.signer, evm);
87
- account = signer.signer;
88
- } else if (signer.type === "cdp") {
89
- if (!evm) {
90
- throw new LunoraError(
91
- "NOT_IMPLEMENTED",
92
- `x402 pay: CDP-managed Solana custody (account "${signer.account}") is not wired — a CDP Solana account is not a @solana/kit signer. Build a @solana/kit signer around it and pass it via the { type: "signer" } escape hatch, or use "raw-key".`
93
- );
94
- }
95
- account = await resolveCdpEvmAccount(signer, deps.getSecret);
96
- } else {
97
- const secret = await requireSecret(deps.getSecret, signer.secretName);
98
- account = evm ? await resolveEvmAccount(secret) : await resolveSvmSigner(secret);
99
- }
100
- if (evm) {
101
- const { registerExactEvmScheme } = await import('@x402/evm/exact/client');
102
- registerExactEvmScheme(client, { networks: [network], signer: account });
103
- } else {
104
- const { registerExactSvmScheme } = await import('@x402/svm/exact/client');
105
- registerExactSvmScheme(client, { networks: [network], signer: account });
106
- }
107
- };
108
-
109
- export { registerWallet, resolveEvmAccount, resolveSvmSigner };
@@ -1,22 +0,0 @@
1
- const toReceipt = (settlement, context) => {
2
- return {
3
- amount: settlement.amount ?? settlement.requirements.amount,
4
- asset: settlement.requirements.asset,
5
- from: settlement.payer,
6
- network: settlement.network,
7
- resource: context.resource,
8
- to: settlement.requirements.payTo,
9
- ts: context.ts,
10
- tx: settlement.transaction
11
- };
12
- };
13
- const toPaymentEventRow = (receipt) => {
14
- return {
15
- processedAt: receipt.ts,
16
- provider: "x402",
17
- providerEventId: receipt.tx,
18
- type: "x402.settled"
19
- };
20
- };
21
-
22
- export { toPaymentEventRow, toReceipt };
@@ -1,15 +0,0 @@
1
- import { createChargeMiddleware } from './createChargeMiddleware-D3yhOpFs.mjs';
2
-
3
- const withX402 = (config, handler) => {
4
- let pending;
5
- return async (context, request) => {
6
- pending ??= createChargeMiddleware(config).catch((error) => {
7
- pending = void 0;
8
- throw error;
9
- });
10
- const middleware = await pending;
11
- return middleware.handle(request, () => handler(context, request));
12
- };
13
- };
14
-
15
- export { withX402 };