@three-ws/x402-payment-modal 1.1.0 → 1.2.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/CHANGELOG.md +71 -9
- package/CONTRIBUTING.md +79 -0
- package/LICENSE +38 -180
- package/README.md +238 -63
- package/dist/index.d.ts +14 -3
- package/dist/x402.js +564 -206
- package/dist/x402.min.js +308 -178
- package/docs/EXAMPLES.md +137 -0
- package/docs/api-reference.md +32 -5
- package/docs/architecture.md +7 -1
- package/docs/react.md +163 -0
- package/docs/server-setup.md +63 -6
- package/examples/README.md +2 -1
- package/examples/react/App.jsx +95 -0
- package/examples/react/README.md +34 -31
- package/examples/server-express/server.js +16 -9
- package/examples/solana-crypto-paywall/README.md +81 -0
- package/examples/solana-crypto-paywall/facilitator.mjs +170 -0
- package/examples/solana-crypto-paywall/package.json +17 -0
- package/examples/solana-crypto-paywall/public/index.html +506 -0
- package/examples/solana-crypto-paywall/server.mjs +279 -0
- package/package.json +126 -111
- package/react/index.d.ts +39 -0
- package/react/index.js +112 -0
- package/server/checkout.js +208 -66
- package/server/express.js +7 -4
- package/server/vercel.js +2 -2
- package/src/index.js +563 -205
- package/types/index.d.ts +14 -3
- package/types/server.d.ts +2 -1
- package/examples/react/X402Button.jsx +0 -84
package/dist/x402.min.js
CHANGED
|
@@ -1,117 +1,210 @@
|
|
|
1
|
-
/*! @three-ws/x402-payment-modal v1.
|
|
2
|
-
const
|
|
3
|
-
`)}function
|
|
4
|
-
:root {
|
|
1
|
+
/*! @three-ws/x402-payment-modal v1.2.0 — UNLICENSED — https://github.com/nirholas/x402-payment-modal#readme */
|
|
2
|
+
const de="1.2.0",p={checkoutOrigin:null,checkoutPath:"/api/x402-checkout",brand:{name:null,url:null},footerNote:"x402 \xB7 onchain settled",builderCode:{wallet:"",service:""},theme:"auto",cssVars:null,esm:{solanaWeb3:"https://esm.sh/@solana/web3.js@1.95.3?bundle",nobleHashesSha3:"https://esm.sh/@noble/hashes@1.4.0/sha3?bundle"}},H={solanaWeb3:["https://cdn.jsdelivr.net/npm/@solana/web3.js@1.95.3/+esm","https://cdn.skypack.dev/@solana/web3.js@1.95.3"],nobleHashesSha3:["https://cdn.jsdelivr.net/npm/@noble/hashes@1.4.0/sha3/+esm","https://cdn.skypack.dev/@noble/hashes@1.4.0/sha3"]},ue=12e3;function W(n={}){if(!n||typeof n!="object")return p;for(const e of["checkoutOrigin","checkoutPath","footerNote","theme"])n[e]!==void 0&&(p[e]=n[e]);return n.brand&&typeof n.brand=="object"&&Object.assign(p.brand,n.brand),n.builderCode&&typeof n.builderCode=="object"&&Object.assign(p.builderCode,n.builderCode),n.esm&&typeof n.esm=="object"&&Object.assign(p.esm,n.esm),n.cssVars&&typeof n.cssVars=="object"&&(p.cssVars={...p.cssVars||{},...n.cssVars}),p}function U(){return`${p.checkoutOrigin||he}${p.checkoutPath}`}const xe="SIGN-IN-WITH-X",pe="sign-in-with-x",he=(()=>{try{const n=document.currentScript;if(n?.src)return new URL(n.src).origin;const e=document.querySelector('script[src*="/x402.js"]');if(e?.src)return new URL(e.src).origin}catch{}return location.origin})(),z={"eip155:8453":{chainId:8453,name:"Base",explorer:"https://basescan.org/tx/"},"eip155:84532":{chainId:84532,name:"Base Sepolia",explorer:"https://sepolia.basescan.org/tx/"},"eip155:42161":{chainId:42161,name:"Arbitrum",explorer:"https://arbiscan.io/tx/"},"eip155:10":{chainId:10,name:"Optimism",explorer:"https://optimistic.etherscan.io/tx/"}};function Re(n){if(!n||typeof n!="object")return n;const e=n.amount??n.maxAmountRequired;return e!=null&&n.amount==null?{...n,amount:String(e)}:n}const M="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",j="FeMbDoX7R1Psc4GEcvJdsbNbZA3bfztcyDCatJVJpump",L=Object.freeze({[M]:{symbol:"USDC",name:"USD Coin",decimals:6,stable:!0},[j]:{symbol:"THREE",name:"THREE",decimals:6,accent:"#7aa2ff",glyph:"\u25C6"}});function k(n){const e=n&&n.asset&&L[n.asset]||null,t=n?.extra?.name,r=(t?String(t).replace(/^USD Coin$/,"USDC"):e?.symbol)||"USDC",o=Number(n?.extra?.decimals??e?.decimals??6),s=e?.stable||J.has(String(t||"").toLowerCase());return{symbol:r,decimals:o,stable:s,accent:e?.accent||null,glyph:e?.glyph||null}}function He(n){return n?.asset===j}function F(n){return(n?.accepts||[]).filter(e=>O(e.network))}function V(n){return n.find(e=>e.asset===M)||n.find(e=>k(e).stable)||n[0]||null}function O(n){return typeof n=="string"&&(n==="solana"||n.startsWith("solana:"))}function fe(n){return typeof n=="string"&&n.startsWith("eip155:")}function K(n){if(!fe(n?.network))return!1;const e=n?.extra?.assetTransferMethod;return!e||e==="eip3009"}function v(n,e){return O(n)?"Solana":z[n]?.name||e?.extra?.name||n}function me(n,e){if(!e)return null;if(O(n))return`https://solscan.io/tx/${e}`;const t=z[n];return t?`${t.explorer}${e}`:null}function C(n,e=6){const t=Number(n)/10**e;return t<.01?t.toFixed(6).replace(/0+$/,"").replace(/\.$/,""):t<1?t.toFixed(4).replace(/0+$/,"").replace(/\.$/,""):t.toFixed(2)}function be(n){const e=JSON.stringify(n);return typeof Buffer<"u"?Buffer.from(e,"utf8").toString("base64"):btoa(unescape(encodeURIComponent(e)))}function q(n){if(!n)return null;try{const e=typeof Buffer<"u"?Buffer.from(n,"base64").toString("utf8"):decodeURIComponent(escape(atob(n)));return JSON.parse(e)}catch{return null}}const we="x402.spend.",J=new Set(["usdc","usd coin","usdt","tether","binance-peg usd coin","dai"]);function ye(n=Date.now()){const e=Math.floor(n/36e5),t=Math.floor(n/864e5);return{hour:e,day:t}}function Y(n,e,t){return`${we}${e}.${n.toLowerCase()}.${t}`}function P(n,e,t){try{const r=localStorage.getItem(Y(n,e,t));return r?BigInt(r):0n}catch{return 0n}}function B(n,e,t,r){try{localStorage.setItem(Y(n,e,t),r.toString())}catch{}}function ge(n,e){const t=BigInt(n),r=e&&e.asset&&L[e.asset]||null,o=Number(e?.extra?.decimals??r?.decimals??6),s=String(e?.extra?.name||"").toLowerCase();return J.has(s)||r?.stable?o===6?t:o>6?t/10n**BigInt(o-6):t*10n**BigInt(6-o):t}function G({accept:n,caps:e,address:t}){if(!e||!t)return{abort:!1};const r=ge(n.amount,n),o=e.maxPerCall!=null?BigInt(e.maxPerCall):null,s=e.maxPerHour!=null?BigInt(e.maxPerHour):null,a=e.maxPerDay!=null?BigInt(e.maxPerDay):null;if(o!=null&&r>o)return{abort:!0,reason:`Per-call cap exceeded (${r} > ${o} \xB5USD)`};const i=ye(),l=P(t,"hr",i.hour)+r,c=P(t,"day",i.day)+r;return s!=null&&l>s?{abort:!0,reason:`Hourly cap exceeded (${l} > ${s} \xB5USD)`}:a!=null&&c>a?{abort:!0,reason:`Daily cap exceeded (${c} > ${a} \xB5USD)`}:(B(t,"hr",i.hour,l),B(t,"day",i.day,c),{abort:!1,reservation:{address:t,microUsd:r,buckets:i}})}function D(n){if(!n)return;const{address:e,microUsd:t,buckets:r}=n,o=P(e,"hr",r.hour),s=P(e,"day",r.day),a=o-t,i=s-t;B(e,"hr",r.hour,a<0n?0n:a),B(e,"day",r.day,i<0n?0n:i)}const ve="builder-code",R=/^[a-z0-9_]{1,32}$/;function X(n){const t=n?.extensions?.[ve]?.info?.a;if(!t||!R.test(t))return null;const r={a:t},o=p.builderCode.service,s=p.builderCode.wallet;return o&&R.test(o)&&(r.s=[o]),s&&R.test(s)&&(r.w=s),r}function ke(n){const e=n?.extensions?.[pe];return!e||!e.info||!Array.isArray(e.supportedChains)||!e.supportedChains.length?null:e}function Z(n,e){for(const t of n.supportedChains){if(e==="evm"&&t.type==="eip191")return{chain:t,kind:"evm"};if(e==="solana"&&t.type==="ed25519")return{chain:t,kind:"solana"}}return null}function Q(n,e,t){const r=e.type==="eip191",o=r?`${n.domain} wants you to sign in with your Ethereum account:`:`${n.domain} wants you to sign in with your Solana account:`,[,s=""]=String(e.chainId).split(":"),a=r?String(parseInt(s,10)):s,i=[o,t,""];if(n.statement?i.push(n.statement,""):r&&i.push(""),i.push(`URI: ${n.uri}`),i.push(`Version: ${n.version||"1"}`),i.push(`Chain ID: ${a}`),i.push(`Nonce: ${n.nonce}`),i.push(`Issued At: ${n.issuedAt}`),n.expirationTime&&i.push(`Expiration Time: ${n.expirationTime}`),n.notBefore&&i.push(`Not Before: ${n.notBefore}`),n.requestId!==void 0&&n.requestId!==null&&i.push(`Request ID: ${n.requestId}`),Array.isArray(n.resources)&&n.resources.length){i.push("Resources:");for(const l of n.resources)i.push(`- ${l}`)}return i.join(`
|
|
3
|
+
`)}function Se(n){const e=JSON.stringify(n);return typeof Buffer<"u"?Buffer.from(e,"utf8").toString("base64"):btoa(unescape(encodeURIComponent(e)))}const ee="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";function Ee(n){if(!n||n.length===0)return"";let e=0;for(;e<n.length&&n[e]===0;)e++;let t=0n;for(let o=0;o<n.length;o++)t=t<<8n|BigInt(n[o]);let r="";for(;t>0n;)r=ee[Number(t%58n)]+r,t/=58n;for(let o=0;o<e;o++)r=ee[0]+r;return r}let N=null;async function $e(){if(N)return N;const e=(await ae(p.esm.nobleHashesSha3,H.nobleHashesSha3,"@noble/hashes/sha3")).keccak_256;return N=t=>{const r=String(t).toLowerCase().replace(/^0x/,"");if(!/^[0-9a-f]{40}$/.test(r))throw new Error(`invalid EVM address: ${t}`);const o=e(new TextEncoder().encode(r));let s="";for(let i=0;i<o.length;i++)s+=o[i].toString(16).padStart(2,"0");let a="0x";for(let i=0;i<40;i++)a+=parseInt(s[i],16)>=8?r[i].toUpperCase():r[i];return a},N}const te="x402-styles",Ae=`
|
|
5
4
|
--x402-z: 2147483600;
|
|
5
|
+
--x402-font: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
6
|
+
--x402-mono: ui-monospace, "JetBrains Mono", "SF Mono", Menlo, monospace;
|
|
7
|
+
--x402-scrim: rgba(8, 10, 18, 0.55);
|
|
8
|
+
--x402-surface: #ffffff;
|
|
9
|
+
--x402-surface-2: #f7f8fa;
|
|
10
|
+
--x402-fg: #0f1116;
|
|
11
|
+
--x402-muted: #646b7a;
|
|
12
|
+
--x402-faint: #9aa1ad;
|
|
13
|
+
--x402-border: #ecedf1;
|
|
14
|
+
--x402-border-strong: #d8dce4;
|
|
15
|
+
--x402-accent: #635bff;
|
|
16
|
+
--x402-accent-hover: #524bdb;
|
|
17
|
+
--x402-accent-weak: #f2f1ff;
|
|
18
|
+
--x402-accent-fg: #ffffff;
|
|
19
|
+
--x402-success: #16a34a;
|
|
20
|
+
--x402-success-fg: #15803d;
|
|
21
|
+
--x402-success-bg: #f0fdf4;
|
|
22
|
+
--x402-success-border: #bbf7d0;
|
|
23
|
+
--x402-error: #dc2626;
|
|
24
|
+
--x402-error-fg: #b91c1c;
|
|
25
|
+
--x402-error-bg: #fef2f2;
|
|
26
|
+
--x402-error-border: #fecaca;
|
|
27
|
+
--x402-warn-fg: #b45309;
|
|
28
|
+
--x402-warn-bg: #fffbeb;
|
|
29
|
+
--x402-warn-border: #fde68a;
|
|
30
|
+
--x402-link: #524bdb;
|
|
31
|
+
--x402-radius: 18px;
|
|
32
|
+
--x402-radius-md: 12px;
|
|
33
|
+
--x402-radius-sm: 9px;
|
|
34
|
+
--x402-shadow: 0 24px 80px rgba(8, 10, 18, 0.28), 0 4px 16px rgba(8, 10, 18, 0.12);
|
|
35
|
+
--x402-btn-bg: #0f1116;
|
|
36
|
+
--x402-btn-fg: #ffffff;
|
|
37
|
+
--x402-btn-hover: #242833;
|
|
38
|
+
--x402-btn-shadow: 0 1px 2px rgba(8, 10, 18, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.12);
|
|
39
|
+
`,ne=`
|
|
40
|
+
--x402-scrim: rgba(0, 0, 0, 0.62);
|
|
41
|
+
--x402-surface: #161616;
|
|
42
|
+
--x402-surface-2: #1d1d1d;
|
|
43
|
+
--x402-fg: #e6e8f0;
|
|
44
|
+
--x402-muted: #9aa1b4;
|
|
45
|
+
--x402-faint: #6b7088;
|
|
46
|
+
--x402-border: #2a2a2a;
|
|
47
|
+
--x402-border-strong: #3a3a40;
|
|
48
|
+
--x402-accent: #8b85ff;
|
|
49
|
+
--x402-accent-hover: #a29cff;
|
|
50
|
+
--x402-accent-weak: #1e1b3a;
|
|
51
|
+
--x402-accent-fg: #ffffff;
|
|
52
|
+
--x402-success: #22c55e;
|
|
53
|
+
--x402-success-fg: #4ade80;
|
|
54
|
+
--x402-success-bg: #0b1f17;
|
|
55
|
+
--x402-success-border: #14532d;
|
|
56
|
+
--x402-error: #ef4444;
|
|
57
|
+
--x402-error-fg: #fca5a5;
|
|
58
|
+
--x402-error-bg: #1f1416;
|
|
59
|
+
--x402-error-border: #7f1d1d;
|
|
60
|
+
--x402-warn-fg: #fcd34d;
|
|
61
|
+
--x402-warn-bg: #2a1d10;
|
|
62
|
+
--x402-warn-border: #78350f;
|
|
63
|
+
--x402-link: #a29cff;
|
|
64
|
+
--x402-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
|
|
65
|
+
--x402-btn-bg: #ffffff;
|
|
66
|
+
--x402-btn-fg: #0f1116;
|
|
67
|
+
--x402-btn-hover: #e7e9ee;
|
|
68
|
+
--x402-btn-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
69
|
+
`,Ce=`
|
|
70
|
+
.x402-overlay { ${Ae} }
|
|
71
|
+
.x402-overlay.x402-theme-dark { ${ne} }
|
|
72
|
+
@media (prefers-color-scheme: dark) {
|
|
73
|
+
.x402-overlay:not(.x402-theme-light) { ${ne} }
|
|
6
74
|
}
|
|
7
75
|
.x402-overlay {
|
|
8
76
|
position: fixed; inset: 0;
|
|
9
|
-
background:
|
|
77
|
+
background: var(--x402-scrim);
|
|
10
78
|
backdrop-filter: blur(10px);
|
|
11
79
|
-webkit-backdrop-filter: blur(10px);
|
|
12
80
|
display: flex; align-items: center; justify-content: center;
|
|
13
81
|
z-index: var(--x402-z);
|
|
14
82
|
opacity: 0; transition: opacity 0.16s ease-out;
|
|
15
|
-
font-family: -
|
|
83
|
+
font-family: var(--x402-font);
|
|
16
84
|
-webkit-font-smoothing: antialiased;
|
|
17
|
-
color:
|
|
85
|
+
color: var(--x402-fg);
|
|
18
86
|
}
|
|
19
87
|
.x402-overlay.x402-open { opacity: 1; }
|
|
20
88
|
.x402-overlay * { box-sizing: border-box; }
|
|
89
|
+
.x402-overlay :focus-visible {
|
|
90
|
+
outline: 2px solid var(--x402-accent);
|
|
91
|
+
outline-offset: 2px;
|
|
92
|
+
}
|
|
21
93
|
.x402-modal {
|
|
22
94
|
width: calc(100% - 32px); max-width: 420px;
|
|
23
|
-
background:
|
|
24
|
-
border-radius:
|
|
25
|
-
box-shadow:
|
|
95
|
+
background: var(--x402-surface);
|
|
96
|
+
border-radius: var(--x402-radius);
|
|
97
|
+
box-shadow: var(--x402-shadow);
|
|
26
98
|
overflow: hidden;
|
|
27
99
|
transform: translateY(8px) scale(0.985);
|
|
28
|
-
transition: transform 0.
|
|
100
|
+
transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
29
101
|
display: flex; flex-direction: column;
|
|
30
102
|
max-height: calc(100dvh - 32px);
|
|
31
103
|
}
|
|
32
104
|
.x402-overlay.x402-open .x402-modal { transform: translateY(0) scale(1); }
|
|
33
105
|
.x402-head {
|
|
34
106
|
padding: 18px 20px 14px;
|
|
35
|
-
border-bottom: 1px solid
|
|
107
|
+
border-bottom: 1px solid var(--x402-border);
|
|
36
108
|
display: flex; align-items: center; gap: 12px;
|
|
37
109
|
}
|
|
38
|
-
.x402-head .x402-merchant {
|
|
39
|
-
|
|
40
|
-
}
|
|
110
|
+
.x402-head .x402-merchant { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; }
|
|
111
|
+
.x402-head .x402-merchant-text { min-width: 0; }
|
|
112
|
+
.x402-brand-logo { width: 30px; height: 30px; flex: 0 0 auto; border-radius: 8px; object-fit: cover; }
|
|
41
113
|
.x402-merchant .x402-name {
|
|
42
|
-
font-size: 12px; color:
|
|
114
|
+
font-size: 12px; color: var(--x402-muted); font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase;
|
|
43
115
|
margin-bottom: 2px;
|
|
44
116
|
}
|
|
45
117
|
.x402-merchant .x402-action {
|
|
46
|
-
font-size: 17px; font-weight: 700; color:
|
|
118
|
+
font-size: 17px; font-weight: 700; color: var(--x402-fg);
|
|
47
119
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
48
120
|
letter-spacing: -0.01em;
|
|
49
121
|
}
|
|
50
122
|
.x402-close {
|
|
51
|
-
width: 32px; height: 32px;
|
|
52
|
-
border-radius: 8px; border: none; background:
|
|
53
|
-
|
|
123
|
+
width: 32px; height: 32px; flex: 0 0 auto;
|
|
124
|
+
border-radius: 8px; border: none; background: var(--x402-surface-2);
|
|
125
|
+
color: var(--x402-muted); cursor: pointer;
|
|
54
126
|
display: flex; align-items: center; justify-content: center;
|
|
55
|
-
transition: background 0.12s;
|
|
127
|
+
transition: background 0.12s, color 0.12s;
|
|
56
128
|
}
|
|
57
|
-
.x402-close:hover { background:
|
|
129
|
+
.x402-close:hover { background: var(--x402-border-strong); color: var(--x402-fg); }
|
|
130
|
+
.x402-close svg { width: 14px; height: 14px; }
|
|
58
131
|
|
|
59
132
|
.x402-price-row {
|
|
60
133
|
padding: 18px 20px;
|
|
61
|
-
display: flex; align-items: baseline; justify-content: space-between;
|
|
62
|
-
background:
|
|
63
|
-
border-bottom: 1px solid
|
|
134
|
+
display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
|
|
135
|
+
background: var(--x402-surface-2);
|
|
136
|
+
border-bottom: 1px solid var(--x402-border);
|
|
64
137
|
}
|
|
138
|
+
.x402-price-main { min-width: 0; }
|
|
65
139
|
.x402-price {
|
|
66
|
-
font-size: 32px; font-weight: 700; letter-spacing: -0.02em; color:
|
|
140
|
+
font-size: 32px; font-weight: 700; letter-spacing: -0.02em; color: var(--x402-fg);
|
|
67
141
|
font-variant-numeric: tabular-nums;
|
|
68
142
|
}
|
|
69
|
-
.x402-price .x402-currency { font-size: 14px; color:
|
|
143
|
+
.x402-price .x402-currency { font-size: 14px; color: var(--x402-muted); font-weight: 600; margin-left: 6px; letter-spacing: 0; }
|
|
144
|
+
.x402-price-sub { font-size: 11px; color: var(--x402-muted); margin-top: 3px; font-weight: 500; }
|
|
70
145
|
.x402-network {
|
|
71
|
-
font-size: 12px; color:
|
|
72
|
-
background:
|
|
146
|
+
font-size: 12px; color: var(--x402-muted); font-weight: 500; flex: 0 0 auto;
|
|
147
|
+
background: var(--x402-surface); border: 1px solid var(--x402-border);
|
|
148
|
+
padding: 5px 10px; border-radius: 99px;
|
|
73
149
|
display: inline-flex; align-items: center; gap: 6px;
|
|
74
150
|
}
|
|
75
151
|
.x402-network::before {
|
|
76
152
|
content: ''; width: 6px; height: 6px; border-radius: 50%;
|
|
77
|
-
background:
|
|
153
|
+
background: var(--x402-success);
|
|
154
|
+
box-shadow: 0 0 0 0 var(--x402-success);
|
|
155
|
+
animation: x402-pulse 2s ease-out infinite;
|
|
156
|
+
}
|
|
157
|
+
@keyframes x402-pulse {
|
|
158
|
+
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--x402-success) 55%, transparent); }
|
|
159
|
+
70% { box-shadow: 0 0 0 5px transparent; }
|
|
160
|
+
100% { box-shadow: 0 0 0 0 transparent; }
|
|
78
161
|
}
|
|
79
162
|
|
|
80
163
|
.x402-body {
|
|
81
|
-
padding: 16px 20px 18px;
|
|
164
|
+
padding: 16px 20px max(18px, env(safe-area-inset-bottom));
|
|
82
165
|
flex: 1 1 auto; overflow-y: auto;
|
|
83
166
|
display: flex; flex-direction: column; gap: 10px;
|
|
84
167
|
}
|
|
168
|
+
.x402-body > * { animation: x402-fade 0.16s ease-out both; }
|
|
169
|
+
@keyframes x402-fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
|
|
85
170
|
.x402-step {
|
|
86
171
|
display: flex; gap: 12px; align-items: flex-start;
|
|
87
172
|
padding: 10px 0;
|
|
88
173
|
}
|
|
89
|
-
.x402-step + .x402-step { border-top: 1px solid
|
|
174
|
+
.x402-step + .x402-step { border-top: 1px solid var(--x402-border); }
|
|
90
175
|
.x402-step-num {
|
|
91
176
|
width: 22px; height: 22px; flex: 0 0 auto;
|
|
92
|
-
border-radius: 50%; border: 1.5px solid
|
|
93
|
-
color:
|
|
177
|
+
border-radius: 50%; border: 1.5px solid var(--x402-border-strong); background: var(--x402-surface);
|
|
178
|
+
color: var(--x402-muted);
|
|
94
179
|
font-size: 11px; font-weight: 700;
|
|
95
180
|
display: flex; align-items: center; justify-content: center;
|
|
96
181
|
}
|
|
97
182
|
.x402-step.x402-active .x402-step-num {
|
|
98
|
-
border-color:
|
|
183
|
+
border-color: var(--x402-accent); background: var(--x402-accent); color: var(--x402-accent-fg);
|
|
99
184
|
animation: x402-spin 1.2s linear infinite;
|
|
100
185
|
}
|
|
101
186
|
.x402-step.x402-done .x402-step-num {
|
|
102
|
-
border-color:
|
|
187
|
+
border-color: var(--x402-success); background: var(--x402-success); color: #fff;
|
|
103
188
|
}
|
|
104
189
|
.x402-step.x402-error .x402-step-num {
|
|
105
|
-
border-color:
|
|
190
|
+
border-color: var(--x402-error); background: var(--x402-error); color: #fff;
|
|
106
191
|
}
|
|
107
192
|
@keyframes x402-spin {
|
|
108
|
-
from { box-shadow: 0 0 0 0
|
|
109
|
-
to { box-shadow: 0 0 0 8px
|
|
193
|
+
from { box-shadow: 0 0 0 0 color-mix(in srgb, var(--x402-accent) 40%, transparent); }
|
|
194
|
+
to { box-shadow: 0 0 0 8px transparent; }
|
|
110
195
|
}
|
|
111
196
|
.x402-step-body { flex: 1; min-width: 0; }
|
|
112
|
-
.x402-step-label { font-size: 14px; font-weight: 600; color:
|
|
113
|
-
.x402-step-meta { font-size: 12px; color:
|
|
114
|
-
.x402-step.x402-error .x402-step-meta { color:
|
|
197
|
+
.x402-step-label { font-size: 14px; font-weight: 600; color: var(--x402-fg); line-height: 1.35; }
|
|
198
|
+
.x402-step-meta { font-size: 12px; color: var(--x402-muted); margin-top: 2px; font-feature-settings: 'tnum' 1; }
|
|
199
|
+
.x402-step.x402-error .x402-step-meta { color: var(--x402-error-fg); }
|
|
200
|
+
|
|
201
|
+
.x402-skeleton {
|
|
202
|
+
border-radius: 6px;
|
|
203
|
+
background: linear-gradient(100deg, var(--x402-surface-2) 30%, var(--x402-border) 50%, var(--x402-surface-2) 70%);
|
|
204
|
+
background-size: 200% 100%;
|
|
205
|
+
animation: x402-shimmer 1.3s ease-in-out infinite;
|
|
206
|
+
}
|
|
207
|
+
@keyframes x402-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
|
|
115
208
|
|
|
116
209
|
.x402-wallet-buttons {
|
|
117
210
|
display: flex; flex-direction: column; gap: 8px;
|
|
@@ -119,26 +212,30 @@ const te="1.1.0",h={checkoutOrigin:null,checkoutPath:"/api/x402-checkout",brand:
|
|
|
119
212
|
}
|
|
120
213
|
.x402-wallet-btn {
|
|
121
214
|
width: 100%; padding: 13px 14px;
|
|
122
|
-
background:
|
|
123
|
-
font-size: 14px; font-weight: 600; color:
|
|
215
|
+
background: var(--x402-surface); border: 1.5px solid var(--x402-border-strong); border-radius: 11px;
|
|
216
|
+
font-size: 14px; font-weight: 600; color: var(--x402-fg);
|
|
124
217
|
cursor: pointer; font-family: inherit;
|
|
125
218
|
display: flex; align-items: center; gap: 12px;
|
|
126
219
|
transition: border-color 0.12s, background 0.12s, transform 0.05s;
|
|
127
220
|
}
|
|
128
|
-
.x402-wallet-btn:hover:not(:disabled) { border-color:
|
|
221
|
+
.x402-wallet-btn:hover:not(:disabled) { border-color: var(--x402-accent); background: var(--x402-accent-weak); }
|
|
129
222
|
.x402-wallet-btn:active:not(:disabled) { transform: translateY(1px); }
|
|
130
223
|
.x402-wallet-btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
131
224
|
.x402-wallet-icon {
|
|
132
225
|
width: 28px; height: 28px; flex: 0 0 auto;
|
|
133
226
|
border-radius: 7px;
|
|
134
227
|
display: flex; align-items: center; justify-content: center;
|
|
135
|
-
|
|
136
|
-
background: #f3f4f7;
|
|
228
|
+
background: var(--x402-surface-2); overflow: hidden;
|
|
137
229
|
}
|
|
138
|
-
.x402-wallet-icon.x402-
|
|
139
|
-
.x402-wallet-icon.x402-metamask { background: linear-gradient(135deg, #f6851b, #e2761b); color: #fff; }
|
|
230
|
+
.x402-wallet-icon svg, .x402-wallet-icon img { width: 18px; height: 18px; }
|
|
140
231
|
.x402-wallet-name { flex: 1; text-align: left; }
|
|
141
|
-
.x402-wallet-meta { font-size: 11px; color:
|
|
232
|
+
.x402-wallet-meta { font-size: 11px; color: var(--x402-muted); font-weight: 500; }
|
|
233
|
+
.x402-wallet-install {
|
|
234
|
+
font-size: 12px; color: var(--x402-muted); line-height: 1.5; text-align: center;
|
|
235
|
+
padding: 4px 0 2px;
|
|
236
|
+
}
|
|
237
|
+
.x402-wallet-install a { color: var(--x402-link); text-decoration: none; font-weight: 600; }
|
|
238
|
+
.x402-wallet-install a:hover { text-decoration: underline; }
|
|
142
239
|
|
|
143
240
|
.x402-token-row {
|
|
144
241
|
display: flex; gap: 8px; margin-bottom: 10px;
|
|
@@ -146,230 +243,263 @@ const te="1.1.0",h={checkoutOrigin:null,checkoutPath:"/api/x402-checkout",brand:
|
|
|
146
243
|
.x402-token-pill {
|
|
147
244
|
flex: 1; min-width: 0; cursor: pointer; font-family: inherit;
|
|
148
245
|
padding: 9px 12px; border-radius: 10px;
|
|
149
|
-
background:
|
|
246
|
+
background: var(--x402-surface); border: 1.5px solid var(--x402-border-strong);
|
|
150
247
|
display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
|
|
151
|
-
transition: border-color 0.12s, background 0.12s, transform 0.05s;
|
|
248
|
+
transition: border-color 0.12s, background 0.12s, transform 0.05s, box-shadow 0.12s;
|
|
152
249
|
}
|
|
153
|
-
.x402-token-pill:hover { border-color:
|
|
250
|
+
.x402-token-pill:hover { border-color: var(--x402-accent); background: var(--x402-accent-weak); }
|
|
154
251
|
.x402-token-pill:active { transform: translateY(1px); }
|
|
155
|
-
.x402-token-pill.x402-on {
|
|
156
|
-
|
|
157
|
-
|
|
252
|
+
.x402-token-pill.x402-on {
|
|
253
|
+
border-color: var(--x402-accent); background: var(--x402-accent-weak);
|
|
254
|
+
box-shadow: inset 0 0 0 1px var(--x402-accent);
|
|
255
|
+
}
|
|
256
|
+
.x402-token-sym { font-size: 13px; font-weight: 700; color: var(--x402-fg); letter-spacing: -0.005em; }
|
|
257
|
+
.x402-token-amt { font-size: 11px; color: var(--x402-muted); font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
158
258
|
|
|
159
259
|
.x402-pay-btn {
|
|
160
260
|
width: 100%; padding: 14px 16px;
|
|
161
|
-
background:
|
|
162
|
-
border-radius:
|
|
261
|
+
background: var(--x402-btn-bg); color: var(--x402-btn-fg); border: none;
|
|
262
|
+
border-radius: var(--x402-radius-md);
|
|
163
263
|
font-size: 15px; font-weight: 700; font-family: inherit;
|
|
164
264
|
cursor: pointer; letter-spacing: -0.005em;
|
|
165
|
-
|
|
265
|
+
box-shadow: var(--x402-btn-shadow);
|
|
266
|
+
transition: background 0.12s, transform 0.1s, box-shadow 0.12s;
|
|
166
267
|
margin-top: 4px;
|
|
167
268
|
display: flex; align-items: center; justify-content: center; gap: 8px;
|
|
168
269
|
}
|
|
169
|
-
.x402-pay-btn:hover:not(:disabled) { background:
|
|
170
|
-
.x402-pay-btn:active:not(:disabled) { transform: translateY(
|
|
171
|
-
.x402-pay-btn:disabled {
|
|
270
|
+
.x402-pay-btn:hover:not(:disabled) { background: var(--x402-btn-hover); transform: translateY(-1px); }
|
|
271
|
+
.x402-pay-btn:active:not(:disabled) { transform: translateY(0); }
|
|
272
|
+
.x402-pay-btn:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }
|
|
172
273
|
|
|
173
274
|
.x402-pay-secondary {
|
|
174
275
|
width: 100%; padding: 12px 14px;
|
|
175
|
-
background:
|
|
176
|
-
border: 1.5px solid
|
|
276
|
+
background: var(--x402-surface); color: var(--x402-fg);
|
|
277
|
+
border: 1.5px solid var(--x402-border-strong); border-radius: 11px;
|
|
177
278
|
font-size: 14px; font-weight: 600; font-family: inherit;
|
|
178
279
|
cursor: pointer; letter-spacing: -0.005em;
|
|
179
280
|
margin-top: 6px;
|
|
180
281
|
transition: border-color 0.12s, background 0.12s, transform 0.05s;
|
|
181
282
|
}
|
|
182
|
-
.x402-pay-secondary:hover:not(:disabled) { border-color:
|
|
283
|
+
.x402-pay-secondary:hover:not(:disabled) { border-color: var(--x402-accent); background: var(--x402-accent-weak); }
|
|
183
284
|
.x402-pay-secondary:active:not(:disabled) { transform: translateY(1px); }
|
|
184
285
|
|
|
286
|
+
.x402-trust {
|
|
287
|
+
font-size: 11.5px; color: var(--x402-muted); text-align: center;
|
|
288
|
+
margin-top: 10px; line-height: 1.45;
|
|
289
|
+
display: flex; align-items: center; justify-content: center; gap: 6px;
|
|
290
|
+
}
|
|
291
|
+
.x402-trust svg { width: 12px; height: 12px; flex: 0 0 auto; color: var(--x402-success); }
|
|
292
|
+
|
|
185
293
|
.x402-siwx-hint {
|
|
186
|
-
font-size: 11px; color:
|
|
294
|
+
font-size: 11px; color: var(--x402-muted); text-align: center;
|
|
187
295
|
margin-top: 8px; line-height: 1.4;
|
|
188
296
|
}
|
|
189
297
|
.x402-siwx-fallback {
|
|
190
|
-
font-size: 12px; color:
|
|
298
|
+
font-size: 12px; color: var(--x402-warn-fg); line-height: 1.45;
|
|
191
299
|
padding: 8px 10px; border-radius: 8px;
|
|
192
|
-
background:
|
|
300
|
+
background: var(--x402-warn-bg); border: 1px solid var(--x402-warn-border);
|
|
193
301
|
margin-bottom: 6px;
|
|
194
302
|
}
|
|
195
303
|
|
|
196
304
|
.x402-error-box {
|
|
197
305
|
padding: 12px 14px; border-radius: 10px;
|
|
198
|
-
background:
|
|
199
|
-
font-size:
|
|
200
|
-
font-family: ui-monospace, "JetBrains Mono", Menlo, monospace;
|
|
306
|
+
background: var(--x402-error-bg); border: 1px solid var(--x402-error-border); color: var(--x402-error-fg);
|
|
307
|
+
font-size: 13.5px; line-height: 1.5;
|
|
201
308
|
word-break: break-word;
|
|
202
309
|
}
|
|
203
|
-
.x402-error-box
|
|
310
|
+
.x402-error-box .x402-error-title { font-weight: 700; margin-bottom: 2px; }
|
|
311
|
+
.x402-error-box .x402-error-detail { opacity: 0.85; font-size: 12.5px; }
|
|
204
312
|
|
|
205
313
|
.x402-receipt {
|
|
206
|
-
padding:
|
|
207
|
-
background:
|
|
208
|
-
border: 1px solid
|
|
314
|
+
padding: 16px; border-radius: var(--x402-radius-md);
|
|
315
|
+
background: var(--x402-success-bg);
|
|
316
|
+
border: 1px solid var(--x402-success-border);
|
|
317
|
+
animation: x402-pop 0.34s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
318
|
+
}
|
|
319
|
+
@keyframes x402-pop { from { opacity: 0; transform: scale(0.94); } to { opacity: 1; transform: scale(1); } }
|
|
320
|
+
.x402-receipt-check {
|
|
321
|
+
width: 40px; height: 40px; margin: 2px auto 10px;
|
|
322
|
+
border-radius: 50%; background: var(--x402-success);
|
|
323
|
+
display: flex; align-items: center; justify-content: center;
|
|
324
|
+
animation: x402-check-pop 0.4s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both;
|
|
209
325
|
}
|
|
326
|
+
.x402-receipt-check svg { width: 22px; height: 22px; color: #fff; }
|
|
327
|
+
.x402-receipt-check svg path { stroke-dasharray: 24; stroke-dashoffset: 24; animation: x402-draw 0.4s ease-out 0.22s forwards; }
|
|
328
|
+
@keyframes x402-check-pop { 0% { transform: scale(0); } 60% { transform: scale(1.12); } 100% { transform: scale(1); } }
|
|
329
|
+
@keyframes x402-draw { to { stroke-dashoffset: 0; } }
|
|
210
330
|
.x402-receipt-title {
|
|
211
|
-
font-size:
|
|
212
|
-
text-
|
|
213
|
-
margin-bottom: 8px;
|
|
214
|
-
display: flex; align-items: center; gap: 6px;
|
|
331
|
+
font-size: 15px; font-weight: 700; color: var(--x402-fg);
|
|
332
|
+
text-align: center; margin-bottom: 10px; letter-spacing: -0.01em;
|
|
215
333
|
}
|
|
216
|
-
.x402-receipt-title::before { content: '\u2713'; font-size: 14px; }
|
|
217
334
|
.x402-receipt-row {
|
|
218
335
|
display: flex; justify-content: space-between; gap: 12px;
|
|
219
|
-
font-size: 12px; padding:
|
|
220
|
-
font-family:
|
|
336
|
+
font-size: 12px; padding: 3px 0;
|
|
337
|
+
font-family: var(--x402-mono);
|
|
221
338
|
}
|
|
222
|
-
.x402-receipt-row .x402-k { color:
|
|
223
|
-
.x402-receipt-row .x402-v { color:
|
|
224
|
-
.x402-receipt-row a { color:
|
|
339
|
+
.x402-receipt-row .x402-k { color: var(--x402-muted); }
|
|
340
|
+
.x402-receipt-row .x402-v { color: var(--x402-fg); text-align: right; word-break: break-all; }
|
|
341
|
+
.x402-receipt-row a { color: var(--x402-link); text-decoration: none; }
|
|
225
342
|
.x402-receipt-row a:hover { text-decoration: underline; }
|
|
226
343
|
|
|
227
344
|
.x402-result {
|
|
228
345
|
padding: 12px 14px; border-radius: 10px;
|
|
229
|
-
background:
|
|
346
|
+
background: var(--x402-surface-2); border: 1px solid var(--x402-border);
|
|
230
347
|
max-height: 240px; overflow: auto;
|
|
231
|
-
font-family:
|
|
232
|
-
font-size: 12px; line-height: 1.5; color:
|
|
348
|
+
font-family: var(--x402-mono);
|
|
349
|
+
font-size: 12px; line-height: 1.5; color: var(--x402-fg);
|
|
233
350
|
white-space: pre-wrap; word-break: break-word;
|
|
234
351
|
}
|
|
352
|
+
.x402-result.x402-prose { font-family: var(--x402-font); font-size: 13.5px; line-height: 1.55; }
|
|
235
353
|
|
|
236
354
|
.x402-foot {
|
|
237
|
-
padding: 10px 20px 14px;
|
|
238
|
-
border-top: 1px solid
|
|
355
|
+
padding: 10px 20px max(14px, env(safe-area-inset-bottom));
|
|
356
|
+
border-top: 1px solid var(--x402-border);
|
|
239
357
|
display: flex; align-items: center; justify-content: space-between;
|
|
240
|
-
font-size: 11px; color:
|
|
358
|
+
font-size: 11px; color: var(--x402-muted);
|
|
241
359
|
}
|
|
242
|
-
.x402-foot a { color:
|
|
243
|
-
.x402-foot a:hover { color:
|
|
360
|
+
.x402-foot a { color: var(--x402-muted); text-decoration: none; font-weight: 600; }
|
|
361
|
+
.x402-foot a:hover { color: var(--x402-fg); }
|
|
244
362
|
.x402-foot .x402-secure { display: flex; align-items: center; gap: 5px; }
|
|
245
|
-
.x402-foot .x402-secure
|
|
363
|
+
.x402-foot .x402-secure svg { width: 11px; height: 11px; }
|
|
246
364
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
365
|
+
.x402-sr-only {
|
|
366
|
+
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
367
|
+
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
250
368
|
}
|
|
251
369
|
|
|
252
|
-
@media (
|
|
253
|
-
.x402-overlay {
|
|
254
|
-
.x402-modal {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
.x402-
|
|
261
|
-
.x402-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
.x402-
|
|
266
|
-
.x402-
|
|
267
|
-
.x402-
|
|
268
|
-
.x402-
|
|
269
|
-
.x402-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
.x402-siwx-hint { color: #8a90a8; }
|
|
274
|
-
.x402-siwx-fallback { background: #2a1d10; border-color: #78350f; color: #fcd34d; }
|
|
275
|
-
.x402-step-num { background: #161616; border-color: #2e2e2e; color: #8a90a8; }
|
|
276
|
-
.x402-result { background: #1d1d1d; border-color: #2e2e2e; color: #e6e8f0; }
|
|
277
|
-
.x402-receipt { background: linear-gradient(180deg, #0b1f17 0%, #161616 100%); border-color: #14532d; }
|
|
278
|
-
.x402-receipt-title { color: #4ade80; }
|
|
279
|
-
.x402-receipt-row .x402-k { color: #8a90a8; }
|
|
280
|
-
.x402-receipt-row .x402-v { color: #e6e8f0; }
|
|
281
|
-
.x402-receipt-row a { color: #60a5fa; }
|
|
282
|
-
.x402-error-box { background: #1f1416; border-color: #7f1d1d; color: #fca5a5; }
|
|
283
|
-
.x402-foot a { color: #b0b6cc; }
|
|
284
|
-
.x402-foot a:hover { color: #ffffff; }
|
|
285
|
-
}
|
|
286
|
-
`;function be(){if(document.getElementById(G))return;const n=document.createElement("style");n.id=G,n.textContent=me,document.head.appendChild(n)}class ye{constructor(e){this.opts=e,this.steps=[{id:"discover",label:"Confirming price"},{id:"connect",label:"Connect wallet"},{id:"authorize",label:"Authorize payment"},{id:"verify",label:"Verify & complete"}],this.activeNetwork=null,this.payerAddress=null,this.accept=null,this.challenge=null,this.disposed=!1,this.autoConnectTried=!1}mount(){be();const e=document.createElement("div");return e.className="x402-overlay",e.innerHTML=`
|
|
287
|
-
<div class="x402-modal" role="dialog" aria-modal="true" aria-label="x402 payment">
|
|
370
|
+
@media (max-width: 520px) {
|
|
371
|
+
.x402-overlay { align-items: flex-end; }
|
|
372
|
+
.x402-modal {
|
|
373
|
+
max-width: none; width: 100%;
|
|
374
|
+
border-radius: var(--x402-radius) var(--x402-radius) 0 0;
|
|
375
|
+
max-height: 92dvh;
|
|
376
|
+
transform: translateY(100%);
|
|
377
|
+
}
|
|
378
|
+
.x402-overlay.x402-open .x402-modal { transform: translateY(0); }
|
|
379
|
+
.x402-price { font-size: 28px; }
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@media (prefers-reduced-motion: reduce) {
|
|
383
|
+
.x402-overlay, .x402-modal, .x402-body > *,
|
|
384
|
+
.x402-receipt, .x402-receipt-check, .x402-receipt-check svg path { animation: none !important; transition: none !important; }
|
|
385
|
+
.x402-step.x402-active .x402-step-num { animation: none; }
|
|
386
|
+
.x402-network::before { animation: none; }
|
|
387
|
+
.x402-receipt-check svg path { stroke-dashoffset: 0; }
|
|
388
|
+
}
|
|
389
|
+
`,m={close:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>',lock:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="5" y="11" width="14" height="9" rx="2"/><path d="M8 11V8a4 4 0 0 1 8 0v3"/></svg>',check:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 13l4 4L19 7"/></svg>',shield:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l7 3v6c0 4.5-3 7.4-7 9-4-1.6-7-4.5-7-9V6z"/><path d="M9 12l2 2 4-4"/></svg>',phantom:'<svg viewBox="0 0 24 24" aria-hidden="true"><rect width="24" height="24" rx="6" fill="#ab9ff2"/><path fill="#fff" d="M19 12.4c0 3.8-3.1 6.8-7 6.8-.6 0-1-.6-.7-1.1.2-.4 0-.9-.4-1.1-.4-.2-1 0-1.3.4-.5.7-1.3 1.1-2.2 1.1H6.7c-1.2 0-2.2-1-2.2-2.2v-1.7c0-4.1 3.4-7.4 7.5-7.4h-.1c3.9 0 7.1 2.6 7.1 5.9z"/><circle cx="9.4" cy="12.4" r="1" fill="#534bb1"/><circle cx="12.6" cy="12.4" r="1" fill="#534bb1"/></svg>',wallet:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="6" width="18" height="13" rx="2.5"/><path d="M3 10h18"/><circle cx="16.5" cy="14" r="1.3" fill="currentColor" stroke="none"/></svg>'},Te={discover:"Couldn't confirm the price",connect:"Couldn't connect your wallet",authorize:"Payment couldn't be authorized",verify:"Payment couldn't be completed"};function Pe(){if(typeof window>"u")return[];const n=[],e=new Set,t=(r,o,s)=>{!o||typeof o.signTransaction!="function"||e.has(o)||(e.add(o),n.push({kind:"solana",name:r,provider:o,icon:s||m.wallet}))};return t("Phantom",window.phantom?.solana||(window.solana?.isPhantom?window.solana:null),m.phantom),t("Solflare",window.solflare?.isSolflare?window.solflare:null,m.wallet),t("Backpack",window.backpack?.isBackpack?window.backpack:null,m.wallet),t("Glow",window.glowSolana||window.glow||null,m.wallet),t("Coinbase Wallet",window.coinbaseSolana||null,m.wallet),window.solana&&!window.solana.isPhantom&&t(window.solana.isSolflare?"Solflare":"Solana wallet",window.solana,m.wallet),n}function Be(){if(typeof window>"u"||typeof window.dispatchEvent!="function")return[];const n=[],e=new Set,t=(s,a,i)=>{!a||e.has(a)||(e.add(a),n.push({kind:"evm",name:s||"Browser wallet",provider:a,icon:i||m.wallet}))},r=[],o=s=>{s?.detail&&r.push(s.detail)};window.addEventListener("eip6963:announceProvider",o);try{window.dispatchEvent(new Event("eip6963:requestProvider"))}catch{}window.removeEventListener("eip6963:announceProvider",o);for(const s of r)t(s.info?.name,s.provider,s.info?.icon);if(!n.length){const s=window.ethereum,a=i=>i?.isMetaMask?"MetaMask":i?.isCoinbaseWallet?"Coinbase Wallet":"Browser wallet";if(Array.isArray(s?.providers))for(const i of s.providers)t(a(i),i);else s&&t(a(s),s)}return n}function re(n){return n&&/^(data:|https?:)/.test(n)?`<img src="${u(n)}" alt="" />`:n||m.wallet}function Ne(){if(document.getElementById(te))return;const n=document.createElement("style");n.id=te,n.textContent=Ce,document.head.appendChild(n)}class Ie{constructor(e){this.opts=e,this.steps=[{id:"discover",label:"Confirming price"},{id:"connect",label:"Connect wallet"},{id:"authorize",label:"Authorize payment"},{id:"verify",label:"Verify & complete"}],this.activeNetwork=null,this.payerAddress=null,this.accept=null,this.challenge=null,this.disposed=!1,this.autoConnectTried=!1}mount(){Ne();const e=document.createElement("div");if(e.className="x402-overlay",p.theme==="dark"?e.classList.add("x402-theme-dark"):p.theme==="light"&&e.classList.add("x402-theme-light"),p.cssVars&&typeof p.cssVars=="object")for(const[r,o]of Object.entries(p.cssVars))/^--x402-[a-z0-9-]+$/i.test(r)&&e.style.setProperty(r,String(o));const t=p.brand?.logo?`<img class="x402-brand-logo" src="${u(p.brand.logo)}" alt="" />`:"";return e.innerHTML=`
|
|
390
|
+
<div class="x402-modal" role="dialog" aria-modal="true" aria-labelledby="x402-act" aria-describedby="x402-price">
|
|
288
391
|
<div class="x402-head">
|
|
289
392
|
<div class="x402-merchant">
|
|
290
|
-
|
|
291
|
-
<div class="x402-
|
|
393
|
+
${t}
|
|
394
|
+
<div class="x402-merchant-text">
|
|
395
|
+
<div class="x402-name" data-merchant>${u(this.opts.merchant||"Payment")}</div>
|
|
396
|
+
<div class="x402-action" id="x402-act" data-action>${u(this.opts.action||"Pay-per-call")}</div>
|
|
397
|
+
</div>
|
|
292
398
|
</div>
|
|
293
|
-
<button class="x402-close" data-close aria-label="Close"
|
|
399
|
+
<button class="x402-close" data-close aria-label="Close payment">${m.close}</button>
|
|
294
400
|
</div>
|
|
295
401
|
<div class="x402-price-row">
|
|
296
|
-
<div class="x402-price
|
|
402
|
+
<div class="x402-price-main">
|
|
403
|
+
<div class="x402-price" id="x402-price" data-price>\u2014<span class="x402-currency"> USDC</span></div>
|
|
404
|
+
<div class="x402-price-sub" data-price-sub></div>
|
|
405
|
+
</div>
|
|
297
406
|
<div class="x402-network" data-network>resolving\u2026</div>
|
|
298
407
|
</div>
|
|
299
|
-
<div class="x402-body" data-body></div>
|
|
408
|
+
<div class="x402-body" data-body aria-live="polite"></div>
|
|
300
409
|
<div class="x402-foot">
|
|
301
|
-
<span class="x402-secure">${
|
|
302
|
-
${
|
|
410
|
+
<span class="x402-secure">${m.lock}${u(p.footerNote)}</span>
|
|
411
|
+
${p.brand?.name?`<a href="${u(p.brand.url||"#")}" target="_blank" rel="noopener">Powered by ${u(p.brand.name)}</a>`:""}
|
|
303
412
|
</div>
|
|
304
413
|
</div>
|
|
305
|
-
`,document.body.appendChild(e),this.overlay=e,this.bodyEl=e.querySelector("[data-body]"),this.priceEl=e.querySelector("[data-price]"),this.networkEl=e.querySelector("[data-network]"),e.querySelector("[data-close]").addEventListener("click",()=>this.close("cancelled")),e.addEventListener("click",
|
|
414
|
+
`,document.body.appendChild(e),this.overlay=e,this.bodyEl=e.querySelector("[data-body]"),this.priceEl=e.querySelector("[data-price]"),this.priceSubEl=e.querySelector("[data-price-sub]"),this.networkEl=e.querySelector("[data-network]"),e.querySelector("[data-close]").addEventListener("click",()=>this.close("cancelled")),e.addEventListener("click",r=>{r.target===e&&this.close("cancelled")}),this.previouslyFocused=typeof document<"u"?document.activeElement:null,this.onKey=r=>{if(r.key==="Escape"){this.close("cancelled");return}r.key==="Tab"&&this.trapTab(r)},document.addEventListener("keydown",this.onKey),requestAnimationFrame(()=>{e.classList.add("x402-open"),this.focusFirst()}),new Promise((r,o)=>{this.resolve=r,this.reject=o})}focusables(){return this.overlay?Array.from(this.overlay.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])')).filter(t=>t.offsetParent!==null):[]}focusFirst(){const e=this.focusables();(e.find(t=>!t.hasAttribute("data-close"))||e[0])?.focus?.()}trapTab(e){const t=this.focusables();if(!t.length)return;const r=t[0],o=t[t.length-1];e.shiftKey&&document.activeElement===r?(e.preventDefault(),o.focus()):!e.shiftKey&&document.activeElement===o&&(e.preventDefault(),r.focus())}close(e){if(!this.disposed&&(this.disposed=!0,document.removeEventListener("keydown",this.onKey),this.overlay.classList.remove("x402-open"),setTimeout(()=>this.overlay.remove(),180),this.previouslyFocused?.focus?.(),e==="cancelled"&&this.reject)){const t=new Error("cancelled");t.code="cancelled",this.reject(t)}}renderSteps(e,t={}){return this.steps.map(o=>{const s=t[o.id]||(o.id===e?"active":"idle"),a=s==="active"?"x402-active":s==="done"?"x402-done":s==="error"?"x402-error":"",i=t[`${o.id}_meta`]||"",l=s==="done"?"\u2713":s==="error"?"!":o.id===e&&s==="active"?" ":this.steps.findIndex(c=>c.id===o.id)+1;return`<div class="x402-step ${a}">
|
|
306
415
|
<div class="x402-step-num">${l}</div>
|
|
307
416
|
<div class="x402-step-body">
|
|
308
417
|
<div class="x402-step-label">${o.label}</div>
|
|
309
|
-
${
|
|
418
|
+
${i?`<div class="x402-step-meta">${u(i)}</div>`:""}
|
|
310
419
|
</div>
|
|
311
|
-
</div>`}).join("")}setPrice(e){const t=
|
|
312
|
-
${
|
|
313
|
-
<span class="x402-token-sym">${
|
|
314
|
-
<span class="x402-token-amt">${
|
|
420
|
+
</div>`}).join("")}setPrice(e){const t=k(e),r=C(e.amount,t.decimals),o=t.glyph?`${t.glyph} `:"";this.priceEl.innerHTML=`${r}<span class="x402-currency"> ${o}${u(t.symbol)}</span>`,this.networkEl.textContent=v(e.network,e)}renderConnect(){const e=Pe(),t=Be();this._solWallets=e,this._evmWallets=t;const r=e.length>0,o=t.length>0,s=F(this.challenge);let a=s.find(x=>x===this.solanaAccept)||V(s);this.solanaAccept=a;const i=this.challenge?.accepts.find(K);if(this.siwx&&!this.payFlowOverride){const x=r?Z(this.siwx,"solana"):null,d=o?Z(this.siwx,"evm"):null;if(x||d){this.renderSiwxChoice({siwxSolana:x,siwxEvm:d});return}}if(this.opts.autoConnect&&!this.autoConnectTried&&!this.siwxFallbackNotice){this.autoConnectTried=!0;const x=a&&e.length===1,d=i&&t.length===1;if(x&&!d){this.runSolana(a,e[0].provider);return}if(d&&!x){this.runEvm(i,t[0].provider);return}}const l=s.length>1?`<div class="x402-token-row" role="group" aria-label="Choose payment token">
|
|
421
|
+
${s.map(x=>{const d=k(x),f=x===a,b=C(x.amount,d.decimals);return`<button type="button" class="x402-token-pill${f?" x402-on":""}" data-token-asset="${u(x.asset)}" aria-pressed="${f}"${d.accent&&f?` style="border-color:${u(d.accent)}"`:""}>
|
|
422
|
+
<span class="x402-token-sym">${d.glyph?u(d.glyph)+" ":""}${u(d.symbol)}</span>
|
|
423
|
+
<span class="x402-token-amt">${b}</span>
|
|
315
424
|
</button>`}).join("")}
|
|
316
|
-
</div>`:"",
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
425
|
+
</div>`:"",c=[];if(a){const x=k(a),d=s.length>1?`${v(a.network,a)} \xB7 ${x.symbol}`:v(a.network,a);e.length?e.forEach((f,b)=>c.push(`
|
|
426
|
+
<button class="x402-wallet-btn" data-wallet-kind="solana" data-wallet-idx="${b}">
|
|
427
|
+
<div class="x402-wallet-icon">${re(f.icon)}</div>
|
|
428
|
+
<span class="x402-wallet-name">${u(f.name)}</span>
|
|
429
|
+
<span class="x402-wallet-meta"${b===0?" data-sol-meta":""}>${u(d)}</span>
|
|
430
|
+
</button>
|
|
431
|
+
`)):c.push(`
|
|
432
|
+
<button class="x402-wallet-btn" disabled>
|
|
433
|
+
<div class="x402-wallet-icon">${m.phantom}</div>
|
|
434
|
+
<span class="x402-wallet-name">No Solana wallet detected</span>
|
|
435
|
+
<span class="x402-wallet-meta">${u(d)}</span>
|
|
436
|
+
</button>
|
|
437
|
+
`)}i&&(t.length?t.forEach((x,d)=>c.push(`
|
|
438
|
+
<button class="x402-wallet-btn" data-wallet-kind="evm" data-wallet-idx="${d}">
|
|
439
|
+
<div class="x402-wallet-icon">${re(x.icon)}</div>
|
|
440
|
+
<span class="x402-wallet-name">${u(x.name)}</span>
|
|
441
|
+
<span class="x402-wallet-meta">${u(v(i.network,i))}</span>
|
|
442
|
+
</button>
|
|
443
|
+
`)):c.push(`
|
|
444
|
+
<button class="x402-wallet-btn" disabled>
|
|
445
|
+
<div class="x402-wallet-icon">${m.wallet}</div>
|
|
446
|
+
<span class="x402-wallet-name">No EVM wallet detected</span>
|
|
447
|
+
<span class="x402-wallet-meta">${u(v(i.network,i))}</span>
|
|
448
|
+
</button>
|
|
449
|
+
`));const w=!r&&!o?`<div class="x402-wallet-install">No wallet detected \u2014 install
|
|
450
|
+
${a?'<a href="https://phantom.app/download" target="_blank" rel="noopener">Phantom</a>':""}${a&&i?" or ":""}${i?'<a href="https://metamask.io/download" target="_blank" rel="noopener">MetaMask</a>':""}
|
|
451
|
+
to continue.</div>`:"",h=this.siwxFallbackNotice?`<div class="x402-siwx-fallback">${u(this.siwxFallbackNotice)}</div>`:"",y=k(this.accept),$=C(this.accept.amount,y.decimals),S=`<div class="x402-trust">${m.shield}<span>You authorize exactly ${u($)} ${u(y.symbol)} \u2014 nothing more can be charged.</span></div>`;this.bodyEl.innerHTML=`
|
|
329
452
|
${this.renderSteps("connect",{discover:"done"})}
|
|
453
|
+
${h}
|
|
330
454
|
${l}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
455
|
+
<div class="x402-wallet-buttons">${c.join("")}</div>
|
|
456
|
+
${w}
|
|
457
|
+
${r||o?S:""}
|
|
458
|
+
`,requestAnimationFrame(()=>this.focusFirst());const A=x=>{const d=x.target.closest("[data-wallet-kind]");if(!d||d.disabled)return;const f=d.dataset.walletKind,b=Number(d.dataset.walletIdx);f==="solana"?this.runSolana(this.solanaAccept,this._solWallets[b]?.provider):f==="evm"&&this.runEvm(i,this._evmWallets[b]?.provider)};this.bodyEl.querySelectorAll("[data-wallet-kind]").forEach(x=>x.addEventListener("click",A)),this.bodyEl.querySelectorAll("[data-token-asset]").forEach(x=>{x.addEventListener("click",()=>{const d=s.find(g=>g.asset===x.dataset.tokenAsset);if(!d||d===this.solanaAccept)return;this.solanaAccept=d,this.accept=d,this.setPrice(d);const f=k(d),b=this.bodyEl.querySelector("[data-sol-meta]");b&&(b.textContent=`${v(d.network,d)} \xB7 ${f.symbol}`),this.bodyEl.querySelectorAll("[data-token-asset]").forEach(g=>{const T=g===x;g.classList.toggle("x402-on",T),g.setAttribute("aria-pressed",String(T)),g.style.borderColor=T&&f.accent?f.accent:""})})})}renderSiwxChoice({siwxSolana:e,siwxEvm:t}){const r=k(this.accept),o=C(this.accept.amount,r.decimals),s=e?{kind:"solana",chain:e.chain}:{kind:"evm",chain:t.chain},a=s.kind==="solana"?"Sign in with Phantom":"Sign in with wallet";this.bodyEl.innerHTML=`
|
|
334
459
|
${this.renderSteps("connect",{discover:"done"})}
|
|
335
|
-
<button class="x402-pay-btn" data-action="siwx">${
|
|
336
|
-
<button class="x402-pay-secondary" data-action="pay">Pay ${o} ${
|
|
460
|
+
<button class="x402-pay-btn" data-action="siwx">${a}</button>
|
|
461
|
+
<button class="x402-pay-secondary" data-action="pay">Pay ${o} ${u(r.symbol)} instead</button>
|
|
337
462
|
<div class="x402-siwx-hint">Already paid for this once? Sign in to re-enter without paying again.</div>
|
|
338
|
-
`;const
|
|
463
|
+
`;const i=this.bodyEl.querySelector('[data-action="siwx"]'),l=this.bodyEl.querySelector('[data-action="pay"]');i.addEventListener("click",()=>{s.kind==="solana"?this.runSiwxSolana(s.chain):this.runSiwxEvm(s.chain)}),l.addEventListener("click",()=>{this.payFlowOverride=!0,this.renderConnect()}),requestAnimationFrame(()=>i.focus())}renderProgress(e,t={}){this.bodyEl.innerHTML=this.renderSteps(e,{discover:"done",connect:"done",...e==="verify"?{authorize:"done"}:{},[`${e}_meta`]:t.text||"",...t.statuses})}renderError(e,t){this.bodyEl.innerHTML=`
|
|
339
464
|
${this.renderSteps(e,{...e!=="discover"?{discover:"done"}:{},...e==="authorize"||e==="verify"?{connect:"done"}:{},...e==="verify"?{authorize:"done"}:{},[e]:"error",[`${e}_meta`]:"failed"})}
|
|
340
|
-
<div class="x402-error-box"
|
|
465
|
+
<div class="x402-error-box">
|
|
466
|
+
<div class="x402-error-title">${u(Te[e]||"Something went wrong")}</div>
|
|
467
|
+
<div class="x402-error-detail">${u(t)}</div>
|
|
468
|
+
</div>
|
|
341
469
|
<button class="x402-pay-btn" data-retry>Try again</button>
|
|
342
|
-
|
|
470
|
+
`;const r=this.bodyEl.querySelector("[data-retry]");r.addEventListener("click",()=>this.start()),requestAnimationFrame(()=>r.focus())}renderDone({result:e,payment:t,siwx:r}){const o=typeof e=="string"?e:JSON.stringify(e,null,2);let s;if(r){const l=r.address?`${r.address.slice(0,8)}\u2026${r.address.slice(-6)}`:"\u2014";s=`
|
|
343
471
|
<div class="x402-receipt">
|
|
344
|
-
<div class="x402-receipt-
|
|
472
|
+
<div class="x402-receipt-check">${m.check}</div>
|
|
473
|
+
<div class="x402-receipt-title">Welcome back</div>
|
|
345
474
|
<div class="x402-receipt-row">
|
|
346
475
|
<span class="x402-k">network</span>
|
|
347
|
-
<span class="x402-v">${
|
|
476
|
+
<span class="x402-v">${u(v(r.network)||r.network||"\u2014")}</span>
|
|
348
477
|
</div>
|
|
349
478
|
<div class="x402-receipt-row">
|
|
350
479
|
<span class="x402-k">wallet</span>
|
|
351
|
-
<span class="x402-v">${
|
|
480
|
+
<span class="x402-v">${u(l)}</span>
|
|
352
481
|
</div>
|
|
353
482
|
<div class="x402-receipt-row">
|
|
354
483
|
<span class="x402-k">paid</span>
|
|
355
484
|
<span class="x402-v">previously \xB7 re-entered free</span>
|
|
356
485
|
</div>
|
|
357
486
|
</div>
|
|
358
|
-
`}else{const
|
|
487
|
+
`}else{const l=me(t?.network,t?.transaction),c=t?.transaction?`${t.transaction.slice(0,8)}\u2026${t.transaction.slice(-6)}`:"\u2014";s=`
|
|
359
488
|
<div class="x402-receipt">
|
|
360
|
-
<div class="x402-receipt-
|
|
489
|
+
<div class="x402-receipt-check">${m.check}</div>
|
|
490
|
+
<div class="x402-receipt-title">Payment confirmed</div>
|
|
361
491
|
<div class="x402-receipt-row">
|
|
362
492
|
<span class="x402-k">network</span>
|
|
363
|
-
<span class="x402-v">${
|
|
493
|
+
<span class="x402-v">${u(v(t?.network)||"\u2014")}</span>
|
|
364
494
|
</div>
|
|
365
495
|
<div class="x402-receipt-row">
|
|
366
496
|
<span class="x402-k">payer</span>
|
|
367
|
-
<span class="x402-v">${
|
|
497
|
+
<span class="x402-v">${u(t?.payer?`${t.payer.slice(0,8)}\u2026${t.payer.slice(-6)}`:"\u2014")}</span>
|
|
368
498
|
</div>
|
|
369
|
-
${t?.transaction?`<div class="x402-receipt-row"><span class="x402-k">tx</span><span class="x402-v">${
|
|
499
|
+
${t?.transaction?`<div class="x402-receipt-row"><span class="x402-k">tx</span><span class="x402-v">${l?`<a href="${l}" target="_blank" rel="noopener">${c} \u2197</a>`:c}</span></div>`:""}
|
|
370
500
|
</div>
|
|
371
|
-
`}this.bodyEl.innerHTML=`
|
|
501
|
+
`}const a=typeof e=="string";this.bodyEl.innerHTML=`
|
|
372
502
|
${s}
|
|
373
|
-
<div class="x402-result">${
|
|
503
|
+
<div class="x402-result${a?" x402-prose":""}">${u(o).slice(0,4e3)}</div>
|
|
374
504
|
<button class="x402-pay-btn" data-done>Done</button>
|
|
375
|
-
`,this.bodyEl.querySelector("[data-done]").addEventListener("click",()=>{this.disposed=!0,document.removeEventListener("keydown",this.onKey),this.overlay.classList.remove("x402-open"),setTimeout(()=>this.overlay.remove(),180)})}async start(){this.bodyEl.innerHTML=this.renderSteps("discover");try{const e=await $e(this.opts);this.challenge=e,this.siwx=fe(e),this.payFlowOverride=!1,this.siwxFallbackNotice=null;const t=q(e),r=R(t);this.solanaAccept=r;const o=e.accepts.find(D),s=typeof window<"u"&&(window.solana?.isPhantom||window.phantom?.solana);this.accept=s&&r||o||e.accepts[0],this.setPrice(this.accept),this.renderConnect()}catch(e){this.renderError("discover",e.message||String(e))}}async runSolana(e){this.accept=e,this.setPrice(e),this.renderProgress("connect",{text:"Opening Phantom\u2026"});try{const t=window.phantom?.solana||window.solana;if(!t)throw new Error("Phantom wallet not detected");const o=((await t.connect())?.publicKey||t.publicKey)?.toString();if(!o)throw new Error("Phantom did not return a public key");this.payerAddress=o;const s=F({accept:e,caps:this.opts.caps,address:o});if(s.abort){this.renderError("authorize",s.reason);return}this.spendReservation=s.reservation||null,this.renderProgress("authorize",{text:`Building Solana payment for ${o.slice(0,6)}\u2026${o.slice(-4)}`});const i=await X(`${L()}?action=prepare`,{accept:e,buyer:o});this.renderProgress("authorize",{text:"Confirm in Phantom\u2026"});const a=ve(i.tx_base64),d=(await Ee()).VersionedTransaction.deserialize(a),u=await t.signTransaction(d),c=ke(u.serialize()),p=W(this.challenge),x=await X(`${L()}?action=encode`,{accept:e,signed_tx_base64:c,resource_url:new URL(this.opts.endpoint,location.href).href,...p?{builder_code:p}:{}});await this.executePaid(x.x_payment)}catch(t){this.spendReservation&&(z(this.spendReservation),this.spendReservation=null),this.renderError(this.payerAddress?"authorize":"connect",g(t))}}async runEvm(e){this.accept=e,this.setPrice(e),this.renderProgress("connect",{text:"Opening browser wallet\u2026"});try{const t=window.ethereum;if(!t)throw new Error("No EVM wallet detected");const o=(await t.request({method:"eth_requestAccounts"}))?.[0];if(!o)throw new Error("Wallet did not return an account");this.payerAddress=o;const s=F({accept:e,caps:this.opts.caps,address:o});if(s.abort){this.renderError("authorize",s.reason);return}this.spendReservation=s.reservation||null;const i=C[e.network];if(!i)throw new Error(`Unknown EVM network ${e.network}`);const a=await t.request({method:"eth_chainId"}),l="0x"+i.chainId.toString(16);if(a!==l){this.renderProgress("connect",{text:`Switch wallet to ${i.name}\u2026`});try{await t.request({method:"wallet_switchEthereumChain",params:[{chainId:l}]})}catch{throw new Error(`Wallet is on ${a}; please switch to ${i.name} (${l}) and retry`)}}this.renderProgress("authorize",{text:`Authorize ${v(e.amount)} USDC\u2026`});const d=0,u=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||600),c="0x"+Se(32),p={name:e.extra?.name||"USD Coin",version:e.extra?.version||"2",chainId:i.chainId,verifyingContract:e.asset},x={EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}],TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},m={from:o,to:e.payTo,value:e.amount,validAfter:d,validBefore:u,nonce:c},w={primaryType:"TransferWithAuthorization",types:x,domain:p,message:m},Q=await t.request({method:"eth_signTypedData_v4",params:[o,JSON.stringify(w)]}),O={x402Version:2,scheme:"exact",network:e.network,resource:{url:this.opts.endpoint,mimeType:"application/json"},accepted:e,payload:{signature:Q,authorization:{from:o,to:e.payTo,value:e.amount,validAfter:String(d),validBefore:String(u),nonce:c}}},M=W(this.challenge);M&&(O.extensions={"builder-code":M});const ee=ie(O);await this.executePaid(ee)}catch(t){this.spendReservation&&(z(this.spendReservation),this.spendReservation=null),this.renderError(this.payerAddress?"authorize":"connect",g(t))}}async executePaid(e,t=0){this.renderProgress("verify",{text:t?"Retrying after upstream throttle\u2026":"Calling merchant endpoint\u2026"});try{const r=await fetch(this.opts.endpoint,{method:this.opts.method||"GET",headers:{...this.opts.headers||{},...this.opts.body&&!this.opts.headers?.["content-type"]?{"content-type":"application/json"}:{},"X-PAYMENT":e},body:this.opts.body?typeof this.opts.body=="string"?this.opts.body:JSON.stringify(this.opts.body):void 0}),o=r.headers.get("content-type")||"",s=await r.text();let i;if(o.includes("json"))try{i=JSON.parse(s)}catch{i=s}else i=s;if(!r.ok){if(r.status===429&&t<ge)return await this.waitForThrottle(we(r,i)),this.executePaid(e,t+1);const d=i&&typeof i=="object"&&(i.error_description||i.error)||`HTTP ${r.status}`;throw new Error(d)}const a=r.headers.get("x-payment-response"),l=I(a)||{};this.spendReservation=null,this.renderDone({result:i,payment:l}),this.resolve?.({ok:!0,result:i,payment:l,response:{status:r.status,headers:Y(r.headers)}})}catch(r){this.spendReservation&&(z(this.spendReservation),this.spendReservation=null),this.renderError("verify",g(r))}}async waitForThrottle(e){const t=Math.max(1,Math.min(30,Math.round(e)||6));for(let r=t;r>0;r--)this.renderProgress("verify",{text:`Generator is busy \u2014 retrying in ${r}s\u2026`}),await new Promise(o=>setTimeout(o,1e3));this.renderProgress("verify",{text:"Retrying\u2026"})}async runSiwxEvm(e){this.renderProgress("connect",{text:"Opening browser wallet\u2026"});try{const t=window.ethereum;if(!t)throw new Error("No EVM wallet detected");const o=(await t.request({method:"eth_requestAccounts"}))?.[0];if(!o)throw new Error("Wallet did not return an account");const i=(await xe())(o);this.payerAddress=i,this.renderProgress("authorize",{text:`Sign sign-in message as ${i.slice(0,6)}\u2026${i.slice(-4)}`});const a=V(this.siwx.info,e,i),l=await t.request({method:"personal_sign",params:[a,i]}),d=this.siwx.info,u={domain:d.domain,address:i,...d.statement?{statement:d.statement}:{},uri:d.uri,version:d.version||"1",chainId:e.chainId,type:"eip191",nonce:d.nonce,issuedAt:d.issuedAt,...d.expirationTime?{expirationTime:d.expirationTime}:{},...d.notBefore?{notBefore:d.notBefore}:{},...d.requestId!==void 0&&d.requestId!==null?{requestId:d.requestId}:{},...Array.isArray(d.resources)?{resources:d.resources}:{},signatureScheme:"eip191",signature:l};await this.executeSiwx(u,e.chainId)}catch(t){this.renderError(this.payerAddress?"authorize":"connect",g(t))}}async runSiwxSolana(e){this.renderProgress("connect",{text:"Opening Phantom\u2026"});try{const t=window.phantom?.solana||window.solana;if(!t)throw new Error("Phantom wallet not detected");const s=((await t.connect())?.publicKey||t.publicKey)?.toString();if(!s)throw new Error("Phantom did not return a public key");this.payerAddress=s,this.renderProgress("authorize",{text:`Sign sign-in message as ${s.slice(0,6)}\u2026${s.slice(-4)}`});const i=V(this.siwx.info,e,s),a=new TextEncoder().encode(i),l=await t.signMessage(a,"utf8"),d=l?.signature instanceof Uint8Array?l.signature:new Uint8Array(l?.signature||l);if(!d||!d.length)throw new Error("Phantom did not return a signature");const u=he(d),c=this.siwx.info,p={domain:c.domain,address:s,...c.statement?{statement:c.statement}:{},uri:c.uri,version:c.version||"1",chainId:e.chainId,type:"ed25519",nonce:c.nonce,issuedAt:c.issuedAt,...c.expirationTime?{expirationTime:c.expirationTime}:{},...c.notBefore?{notBefore:c.notBefore}:{},...c.requestId!==void 0&&c.requestId!==null?{requestId:c.requestId}:{},...Array.isArray(c.resources)?{resources:c.resources}:{},signatureScheme:"siws",signature:u};await this.executeSiwx(p,e.chainId)}catch(t){this.renderError(this.payerAddress?"authorize":"connect",g(t))}}async executeSiwx(e,t){this.renderProgress("verify",{text:"Verifying sign-in\u2026"});const r=pe(e);let o;try{o=await fetch(this.opts.endpoint,{method:this.opts.method||"GET",headers:{...this.opts.headers||{},...this.opts.body&&!this.opts.headers?.["content-type"]?{"content-type":"application/json"}:{},[ne]:r},body:this.opts.body?typeof this.opts.body=="string"?this.opts.body:JSON.stringify(this.opts.body):void 0})}catch(i){this.renderError("verify",g(i));return}if(o.status===200){const i=o.headers.get("content-type")||"",a=await o.text();let l;if(i.includes("json"))try{l=JSON.parse(a)}catch{l=a}else l=a;const d={address:e.address,network:t};this.renderDone({result:l,siwx:d}),this.resolve?.({ok:!0,result:l,siwx:d,response:{status:o.status,headers:Y(o.headers)}});return}if(o.status===401||o.status===402){let i=null;try{i=await o.clone().json()}catch{}const a=i?.code||i?.error;this.siwx=null,this.payerAddress=null,this.payFlowOverride=!1,this.siwxFallbackNotice=a==="siwx_not_paid"||o.status===402?"You haven't paid for this yet \u2014 pay now to unlock re-entry.":"Sign-in not accepted \u2014 please pay to continue.",!this.challenge||!Array.isArray(this.challenge.accepts)||!this.challenge.accepts.length?this.start():this.renderConnect();return}const s=await o.text().catch(()=>"");this.renderError("verify",`SIWX retry failed: HTTP ${o.status}${s?` \xB7 ${s.slice(0,120)}`:""}`)}}function f(n){return String(n??"").replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function Y(n){const e={};return n.forEach((t,r)=>e[r]=t),e}const ge=2;function we(n,e,t=6){const r=Number.parseInt(n.headers.get("retry-after")||"",10);if(Number.isFinite(r)&&r>0)return r;const o=e&&typeof e=="object"?Number(e.retry_after):NaN;return Number.isFinite(o)&&o>0?o:t}function g(n){const e=n?.shortMessage||n?.message||String(n);return/user rejected|user denied|reject/i.test(e)?"cancelled in wallet":/throttl|rate.?limit|too many requests|less than \$|in credit|\b429\b/i.test(e)?"The service is briefly busy and your payment was not taken \u2014 retry in a few seconds.":/dynamically imported module|esm\.sh|module script failed/i.test(e)?"A component this wallet path needs (loaded from esm.sh) was blocked \u2014 often by a strict host security policy. Pay with MetaMask on Base instead; it needs no third-party code.":e.slice(0,240)}function ve(n){if(typeof Buffer<"u")return new Uint8Array(Buffer.from(n,"base64"));const e=atob(n),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}function ke(n){if(typeof Buffer<"u")return Buffer.from(n).toString("base64");let e="";for(let t=0;t<n.length;t++)e+=String.fromCharCode(n[t]);return btoa(e)}function Se(n){const e=new Uint8Array(n);return crypto.getRandomValues(e),Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}let $=null;async function Ee(){return $||($=await import(h.esm.solanaWeb3),$)}async function X(n,e){const t=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),r=await t.text();let o;try{o=JSON.parse(r)}catch{o={error:"parse_error",error_description:r.slice(0,200)}}if(!t.ok){const s=new Error(o.error_description||o.error||`HTTP ${t.status}`);throw s.status=t.status,s.data=o,s}return o}async function $e(n){const e={...n.headers||{}},t={method:n.method||"GET",headers:e,body:n.body?typeof n.body=="string"?n.body:JSON.stringify(n.body):void 0};t.body&&!e["content-type"]&&(e["content-type"]="application/json");const r=await fetch(n.endpoint,t),o=r.headers.get("payment-required"),s=r.status===401&&!!o;if(r.status!==402&&!s){const a=await r.text();throw new Error(`Endpoint did not return 402 (got ${r.status}). Body: ${a.slice(0,120)}`)}let i=s?I(o):await r.json().catch(()=>null);if(!i||!Array.isArray(i.accepts)||!i.accepts.length){const a=I(o);a&&Array.isArray(a.accepts)&&a.accepts.length&&(i=a)}if(!i||!Array.isArray(i.accepts)||!i.accepts.length)throw new Error("Endpoint returned 402 but no `accepts` array could be found in body or header");return i}async function Z(n){if(!n?.endpoint)throw new Error("X402.pay: endpoint is required");const e=new ye(n),t=e.mount();return queueMicrotask(()=>e.start()),t}function Ae(n){n.dataset.x402Bound!=="1"&&(n.dataset.x402Bound="1",n.addEventListener("click",async e=>{e.preventDefault();const t=Ce(n);try{const r=await Z(t);r?.siwx&&n.dispatchEvent(new CustomEvent("x402:siwx-signed",{detail:r.siwx,bubbles:!0})),n.dispatchEvent(new CustomEvent("x402:result",{detail:r,bubbles:!0}))}catch(r){if(r?.code==="cancelled")return;n.dispatchEvent(new CustomEvent("x402:error",{detail:{error:r?.message||String(r)},bubbles:!0}))}}))}function Ce(n){const e=n.dataset;let t=e.x402Body;if(t)try{t=JSON.parse(t)}catch{}let r=e.x402Headers;if(r)try{r=JSON.parse(r)}catch{r=void 0}return{endpoint:e.x402Endpoint,method:e.x402Method||(t?"POST":"GET"),body:t,headers:r,merchant:e.x402Merchant,action:e.x402Action||n.textContent?.trim().slice(0,60)}}function A(){document.querySelectorAll("[data-x402-endpoint]").forEach(Ae)}function Te(){try{const e=(document.currentScript||document.querySelector('script[src*="x402"][type="module"]')||document.querySelector("script[data-x402-checkout-origin]"))?.dataset;if(!e)return;const t={};e.x402CheckoutOrigin&&(t.checkoutOrigin=e.x402CheckoutOrigin),e.x402CheckoutPath&&(t.checkoutPath=e.x402CheckoutPath),e.x402FooterNote&&(t.footerNote=e.x402FooterNote),(e.x402BrandName||e.x402BrandUrl)&&(t.brand={},e.x402BrandName&&(t.brand.name=e.x402BrandName),e.x402BrandUrl&&(t.brand.url=e.x402BrandUrl)),(e.x402BuilderWallet||e.x402BuilderService)&&(t.builderCode={},e.x402BuilderWallet&&(t.builderCode.wallet=e.x402BuilderWallet),e.x402BuilderService&&(t.builderCode.service=e.x402BuilderService)),Object.keys(t).length&&j(t)}catch{}}typeof document<"u"&&(Te(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",A,{once:!0}):A(),new MutationObserver(()=>A()).observe(document.documentElement,{childList:!0,subtree:!0})),typeof window<"u"&&(window.X402=Object.freeze({pay:Z,init:A,configure:j,version:te,tokens:Object.freeze({USDC_MINT_SOLANA:T,THREE_MINT:P,KNOWN_SOLANA_TOKENS:B})}));export{B as KNOWN_SOLANA_TOKENS,P as THREE_MINT,T as USDC_MINT_SOLANA,j as configure,A as init,Z as pay};
|
|
505
|
+
`;const i=this.bodyEl.querySelector("[data-done]");i.addEventListener("click",()=>this.close("done")),requestAnimationFrame(()=>i.focus())}async start(){this.bodyEl.innerHTML=this.renderSteps("discover"),this.priceEl.innerHTML='<span class="x402-skeleton" style="display:inline-block;width:92px;height:26px;vertical-align:middle"></span>',this.networkEl.innerHTML='<span class="x402-skeleton" style="display:inline-block;width:58px;height:11px;border-radius:99px"></span>',ie().catch(()=>{});try{const e=await Le(this.opts);this.challenge=e,this.siwx=ke(e),this.payFlowOverride=!1,this.siwxFallbackNotice=null;const t=F(e),r=V(t);this.solanaAccept=r;const o=e.accepts.find(K),s=typeof window<"u"&&(window.solana?.isPhantom||window.phantom?.solana);this.accept=s&&r||o||e.accepts[0],this.setPrice(this.accept),this.renderConnect()}catch(e){this.renderError("discover",e.message||String(e))}}async runSolana(e,t){this.accept=e,this.setPrice(e);const r=t||window.phantom?.solana||window.solana,o=r?.isPhantom?"Phantom":this._solWallets?.find(s=>s.provider===r)?.name||"wallet";this.renderProgress("connect",{text:`Opening ${o}\u2026`});try{if(!r)throw new Error("No Solana wallet detected");const a=((await r.connect())?.publicKey||r.publicKey)?.toString();if(!a)throw new Error("Phantom did not return a public key");this.payerAddress=a;const i=G({accept:e,caps:this.opts.caps,address:a});if(i.abort){this.renderError("authorize",i.reason);return}this.spendReservation=i.reservation||null,this.renderProgress("authorize",{text:`Building Solana payment for ${a.slice(0,6)}\u2026${a.slice(-4)}`});const l=await ce(`${U()}?action=prepare`,{accept:e,buyer:a});this.renderProgress("authorize",{text:"Confirm in Phantom\u2026"});const c=Me(l.tx_base64),h=(await ie()).VersionedTransaction.deserialize(c),y=await r.signTransaction(h),$=je(y.serialize()),S=X(this.challenge),A=await ce(`${U()}?action=encode`,{accept:e,signed_tx_base64:$,resource_url:new URL(this.opts.endpoint,location.href).href,...S?{builder_code:S}:{}});await this.executePaid(A.x_payment)}catch(s){this.spendReservation&&(D(this.spendReservation),this.spendReservation=null),this.renderError(this.payerAddress?"authorize":"connect",E(s))}}async runEvm(e,t){this.accept=e,this.setPrice(e),this.renderProgress("connect",{text:"Opening browser wallet\u2026"});try{const r=t||window.ethereum;if(!r)throw new Error("No EVM wallet detected");const s=(await r.request({method:"eth_requestAccounts"}))?.[0];if(!s)throw new Error("Wallet did not return an account");this.payerAddress=s;const a=G({accept:e,caps:this.opts.caps,address:s});if(a.abort){this.renderError("authorize",a.reason);return}this.spendReservation=a.reservation||null;const i=z[e.network];if(!i)throw new Error(`Unknown EVM network ${e.network}`);const l=await r.request({method:"eth_chainId"}),c="0x"+i.chainId.toString(16);if(l!==c){this.renderProgress("connect",{text:`Switch wallet to ${i.name}\u2026`});try{await r.request({method:"wallet_switchEthereumChain",params:[{chainId:c}]})}catch{throw new Error(`Wallet is on ${l}; please switch to ${i.name} (${c}) and retry`)}}this.renderProgress("authorize",{text:`Authorize ${C(e.amount)} USDC\u2026`});const w=0,h=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||600),y="0x"+se(32),$={name:e.extra?.name||"USD Coin",version:e.extra?.version||"2",chainId:i.chainId,verifyingContract:e.asset},S={EIP712Domain:[{name:"name",type:"string"},{name:"version",type:"string"},{name:"chainId",type:"uint256"},{name:"verifyingContract",type:"address"}],TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},A={from:s,to:e.payTo,value:e.amount,validAfter:w,validBefore:h,nonce:y},x={primaryType:"TransferWithAuthorization",types:S,domain:$,message:A},d=await r.request({method:"eth_signTypedData_v4",params:[s,JSON.stringify(x)]}),f={x402Version:2,scheme:"exact",network:e.network,resource:{url:this.opts.endpoint,mimeType:"application/json"},accepted:e,payload:{signature:d,authorization:{from:s,to:e.payTo,value:e.amount,validAfter:String(w),validBefore:String(h),nonce:y}}},b=X(this.challenge);b&&(f.extensions={"builder-code":b});const g=be(f);await this.executePaid(g)}catch(r){this.spendReservation&&(D(this.spendReservation),this.spendReservation=null),this.renderError(this.payerAddress?"authorize":"connect",E(r))}}async executePaid(e,t=0){this.renderProgress("verify",{text:t?"Retrying after upstream throttle\u2026":"Calling merchant endpoint\u2026"}),this.idempotencyKey||(this.idempotencyKey=`x402-${se(16)}`);try{const r=await fetch(this.opts.endpoint,{method:this.opts.method||"GET",headers:{...this.opts.headers||{},...this.opts.body&&!this.opts.headers?.["content-type"]?{"content-type":"application/json"}:{},"X-PAYMENT":e,"Idempotency-Key":this.idempotencyKey,"X-Idempotency-Key":this.idempotencyKey},body:this.opts.body?typeof this.opts.body=="string"?this.opts.body:JSON.stringify(this.opts.body):void 0}),o=r.headers.get("content-type")||"",s=await r.text();let a;if(o.includes("json"))try{a=JSON.parse(s)}catch{a=s}else a=s;if(!r.ok){if(r.status===429&&t<_e)return await this.waitForThrottle(ze(r,a)),this.executePaid(e,t+1);const c=a&&typeof a=="object"&&(a.error_description||a.error)||`HTTP ${r.status}`;throw new Error(c)}const i=r.headers.get("x-payment-response"),l=q(i)||{};this.spendReservation=null,this.renderDone({result:a,payment:l}),this.resolve?.({ok:!0,result:a,payment:l,response:{status:r.status,headers:oe(r.headers)}})}catch(r){this.spendReservation&&(D(this.spendReservation),this.spendReservation=null),this.renderError("verify",E(r))}}async waitForThrottle(e){const t=Math.max(1,Math.min(30,Math.round(e)||6));for(let r=t;r>0;r--)this.renderProgress("verify",{text:`Generator is busy \u2014 retrying in ${r}s\u2026`}),await new Promise(o=>setTimeout(o,1e3));this.renderProgress("verify",{text:"Retrying\u2026"})}async runSiwxEvm(e){this.renderProgress("connect",{text:"Opening browser wallet\u2026"});try{const t=window.ethereum;if(!t)throw new Error("No EVM wallet detected");const o=(await t.request({method:"eth_requestAccounts"}))?.[0];if(!o)throw new Error("Wallet did not return an account");const a=(await $e())(o);this.payerAddress=a,this.renderProgress("authorize",{text:`Sign sign-in message as ${a.slice(0,6)}\u2026${a.slice(-4)}`});const i=Q(this.siwx.info,e,a),l=await t.request({method:"personal_sign",params:[i,a]}),c=this.siwx.info,w={domain:c.domain,address:a,...c.statement?{statement:c.statement}:{},uri:c.uri,version:c.version||"1",chainId:e.chainId,type:"eip191",nonce:c.nonce,issuedAt:c.issuedAt,...c.expirationTime?{expirationTime:c.expirationTime}:{},...c.notBefore?{notBefore:c.notBefore}:{},...c.requestId!==void 0&&c.requestId!==null?{requestId:c.requestId}:{},...Array.isArray(c.resources)?{resources:c.resources}:{},signatureScheme:"eip191",signature:l};await this.executeSiwx(w,e.chainId)}catch(t){this.renderError(this.payerAddress?"authorize":"connect",E(t))}}async runSiwxSolana(e){this.renderProgress("connect",{text:"Opening Phantom\u2026"});try{const t=window.phantom?.solana||window.solana;if(!t)throw new Error("Phantom wallet not detected");const s=((await t.connect())?.publicKey||t.publicKey)?.toString();if(!s)throw new Error("Phantom did not return a public key");this.payerAddress=s,this.renderProgress("authorize",{text:`Sign sign-in message as ${s.slice(0,6)}\u2026${s.slice(-4)}`});const a=Q(this.siwx.info,e,s),i=new TextEncoder().encode(a),l=await t.signMessage(i,"utf8"),c=l?.signature instanceof Uint8Array?l.signature:new Uint8Array(l?.signature||l);if(!c||!c.length)throw new Error("Phantom did not return a signature");const w=Ee(c),h=this.siwx.info,y={domain:h.domain,address:s,...h.statement?{statement:h.statement}:{},uri:h.uri,version:h.version||"1",chainId:e.chainId,type:"ed25519",nonce:h.nonce,issuedAt:h.issuedAt,...h.expirationTime?{expirationTime:h.expirationTime}:{},...h.notBefore?{notBefore:h.notBefore}:{},...h.requestId!==void 0&&h.requestId!==null?{requestId:h.requestId}:{},...Array.isArray(h.resources)?{resources:h.resources}:{},signatureScheme:"siws",signature:w};await this.executeSiwx(y,e.chainId)}catch(t){this.renderError(this.payerAddress?"authorize":"connect",E(t))}}async executeSiwx(e,t){this.renderProgress("verify",{text:"Verifying sign-in\u2026"});const r=Se(e);let o;try{o=await fetch(this.opts.endpoint,{method:this.opts.method||"GET",headers:{...this.opts.headers||{},...this.opts.body&&!this.opts.headers?.["content-type"]?{"content-type":"application/json"}:{},[xe]:r},body:this.opts.body?typeof this.opts.body=="string"?this.opts.body:JSON.stringify(this.opts.body):void 0})}catch(a){this.renderError("verify",E(a));return}if(o.status===200){const a=o.headers.get("content-type")||"",i=await o.text();let l;if(a.includes("json"))try{l=JSON.parse(i)}catch{l=i}else l=i;const c={address:e.address,network:t};this.renderDone({result:l,siwx:c}),this.resolve?.({ok:!0,result:l,siwx:c,response:{status:o.status,headers:oe(o.headers)}});return}if(o.status===401||o.status===402){let a=null;try{a=await o.clone().json()}catch{}const i=a?.code||a?.error;this.siwx=null,this.payerAddress=null,this.payFlowOverride=!1,this.siwxFallbackNotice=i==="siwx_not_paid"||o.status===402?"You haven't paid for this yet \u2014 pay now to unlock re-entry.":"Sign-in not accepted \u2014 please pay to continue.",!this.challenge||!Array.isArray(this.challenge.accepts)||!this.challenge.accepts.length?this.start():this.renderConnect();return}const s=await o.text().catch(()=>"");this.renderError("verify",`SIWX retry failed: HTTP ${o.status}${s?` \xB7 ${s.slice(0,120)}`:""}`)}}function u(n){return String(n??"").replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function oe(n){const e={};return n.forEach((t,r)=>e[r]=t),e}const _e=2;function ze(n,e,t=6){const r=Number.parseInt(n.headers.get("retry-after")||"",10);if(Number.isFinite(r)&&r>0)return r;const o=e&&typeof e=="object"?Number(e.retry_after):NaN;return Number.isFinite(o)&&o>0?o:t}function E(n){const e=n?.shortMessage||n?.message||String(n);return/user rejected|user denied|reject/i.test(e)?"cancelled in wallet":/throttl|rate.?limit|too many requests|less than \$|in credit|\b429\b/i.test(e)?"The service is briefly busy and your payment was not taken \u2014 retry in a few seconds.":/dynamically imported module|esm\.sh|module script failed/i.test(e)?"A component this wallet path needs (loaded from esm.sh) was blocked \u2014 often by a strict host security policy. Pay with MetaMask on Base instead; it needs no third-party code.":e.slice(0,240)}function Me(n){if(typeof Buffer<"u")return new Uint8Array(Buffer.from(n,"base64"));const e=atob(n),t=new Uint8Array(e.length);for(let r=0;r<e.length;r++)t[r]=e.charCodeAt(r);return t}function je(n){if(typeof Buffer<"u")return Buffer.from(n).toString("base64");let e="";for(let t=0;t<n.length;t++)e+=String.fromCharCode(n[t]);return btoa(e)}function se(n){const e=new Uint8Array(n);return crypto.getRandomValues(e),Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}async function ae(n,e,t){const r=new Set,o=[n,...e].filter(a=>a&&!r.has(a)&&r.add(a));let s;for(const a of o)try{return await Promise.race([import(a),new Promise((i,l)=>setTimeout(()=>l(new Error(`timed out loading ${t} from ${a}`)),ue))])}catch(i){s=i}throw s||new Error(`could not load ${t} from any CDN`)}let I=null;async function ie(){return I||(I=await ae(p.esm.solanaWeb3,H.solanaWeb3,"@solana/web3.js"),I)}async function ce(n,e){const t=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),r=await t.text();let o;try{o=JSON.parse(r)}catch{o={error:"parse_error",error_description:r.slice(0,200)}}if(!t.ok){const s=new Error(o.error_description||o.error||`HTTP ${t.status}`);throw s.status=t.status,s.data=o,s}return o}async function Le(n){const e={...n.headers||{}},t={method:n.method||"GET",headers:e,body:n.body?typeof n.body=="string"?n.body:JSON.stringify(n.body):void 0};t.body&&!e["content-type"]&&(e["content-type"]="application/json");const r=await fetch(n.endpoint,t),o=r.headers.get("payment-required"),s=r.status===401&&!!o;if(r.status!==402&&!s){const i=await r.text();throw new Error(`Endpoint did not return 402 (got ${r.status}). Body: ${i.slice(0,120)}`)}let a=s?q(o):await r.json().catch(()=>null);if(!a||!Array.isArray(a.accepts)||!a.accepts.length){const i=q(o);i&&Array.isArray(i.accepts)&&i.accepts.length&&(a=i)}if(!a||!Array.isArray(a.accepts)||!a.accepts.length)throw new Error("Endpoint returned 402 but no `accepts` array could be found in body or header");return a}async function le(n){if(!n?.endpoint)throw new Error("X402.pay: endpoint is required");const e=new Ie(n),t=e.mount();return queueMicrotask(()=>e.start()),t}function Oe(n){n.dataset.x402Bound!=="1"&&(n.dataset.x402Bound="1",n.addEventListener("click",async e=>{e.preventDefault();const t=qe(n);try{const r=await le(t);r?.siwx&&n.dispatchEvent(new CustomEvent("x402:siwx-signed",{detail:r.siwx,bubbles:!0})),n.dispatchEvent(new CustomEvent("x402:result",{detail:r,bubbles:!0}))}catch(r){if(r?.code==="cancelled")return;n.dispatchEvent(new CustomEvent("x402:error",{detail:{error:r?.message||String(r)},bubbles:!0}))}}))}function qe(n){const e=n.dataset;let t=e.x402Body;if(t)try{t=JSON.parse(t)}catch{}let r=e.x402Headers;if(r)try{r=JSON.parse(r)}catch{r=void 0}return{endpoint:e.x402Endpoint,method:e.x402Method||(t?"POST":"GET"),body:t,headers:r,merchant:e.x402Merchant,action:e.x402Action||n.textContent?.trim().slice(0,60)}}function _(){document.querySelectorAll("[data-x402-endpoint]").forEach(Oe)}function De(){try{const e=(document.currentScript||document.querySelector('script[src*="x402"][type="module"]')||document.querySelector("script[data-x402-checkout-origin]"))?.dataset;if(!e)return;const t={};e.x402CheckoutOrigin&&(t.checkoutOrigin=e.x402CheckoutOrigin),e.x402CheckoutPath&&(t.checkoutPath=e.x402CheckoutPath),e.x402FooterNote&&(t.footerNote=e.x402FooterNote),(e.x402BrandName||e.x402BrandUrl)&&(t.brand={},e.x402BrandName&&(t.brand.name=e.x402BrandName),e.x402BrandUrl&&(t.brand.url=e.x402BrandUrl)),(e.x402BuilderWallet||e.x402BuilderService)&&(t.builderCode={},e.x402BuilderWallet&&(t.builderCode.wallet=e.x402BuilderWallet),e.x402BuilderService&&(t.builderCode.service=e.x402BuilderService)),Object.keys(t).length&&W(t)}catch{}}typeof document<"u"&&(De(),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",_,{once:!0}):_(),new MutationObserver(()=>_()).observe(document.documentElement,{childList:!0,subtree:!0})),typeof window<"u"&&(window.X402=Object.freeze({pay:le,init:_,configure:W,version:de,tokens:Object.freeze({USDC_MINT_SOLANA:M,THREE_MINT:j,KNOWN_SOLANA_TOKENS:L})}));export{L as KNOWN_SOLANA_TOKENS,j as THREE_MINT,M as USDC_MINT_SOLANA,W as configure,_ as init,le as pay};
|