mppx 0.5.1 → 0.5.3

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/Credential.d.ts +12 -0
  3. package/dist/Credential.d.ts.map +1 -1
  4. package/dist/Credential.js +22 -4
  5. package/dist/Credential.js.map +1 -1
  6. package/dist/Method.d.ts +4 -0
  7. package/dist/Method.d.ts.map +1 -1
  8. package/dist/Method.js +2 -1
  9. package/dist/Method.js.map +1 -1
  10. package/dist/proxy/Proxy.d.ts.map +1 -1
  11. package/dist/proxy/Proxy.js +52 -8
  12. package/dist/proxy/Proxy.js.map +1 -1
  13. package/dist/proxy/internal/Route.d.ts.map +1 -1
  14. package/dist/proxy/internal/Route.js +7 -3
  15. package/dist/proxy/internal/Route.js.map +1 -1
  16. package/dist/server/Mppx.d.ts.map +1 -1
  17. package/dist/server/Mppx.js +90 -71
  18. package/dist/server/Mppx.js.map +1 -1
  19. package/dist/server/Transport.d.ts +5 -1
  20. package/dist/server/Transport.d.ts.map +1 -1
  21. package/dist/server/Transport.js +52 -7
  22. package/dist/server/Transport.js.map +1 -1
  23. package/dist/server/internal/html/config.d.ts +7 -0
  24. package/dist/server/internal/html/config.d.ts.map +1 -0
  25. package/dist/server/internal/html/config.js +3 -0
  26. package/dist/server/internal/html/config.js.map +1 -0
  27. package/dist/server/internal/html/serviceWorker.gen.d.ts +2 -0
  28. package/dist/server/internal/html/serviceWorker.gen.d.ts.map +1 -0
  29. package/dist/server/internal/html/serviceWorker.gen.js +3 -0
  30. package/dist/server/internal/html/serviceWorker.gen.js.map +1 -0
  31. package/dist/stripe/server/Charge.d.ts +5 -0
  32. package/dist/stripe/server/Charge.d.ts.map +1 -1
  33. package/dist/stripe/server/Charge.js +14 -6
  34. package/dist/stripe/server/Charge.js.map +1 -1
  35. package/dist/stripe/server/internal/html.gen.d.ts +2 -0
  36. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -0
  37. package/dist/stripe/server/internal/html.gen.js +3 -0
  38. package/dist/stripe/server/internal/html.gen.js.map +1 -0
  39. package/dist/tempo/server/Charge.d.ts +2 -0
  40. package/dist/tempo/server/Charge.d.ts.map +1 -1
  41. package/dist/tempo/server/Charge.js +15 -9
  42. package/dist/tempo/server/Charge.js.map +1 -1
  43. package/dist/tempo/server/Session.d.ts.map +1 -1
  44. package/dist/tempo/server/Session.js +3 -2
  45. package/dist/tempo/server/Session.js.map +1 -1
  46. package/dist/tempo/server/internal/html.gen.d.ts +2 -0
  47. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -0
  48. package/dist/tempo/server/internal/html.gen.js +3 -0
  49. package/dist/tempo/server/internal/html.gen.js.map +1 -0
  50. package/dist/tempo/server/internal/transport.d.ts +1 -1
  51. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  52. package/dist/tempo/server/internal/transport.js +45 -58
  53. package/dist/tempo/server/internal/transport.js.map +1 -1
  54. package/package.json +2 -2
  55. package/src/Credential.ts +28 -4
  56. package/src/Method.ts +6 -1
  57. package/src/env.d.ts +1 -0
  58. package/src/mcp-sdk/server/Transport.test.ts +6 -0
  59. package/src/proxy/Proxy.test.ts +188 -1
  60. package/src/proxy/Proxy.ts +58 -9
  61. package/src/proxy/internal/Route.test.ts +9 -0
  62. package/src/proxy/internal/Route.ts +5 -2
  63. package/src/server/Mppx.test.ts +171 -18
  64. package/src/server/Mppx.ts +120 -79
  65. package/src/server/Transport.test.ts +16 -2
  66. package/src/server/Transport.ts +61 -7
  67. package/src/server/internal/html/config.ts +8 -0
  68. package/src/server/internal/html/serviceWorker.client.ts +28 -0
  69. package/src/server/internal/html/serviceWorker.gen.ts +2 -0
  70. package/src/server/internal/html/serviceWorker.ts +27 -0
  71. package/src/server/internal/html/tsconfig.worker.client.json +8 -0
  72. package/src/server/internal/html/tsconfig.worker.json +8 -0
  73. package/src/stripe/server/Charge.ts +19 -5
  74. package/src/stripe/server/internal/html/main.ts +106 -0
  75. package/src/stripe/server/internal/html/node_modules/.bin/mppx.src +21 -0
  76. package/src/stripe/server/internal/html/package.json +9 -0
  77. package/src/stripe/server/internal/html/stripe-js-pure.d.ts +7 -0
  78. package/src/stripe/server/internal/html/tsconfig.json +8 -0
  79. package/src/stripe/server/internal/html.gen.ts +2 -0
  80. package/src/tempo/server/Charge.ts +20 -8
  81. package/src/tempo/server/Session.ts +3 -2
  82. package/src/tempo/server/internal/html/main.ts +71 -0
  83. package/src/tempo/server/internal/html/node_modules/.bin/mppx.src +21 -0
  84. package/src/tempo/server/internal/html/package.json +10 -0
  85. package/src/tempo/server/internal/html/tsconfig.json +8 -0
  86. package/src/tempo/server/internal/html.gen.ts +2 -0
  87. package/src/tempo/server/internal/transport.test.ts +37 -31
  88. package/src/tempo/server/internal/transport.ts +44 -58
  89. package/src/tsconfig.json +1 -1
@@ -1,9 +1,13 @@
1
+ import { Json } from 'ox'
2
+
1
3
  import * as Challenge from '../Challenge.js'
2
4
  import * as Credential from '../Credential.js'
3
5
  import * as Errors from '../Errors.js'
4
6
  import type { Distribute, UnionToIntersection } from '../internal/types.js'
5
7
  import * as core_Mcp from '../Mcp.js'
6
8
  import * as Receipt from '../Receipt.js'
9
+ import * as Html from './internal/html/config.js'
10
+ import { serviceWorker } from './internal/html/serviceWorker.gen.js'
7
11
 
8
12
  export { type McpSdk, mcpSdk } from '../mcp-sdk/server/Transport.js'
9
13
 
@@ -30,11 +34,14 @@ export type Transport<
30
34
  respondChallenge: (options: {
31
35
  challenge: Challenge.Challenge
32
36
  error?: Errors.PaymentError | undefined
37
+ html?: Html.Options | undefined
33
38
  input: input
34
39
  }) => challengeOutput | Promise<challengeOutput>
35
40
  /** Attaches a receipt to a successful response. */
36
41
  respondReceipt: (options: {
37
42
  challengeId: string
43
+ credential: Credential.Credential
44
+ input: input
38
45
  receipt: Receipt.Receipt
39
46
  response: receiptResponse
40
47
  }) => receiptOutput
@@ -87,7 +94,7 @@ export type WithReceipt<transport extends AnyTransport = Http> = WithReceiptOver
87
94
  * name: 'custom',
88
95
  * getCredential(input) { ... },
89
96
  * respondChallenge({ challenge, input }) { ... },
90
- * respondReceipt({ receipt, response, challengeId }) { ... },
97
+ * respondReceipt({ receipt, response, challengeId, credential, input }) { ... },
91
98
  * })
92
99
  * ```
93
100
  */
@@ -121,17 +128,64 @@ export function http(): Http {
121
128
  return Credential.deserialize(payment)
122
129
  },
123
130
 
124
- respondChallenge({ challenge, error }) {
131
+ respondChallenge(options) {
132
+ const { challenge, error, input } = options
133
+
134
+ if (options.html && new URL(input.url).searchParams.has(Html.serviceWorkerParam))
135
+ return new Response(serviceWorker, {
136
+ status: 200,
137
+ headers: {
138
+ 'Content-Type': 'application/javascript',
139
+ 'Cache-Control': 'no-store',
140
+ },
141
+ })
142
+
125
143
  const headers: Record<string, string> = {
126
144
  'WWW-Authenticate': Challenge.serialize(challenge),
127
145
  'Cache-Control': 'no-store',
128
146
  }
129
147
 
130
- let body: string | null = null
131
- if (error) {
132
- headers['Content-Type'] = 'application/problem+json'
133
- body = JSON.stringify(error.toProblemDetails(challenge.id))
134
- }
148
+ const body = (() => {
149
+ if (options.html && input.headers.get('Accept')?.includes('text/html')) {
150
+ headers['Content-Type'] = 'text/html; charset=utf-8'
151
+ const html = String.raw
152
+ return html`<!doctype html>
153
+ <html lang="en">
154
+ <head>
155
+ <meta charset="UTF-8" />
156
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
157
+ <title>Payment Required</title>
158
+ <style>
159
+ :root {
160
+ color-scheme: dark light;
161
+ }
162
+ </style>
163
+ </head>
164
+ <body>
165
+ <h1>Payment Required</h1>
166
+ <pre>
167
+ ${Json.stringify(challenge, null, 2)
168
+ .replace(/&/g, '&amp;')
169
+ .replace(/</g, '&lt;')
170
+ .replace(/>/g, '&gt;')}</pre
171
+ >
172
+ <div id="root"></div>
173
+ <script id="${Html.dataId}" type="application/json">
174
+ ${Json.stringify({ config: options.html.config, challenge }).replace(
175
+ /</g,
176
+ '\\u003c',
177
+ )}
178
+ </script>
179
+ ${options.html.content}
180
+ </body>
181
+ </html> `
182
+ }
183
+ if (error) {
184
+ headers['Content-Type'] = 'application/problem+json'
185
+ return JSON.stringify(error.toProblemDetails(challenge.id))
186
+ }
187
+ return null
188
+ })()
135
189
 
136
190
  return new Response(body, { status: error?.status ?? 402, headers })
137
191
  },
@@ -0,0 +1,8 @@
1
+ export type Options = {
2
+ config: Record<string, unknown>
3
+ content: string
4
+ }
5
+
6
+ export const dataId = '__MPPX_DATA__'
7
+
8
+ export const serviceWorkerParam = '__mppx_worker'
@@ -0,0 +1,28 @@
1
+ import { serviceWorkerParam } from './config.js'
2
+
3
+ export async function submitCredential(credential: string): Promise<void> {
4
+ const url = new URL(location.href)
5
+ url.searchParams.set(serviceWorkerParam, '')
6
+
7
+ const registration = await navigator.serviceWorker.register(url.pathname + url.search)
8
+
9
+ const serviceWorker = await new Promise<ServiceWorker>((resolve) => {
10
+ const mppxWorker = registration.installing ?? registration.waiting ?? registration.active
11
+ if (mppxWorker?.state === 'activated') return resolve(mppxWorker)
12
+ const target = mppxWorker ?? registration
13
+ target.addEventListener('statechange', function handler() {
14
+ const active = registration.active
15
+ if (active?.state === 'activated') {
16
+ target.removeEventListener('statechange', handler)
17
+ resolve(active)
18
+ }
19
+ })
20
+ })
21
+
22
+ await new Promise<void>((resolve) => {
23
+ const channel = new MessageChannel()
24
+ channel.port1.onmessage = () => resolve()
25
+ serviceWorker.postMessage({ credential }, [channel.port2])
26
+ })
27
+ location.reload()
28
+ }
@@ -0,0 +1,2 @@
1
+ // Generated — do not edit.
2
+ export const serviceWorker = "(function(){let e=self,t;e.addEventListener(`activate`,t=>{t.waitUntil(e.clients.claim())}),e.addEventListener(`message`,e=>{if(!e.source)return;let n=e.data?.credential;typeof n!=`string`||!n.startsWith(`Payment `)||(t=n,e.ports[0]?.postMessage(`ack`))}),e.addEventListener(`fetch`,n=>{if(!t||n.request.mode!==`navigate`||new URL(n.request.url).origin!==e.location.origin)return;let r=new Headers(n.request.headers);r.set(`Authorization`,t),t=void 0,n.respondWith(fetch(n.request,{headers:r})),e.registration.unregister()})})();"
@@ -0,0 +1,27 @@
1
+ const serviceWorker = self as unknown as ServiceWorkerGlobalScope
2
+
3
+ let credential: string | undefined
4
+
5
+ serviceWorker.addEventListener('activate', (event) => {
6
+ event.waitUntil(serviceWorker.clients.claim())
7
+ })
8
+
9
+ serviceWorker.addEventListener('message', (event) => {
10
+ if (!event.source) return
11
+ const value = event.data?.credential
12
+ if (typeof value !== 'string' || !value.startsWith('Payment ')) return
13
+ credential = value
14
+ event.ports[0]?.postMessage('ack')
15
+ })
16
+
17
+ serviceWorker.addEventListener('fetch', (event) => {
18
+ if (!credential || event.request.mode !== 'navigate') return
19
+ if (new URL(event.request.url).origin !== serviceWorker.location.origin) return
20
+
21
+ const headers = new Headers(event.request.headers)
22
+ headers.set('Authorization', credential)
23
+ credential = undefined
24
+
25
+ event.respondWith(fetch(event.request, { headers }))
26
+ serviceWorker.registration.unregister()
27
+ })
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "lib": ["es2022", "dom"],
5
+ "types": []
6
+ },
7
+ "include": ["serviceWorker.client.ts"]
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "lib": ["es2022", "webworker"],
5
+ "types": []
6
+ },
7
+ "include": ["serviceWorker.ts"]
8
+ }
@@ -5,6 +5,7 @@ import type { LooseOmit, OneOf } from '../../internal/types.js'
5
5
  import * as Method from '../../Method.js'
6
6
  import type { StripeClient } from '../internal/types.js'
7
7
  import * as Methods from '../Methods.js'
8
+ import { html as htmlContent } from './internal/html.gen.js'
8
9
 
9
10
  /**
10
11
  * Creates a Stripe charge method intent for usage on the server.
@@ -38,6 +39,7 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
38
39
  decimals,
39
40
  description,
40
41
  externalId,
42
+ html,
41
43
  metadata,
42
44
  networkId,
43
45
  paymentMethodTypes,
@@ -59,9 +61,11 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
59
61
  paymentMethodTypes,
60
62
  } as unknown as Defaults,
61
63
 
62
- async verify({ credential }) {
64
+ html: html ? { config: html, content: htmlContent } : undefined,
65
+
66
+ async verify({ credential, request }) {
63
67
  const { challenge } = credential
64
- const { request } = challenge
68
+ const resolvedRequest = Methods.charge.schema.request.parse(request)
65
69
 
66
70
  Expires.assert(challenge.expires, challenge.id)
67
71
 
@@ -72,15 +76,23 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
72
76
  externalId?: string
73
77
  }
74
78
 
75
- const userMetadata = request.methodDetails?.metadata as Record<string, string> | undefined
79
+ const userMetadata = resolvedRequest.methodDetails?.metadata as
80
+ | Record<string, string>
81
+ | undefined
76
82
  const resolvedMetadata = { ...buildAnalytics({ credential }), ...userMetadata }
77
83
 
78
84
  const pi = client
79
- ? await createWithClient({ client, challenge, request, spt, metadata: resolvedMetadata })
85
+ ? await createWithClient({
86
+ client,
87
+ challenge,
88
+ request: resolvedRequest,
89
+ spt,
90
+ metadata: resolvedMetadata,
91
+ })
80
92
  : await createWithSecretKey({
81
93
  secretKey: secretKey!,
82
94
  challenge,
83
- request,
95
+ request: resolvedRequest,
84
96
  spt,
85
97
  metadata: resolvedMetadata,
86
98
  })
@@ -108,6 +120,8 @@ export declare namespace charge {
108
120
  type Defaults = LooseOmit<Method.RequestDefaults<typeof Methods.charge>, 'recipient'>
109
121
 
110
122
  type Parameters = {
123
+ /** Render payment page when Accept header is text/html (e.g. in browsers) */
124
+ html?: { createTokenUrl: string; publishableKey: string } | undefined
111
125
  /** Optional metadata to include in SPT creation requests. */
112
126
  metadata?: Record<string, string> | undefined
113
127
  } & Defaults &
@@ -0,0 +1,106 @@
1
+ import { loadStripe } from '@stripe/stripe-js/pure'
2
+
3
+ import type * as Challenge from '../../../../Challenge.js'
4
+ import { stripe } from '../../../../client/index.js'
5
+ import * as Html from '../../../../server/internal/html/config.js'
6
+ import { submitCredential } from '../../../../server/internal/html/serviceWorker.client.js'
7
+ import type { charge as chargeClient } from '../../../../stripe/client/Charge.js'
8
+ import type { charge } from '../../../../stripe/server/Charge.js'
9
+ import type * as Methods from '../../../Methods.js'
10
+
11
+ const data = JSON.parse(document.getElementById(Html.dataId)!.textContent!) as {
12
+ config: NonNullable<charge.Parameters['html']>
13
+ challenge: Challenge.FromMethods<[typeof Methods.charge]>
14
+ }
15
+
16
+ const root = document.getElementById('root')!
17
+
18
+ const h2 = document.createElement('h2')
19
+ h2.textContent = 'stripe'
20
+ root.appendChild(h2)
21
+
22
+ ;(async () => {
23
+ if (import.meta.env.MODE === 'test') {
24
+ const button = document.createElement('button')
25
+ button.textContent = 'Pay'
26
+ root.appendChild(button)
27
+ button.onclick = async () => {
28
+ try {
29
+ button.disabled = true
30
+ const method = stripe({ createToken })[0]
31
+ const credential = await method.createCredential({
32
+ challenge: data.challenge,
33
+ context: { paymentMethod: 'pm_card_visa' },
34
+ })
35
+ await submitCredential(credential)
36
+ } finally {
37
+ button.disabled = false
38
+ }
39
+ }
40
+ return
41
+ }
42
+
43
+ const stripeJs = await loadStripe(data.config.publishableKey)
44
+ if (!stripeJs) throw new Error('Failed to loadStripe')
45
+
46
+ const darkQuery = window.matchMedia('(prefers-color-scheme: dark)')
47
+ const getAppearance = () => ({
48
+ theme: (darkQuery.matches ? 'night' : 'stripe') as 'night' | 'stripe',
49
+ })
50
+
51
+ const elements = stripeJs.elements({
52
+ amount: Number(data.challenge.request.amount),
53
+ appearance: getAppearance(),
54
+ currency: data.challenge.request.currency as string,
55
+ mode: 'payment',
56
+ paymentMethodCreation: 'manual',
57
+ })
58
+
59
+ darkQuery.addEventListener('change', () => {
60
+ elements.update({ appearance: getAppearance() })
61
+ })
62
+
63
+ const form = document.createElement('form')
64
+ elements.create('payment').mount(form)
65
+ root.appendChild(form)
66
+
67
+ const button = document.createElement('button')
68
+ button.textContent = 'Pay'
69
+ button.type = 'submit'
70
+ form.appendChild(button)
71
+
72
+ form.onsubmit = async (event) => {
73
+ event.preventDefault()
74
+ button.disabled = true
75
+ try {
76
+ await elements.submit()
77
+ const { paymentMethod, error } = await stripeJs.createPaymentMethod({ elements })
78
+ if (error || !paymentMethod) throw error ?? new Error('Failed to create payment method')
79
+ const method = stripe({ client: stripeJs, createToken })[0]
80
+ const credential = await method.createCredential({
81
+ challenge: data.challenge,
82
+ context: { paymentMethod: paymentMethod.id },
83
+ })
84
+ await submitCredential(credential)
85
+ } finally {
86
+ button.disabled = false
87
+ }
88
+ }
89
+ })()
90
+
91
+ async function createToken(opts: chargeClient.OnChallengeParameters) {
92
+ const createTokenUrl = new URL(data.config.createTokenUrl, location.origin)
93
+ if (createTokenUrl.origin !== location.origin)
94
+ throw new Error('createTokenUrl must be same-origin')
95
+ const res = await fetch(createTokenUrl, {
96
+ method: 'POST',
97
+ headers: { 'Content-Type': 'application/json' },
98
+ body: JSON.stringify(opts),
99
+ })
100
+ if (!res.ok) {
101
+ const text = await res.text().catch(() => '<response body unavailable>')
102
+ throw new Error(`Failed to create SPT (${res.status}): ${text}`)
103
+ }
104
+ const json = (await res.json()) as { spt: string }
105
+ return json.spt
106
+ }
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/mppx/mppx/src/node_modules:/home/runner/work/mppx/mppx/node_modules:/home/runner/work/mppx/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/mppx/mppx/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/mppx/mppx/src/node_modules:/home/runner/work/mppx/mppx/node_modules:/home/runner/work/mppx/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/mppx/mppx/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../mppx/src/bin.ts" "$@"
19
+ else
20
+ exec node "$basedir/../mppx/src/bin.ts" "$@"
21
+ fi
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "@mppx/stripe-html",
3
+ "private": true,
4
+ "type": "module",
5
+ "dependencies": {
6
+ "@stripe/stripe-js": "8.9.0",
7
+ "mppx": "workspace:*"
8
+ }
9
+ }
@@ -0,0 +1,7 @@
1
+ declare module '@stripe/stripe-js/pure' {
2
+ export * from '@stripe/stripe-js'
3
+
4
+ export const loadStripe: typeof import('@stripe/stripe-js').loadStripe & {
5
+ setLoadParameters(parameters: { advancedFraudSignals: boolean }): void
6
+ }
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "lib": ["es2022", "dom"],
5
+ "types": []
6
+ },
7
+ "include": ["./**/*.ts", "../../../../env.d.ts"]
8
+ }
@@ -0,0 +1,2 @@
1
+ // Generated — do not edit.
2
+ export const html = "<script>(function(){var e=(e,t)=>()=>(e&&(t=e(e=0)),t),t=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),n=t((e=>{Object.defineProperty(e,`__esModule`,{value:!0});function t(e){\"@babel/helpers - typeof\";return t=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},t(e)}var n=`clover`,r=function(e){return e===3?`v3`:e},i=`https://js.stripe.com`,a=`${i}/${n}/stripe.js`,o=/^https:\\/\\/js\\.stripe\\.com\\/v3\\/?(\\?.*)?$/,s=/^https:\\/\\/js\\.stripe\\.com\\/(v3|[a-z]+)\\/stripe\\.js(\\?.*)?$/,c=`loadStripe.setLoadParameters was called but an existing Stripe.js script already exists in the document; existing script parameters will be used`,l=function(e){return o.test(e)||s.test(e)},u=function(){for(var e=document.querySelectorAll(`script[src^=\"${i}\"]`),t=0;t<e.length;t++){var n=e[t];if(l(n.src))return n}return null},d=function(e){var t=e&&!e.advancedFraudSignals?`?advancedFraudSignals=false`:``,n=document.createElement(`script`);n.src=`${a}${t}`;var r=document.head||document.body;if(!r)throw Error(`Expected document.body not to be null. Stripe.js requires a <body> element.`);return r.appendChild(n),n},f=function(e,t){!e||!e._registerWrapper||e._registerWrapper({name:`stripe-js`,version:`8.9.0`,startTime:t})},p=null,m=null,h=null,g=function(e){return function(t){e(Error(`Failed to load Stripe.js`,{cause:t}))}},_=function(e,t){return function(){window.Stripe?e(window.Stripe):t(Error(`Stripe.js not available`))}},v=function(e){return p===null?(p=new Promise(function(t,n){if(typeof window>`u`||typeof document>`u`){t(null);return}if(window.Stripe&&e&&console.warn(c),window.Stripe){t(window.Stripe);return}try{var r=u();if(r&&e)console.warn(c);else if(!r)r=d(e);else if(r&&h!==null&&m!==null){var i;r.removeEventListener(`load`,h),r.removeEventListener(`error`,m),(i=r.parentNode)==null||i.removeChild(r),r=d(e)}h=_(t,n),m=g(n),r.addEventListener(`load`,h),r.addEventListener(`error`,m)}catch(e){n(e);return}}),p.catch(function(e){return p=null,Promise.reject(e)})):p},y=function(e,i,a){if(e===null)return null;var o=i[0];if(typeof o!=`string`)throw Error(`Expected publishable key to be of type string, got type ${t(o)} instead.`);var s=o.match(/^pk_test/),c=r(e.version),l=n;s&&c!==l&&console.warn(`Stripe.js@${c} was loaded on the page, but @stripe/stripe-js@8.9.0 expected Stripe.js@${l}. This may result in unexpected behavior. For more information, see https://docs.stripe.com/sdks/stripejs-versioning`);var u=e.apply(void 0,i);return f(u,a),u},b=function(e){var n=`invalid load parameters; expected object of shape\n\n {advancedFraudSignals: boolean}\n\nbut received\n\n ${JSON.stringify(e)}\n`;if(e===null||t(e)!==`object`)throw Error(n);if(Object.keys(e).length===1&&typeof e.advancedFraudSignals==`boolean`)return e;throw Error(n)},x,S=!1,C=function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];S=!0;var r=Date.now();return v(x).then(function(e){return y(e,t,r)})};C.setLoadParameters=function(e){if(S&&x){var t=b(e);if(Object.keys(t).reduce(function(t,n){return t&&e[n]===x?.[n]},!0))return}if(S)throw Error(`You cannot change load parameters after calling loadStripe`);x=b(e)},e.loadStripe=C})),r=t(((e,t)=>{t.exports=n()})),i,a=e((()=>{i=`0.1.1`}));function o(){return i}var s=e((()=>{a()}));function c(e,t){return t?.(e)?e:e&&typeof e==`object`&&`cause`in e&&e.cause?c(e.cause,t):t?null:e}var l,u=e((()=>{s(),l=class e extends Error{static setStaticOptions(t){e.prototype.docsOrigin=t.docsOrigin,e.prototype.showVersion=t.showVersion,e.prototype.version=t.version}constructor(t,n={}){let r=(()=>{if(n.cause instanceof e){if(n.cause.details)return n.cause.details;if(n.cause.shortMessage)return n.cause.shortMessage}return n.cause&&`details`in n.cause&&typeof n.cause.details==`string`?n.cause.details:n.cause?.message?n.cause.message:n.details})(),i=n.cause instanceof e&&n.cause.docsPath||n.docsPath,a=n.docsOrigin??e.prototype.docsOrigin,o=`${a}${i??``}`,s=!!(n.version??e.prototype.showVersion),c=n.version??e.prototype.version,l=[t||`An error occurred.`,...n.metaMessages?[``,...n.metaMessages]:[],...r||i||s?[``,r?`Details: ${r}`:void 0,i?`See: ${o}`:void 0,s?`Version: ${c}`:void 0]:[]].filter(e=>typeof e==`string`).join(`\n`);super(l,n.cause?{cause:n.cause}:void 0),Object.defineProperty(this,`details`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`docs`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`docsOrigin`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`docsPath`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`shortMessage`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`showVersion`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`version`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`cause`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`name`,{enumerable:!0,configurable:!0,writable:!0,value:`BaseError`}),this.cause=n.cause,this.details=r,this.docs=o,this.docsOrigin=a,this.docsPath=i,this.shortMessage=t,this.showVersion=s,this.version=c}walk(e){return c(this,e)}},Object.defineProperty(l,`defaultStaticOptions`,{enumerable:!0,configurable:!0,writable:!0,value:{docsOrigin:`https://oxlib.sh`,showVersion:!1,version:`ox@${o()}`}}),l.setStaticOptions(l.defaultStaticOptions)}));function d(e,t){if(v(e)>t)throw new b({givenSize:v(e),maxSize:t})}function f(e,t={}){let{dir:n,size:r=32}=t;if(r===0)return e;if(e.length>r)throw new x({size:e.length,targetSize:r,type:`Bytes`});let i=new Uint8Array(r);for(let t=0;t<r;t++){let a=n===`right`;i[a?t:r-t-1]=e[a?t:e.length-t-1]}return i}var p=e((()=>{S()}));function m(e){if(e===null||typeof e==`boolean`||typeof e==`string`)return JSON.stringify(e);if(typeof e==`number`){if(!Number.isFinite(e))throw TypeError(`Cannot canonicalize non-finite number`);return Object.is(e,-0)?`0`:JSON.stringify(e)}if(typeof e==`bigint`)throw TypeError(`Cannot canonicalize bigint`);if(Array.isArray(e))return`[${e.map(e=>m(e)).join(`,`)}]`;if(typeof e==`object`)return`{${Object.keys(e).sort().reduce((t,n)=>{let r=e[n];return r!==void 0&&t.push(`${JSON.stringify(n)}:${m(r)}`),t},[]).join(`,`)}}`}var h=e((()=>{}));function g(e,t={}){let{size:n}=t,r=y.encode(e);return typeof n==`number`?(d(r,n),_(r,n)):r}function _(e,t){return f(e,{dir:`right`,size:t})}function v(e){return e.length}var y,b,x,S=e((()=>{u(),p(),h(),y=new TextEncoder,b=class extends l{constructor({givenSize:e,maxSize:t}){super(`Size cannot exceed \\`${t}\\` bytes. Given size: \\`${e}\\` bytes.`),Object.defineProperty(this,`name`,{enumerable:!0,configurable:!0,writable:!0,value:`Bytes.SizeOverflowError`})}},x=class extends l{constructor({size:e,targetSize:t,type:n}){super(`${n.charAt(0).toUpperCase()}${n.slice(1).toLowerCase()} size (\\`${e}\\`) exceeds padding size (\\`${t}\\`).`),Object.defineProperty(this,`name`,{enumerable:!0,configurable:!0,writable:!0,value:`Bytes.SizeExceedsPaddingSizeError`})}}}));S();let C=new TextDecoder,w=Object.fromEntries(Array.from(`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`).map((e,t)=>[t,e.charCodeAt(0)]));({...Object.fromEntries(Array.from(`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`).map((e,t)=>[e.charCodeAt(0),t]))});function ee(e,t={}){let{pad:n=!0,url:r=!1}=t,i=new Uint8Array(Math.ceil(e.length/3)*4);for(let t=0,n=0;n<e.length;t+=4,n+=3){let r=(e[n]<<16)+(e[n+1]<<8)+(e[n+2]|0);i[t]=w[r>>18],i[t+1]=w[r>>12&63],i[t+2]=w[r>>6&63],i[t+3]=w[r&63]}let a=e.length%3,o=Math.floor(e.length/3)*4+(a&&a+1),s=C.decode(new Uint8Array(i.buffer,0,o));return n&&a===1&&(s+=`==`),n&&a===2&&(s+=`=`),r&&(s=s.replaceAll(`+`,`-`).replaceAll(`/`,`_`)),s}function te(e,t={}){return ee(g(e),t)}function ne(e){return te(m(e),{pad:!1,url:!0})}Object.freeze({status:`aborted`});function T(e,t,n){function r(n,r){if(n._zod||Object.defineProperty(n,`_zod`,{value:{def:r,constr:o,traits:new Set},enumerable:!1}),n._zod.traits.has(e))return;n._zod.traits.add(e),t(n,r);let i=o.prototype,a=Object.keys(i);for(let e=0;e<a.length;e++){let t=a[e];t in n||(n[t]=i[t].bind(n))}}let i=n?.Parent??Object;class a extends i{}Object.defineProperty(a,`name`,{value:e});function o(e){var t;let i=n?.Parent?new a:this;r(i,e),(t=i._zod).deferred??(t.deferred=[]);for(let e of i._zod.deferred)e();return i}return Object.defineProperty(o,`init`,{value:r}),Object.defineProperty(o,Symbol.hasInstance,{value:t=>n?.Parent&&t instanceof n.Parent?!0:t?._zod?.traits?.has(e)}),Object.defineProperty(o,`name`,{value:e}),o}var E=class extends Error{constructor(){super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`)}},re=class extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name=`ZodEncodeError`}};let D={};function O(e){return e&&Object.assign(D,e),D}function ie(e,t){return typeof t==`bigint`?t.toString():t}function ae(e){return{get value(){{let t=e();return Object.defineProperty(this,`value`,{value:t}),t}throw Error(`cached value already set`)}}}function oe(e){return e==null}function se(e){let t=e.startsWith(`^`)?1:0,n=e.endsWith(`$`)?e.length-1:e.length;return e.slice(t,n)}let ce=Symbol(`evaluating`);function k(e,t,n){let r;Object.defineProperty(e,t,{get(){if(r!==ce)return r===void 0&&(r=ce,r=n()),r},set(n){Object.defineProperty(e,t,{value:n})},configurable:!0})}let le=`captureStackTrace`in Error?Error.captureStackTrace:(...e)=>{};function A(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function ue(e){if(A(e)===!1)return!1;let t=e.constructor;if(t===void 0||typeof t!=`function`)return!0;let n=t.prototype;return!(A(n)===!1||Object.prototype.hasOwnProperty.call(n,`isPrototypeOf`)===!1)}function de(e,t,n){let r=new e._zod.constr(t??e._zod.def);return(!t||n?.parent)&&(r._zod.parent=e),r}function j(e){let t=e;if(!t)return{};if(typeof t==`string`)return{error:()=>t};if(t?.message!==void 0){if(t?.error!==void 0)throw Error(\"Cannot specify both `message` and `error` params\");t.error=t.message}return delete t.message,typeof t.error==`string`?{...t,error:()=>t.error}:t}function fe(e){return Object.keys(e).filter(t=>e[t]._zod.optin===`optional`&&e[t]._zod.optout===`optional`)}-Number.MAX_VALUE,Number.MAX_VALUE;function M(e,t=0){if(e.aborted===!0)return!0;for(let n=t;n<e.issues.length;n++)if(e.issues[n]?.continue!==!0)return!0;return!1}function N(e,t){return t.map(t=>{var n;return(n=t).path??(n.path=[]),t.path.unshift(e),t})}function P(e){return typeof e==`string`?e:e?.message}function F(e,t,n){let r={...e,path:e.path??[]};return e.message||(r.message=P(e.inst?._zod.def?.error?.(e))??P(t?.error?.(e))??P(n.customError?.(e))??P(n.localeError?.(e))??`Invalid input`),delete r.inst,delete r.continue,t?.reportInput||delete r.input,r}function pe(e){return Array.isArray(e)?`array`:typeof e==`string`?`string`:`unknown`}let I=(e,t)=>{e.name=`$ZodError`,Object.defineProperty(e,`_zod`,{value:e._zod,enumerable:!1}),Object.defineProperty(e,`issues`,{value:t,enumerable:!1}),e.message=JSON.stringify(t,ie,2),Object.defineProperty(e,`toString`,{value:()=>e.message,enumerable:!1})},me=T(`$ZodError`,I),L=T(`$ZodError`,I,{Parent:Error}),he=(e=>(t,n,r,i)=>{let a=r?Object.assign(r,{async:!1}):{async:!1},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise)throw new E;if(o.issues.length){let t=new(i?.Err??e)(o.issues.map(e=>F(e,a,O())));throw le(t,i?.callee),t}return o.value})(L),ge=(e=>async(t,n,r,i)=>{let a=r?Object.assign(r,{async:!0}):{async:!0},o=t._zod.run({value:n,issues:[]},a);if(o instanceof Promise&&(o=await o),o.issues.length){let t=new(i?.Err??e)(o.issues.map(e=>F(e,a,O())));throw le(t,i?.callee),t}return o.value})(L),R=(e=>(t,n,r)=>{let i=r?{...r,async:!1}:{async:!1},a=t._zod.run({value:n,issues:[]},i);if(a instanceof Promise)throw new E;return a.issues.length?{success:!1,error:new(e??me)(a.issues.map(e=>F(e,i,O())))}:{success:!0,data:a.value}})(L),z=(e=>async(t,n,r)=>{let i=r?Object.assign(r,{async:!0}):{async:!0},a=t._zod.run({value:n,issues:[]},i);return a instanceof Promise&&(a=await a),a.issues.length?{success:!1,error:new e(a.issues.map(e=>F(e,i,O())))}:{success:!0,data:a.value}})(L),_e=e=>{let t=e?`[\\\\s\\\\S]{${e?.minimum??0},${e?.maximum??``}}`:`[\\\\s\\\\S]*`;return RegExp(`^${t}$`)},B=/^-?\\d+(?:\\.\\d+)?$/,V=T(`$ZodCheck`,(e,t)=>{var n;e._zod??={},e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),ve=T(`$ZodCheckMinLength`,(e,t)=>{var n;V.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!oe(t)&&t.length!==void 0}),e._zod.onattach.push(e=>{let n=e._zod.bag.minimum??-1/0;t.minimum>n&&(e._zod.bag.minimum=t.minimum)}),e._zod.check=n=>{let r=n.value;if(r.length>=t.minimum)return;let i=pe(r);n.issues.push({origin:i,code:`too_small`,minimum:t.minimum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),ye=T(`$ZodCheckStringFormat`,(e,t)=>{var n,r;V.init(e,t),e._zod.onattach.push(e=>{let n=e._zod.bag;n.format=t.format,t.pattern&&(n.patterns??=new Set,n.patterns.add(t.pattern))}),t.pattern?(n=e._zod).check??(n.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:t.format,input:n.value,...t.pattern?{pattern:t.pattern.toString()}:{},inst:e,continue:!t.abort})}):(r=e._zod).check??(r.check=()=>{})}),be=T(`$ZodCheckRegex`,(e,t)=>{ye.init(e,t),e._zod.check=n=>{t.pattern.lastIndex=0,!t.pattern.test(n.value)&&n.issues.push({origin:`string`,code:`invalid_format`,format:`regex`,input:n.value,pattern:t.pattern.toString(),inst:e,continue:!t.abort})}}),xe={major:4,minor:3,patch:6},H=T(`$ZodType`,(e,t)=>{var n;e??={},e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=xe;let r=[...e._zod.def.checks??[]];e._zod.traits.has(`$ZodCheck`)&&r.unshift(e);for(let t of r)for(let n of t._zod.onattach)n(e);if(r.length===0)(n=e._zod).deferred??(n.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{let t=(e,t,n)=>{let r=M(e),i;for(let a of t){if(a._zod.def.when){if(!a._zod.def.when(e))continue}else if(r)continue;let t=e.issues.length,o=a._zod.check(e);if(o instanceof Promise&&n?.async===!1)throw new E;if(i||o instanceof Promise)i=(i??Promise.resolve()).then(async()=>{await o,e.issues.length!==t&&(r||=M(e,t))});else{if(e.issues.length===t)continue;r||=M(e,t)}}return i?i.then(()=>e):e},n=(n,i,a)=>{if(M(n))return n.aborted=!0,n;let o=t(i,r,a);if(o instanceof Promise){if(a.async===!1)throw new E;return o.then(t=>e._zod.parse(t,a))}return e._zod.parse(o,a)};e._zod.run=(i,a)=>{if(a.skipChecks)return e._zod.parse(i,a);if(a.direction===`backward`){let t=e._zod.parse({value:i.value,issues:[]},{...a,skipChecks:!0});return t instanceof Promise?t.then(e=>n(e,i,a)):n(t,i,a)}let o=e._zod.parse(i,a);if(o instanceof Promise){if(a.async===!1)throw new E;return o.then(e=>t(e,r,a))}return t(o,r,a)}}k(e,`~standard`,()=>({validate:t=>{try{let n=R(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch{return z(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:`zod`,version:1}))}),Se=T(`$ZodString`,(e,t)=>{H.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??_e(e._zod.bag),e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=String(n.value)}catch{}return typeof n.value==`string`||n.issues.push({expected:`string`,code:`invalid_type`,input:n.value,inst:e}),n}}),Ce=T(`$ZodNumber`,(e,t)=>{H.init(e,t),e._zod.pattern=e._zod.bag.pattern??B,e._zod.parse=(n,r)=>{if(t.coerce)try{n.value=Number(n.value)}catch{}let i=n.value;if(typeof i==`number`&&!Number.isNaN(i)&&Number.isFinite(i))return n;let a=typeof i==`number`?Number.isNaN(i)?`NaN`:Number.isFinite(i)?void 0:`Infinity`:void 0;return n.issues.push({expected:`number`,code:`invalid_type`,input:i,inst:e,...a?{received:a}:{}}),n}});function U(e,t,n){e.issues.length&&t.issues.push(...N(n,e.issues)),t.value[n]=e.value}let we=T(`$ZodArray`,(e,t)=>{H.init(e,t),e._zod.parse=(n,r)=>{let i=n.value;if(!Array.isArray(i))return n.issues.push({expected:`array`,code:`invalid_type`,input:i,inst:e}),n;n.value=Array(i.length);let a=[];for(let e=0;e<i.length;e++){let o=i[e],s=t.element._zod.run({value:o,issues:[]},r);s instanceof Promise?a.push(s.then(t=>U(t,n,e))):U(s,n,e)}return a.length?Promise.all(a).then(()=>n):n}});function W(e,t,n,r,i){if(e.issues.length){if(i&&!(n in r))return;t.issues.push(...N(n,e.issues))}e.value===void 0?n in r&&(t.value[n]=void 0):t.value[n]=e.value}function Te(e){let t=Object.keys(e.shape);for(let n of t)if(!e.shape?.[n]?._zod?.traits?.has(`$ZodType`))throw Error(`Invalid element at key \"${n}\": expected a Zod schema`);let n=fe(e.shape);return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}function Ee(e,t,n,r,i,a){let o=[],s=i.keySet,c=i.catchall._zod,l=c.def.type,u=c.optout===`optional`;for(let i in t){if(s.has(i))continue;if(l===`never`){o.push(i);continue}let a=c.run({value:t[i],issues:[]},r);a instanceof Promise?e.push(a.then(e=>W(e,n,i,t,u))):W(a,n,i,t,u)}return o.length&&n.issues.push({code:`unrecognized_keys`,keys:o,input:t,inst:a}),e.length?Promise.all(e).then(()=>n):n}let De=T(`$ZodObject`,(e,t)=>{if(H.init(e,t),!Object.getOwnPropertyDescriptor(t,`shape`)?.get){let e=t.shape;Object.defineProperty(t,`shape`,{get:()=>{let n={...e};return Object.defineProperty(t,`shape`,{value:n}),n}})}let n=ae(()=>Te(t));k(e._zod,`propValues`,()=>{let e=t.shape,n={};for(let t in e){let r=e[t]._zod;if(r.values){n[t]??(n[t]=new Set);for(let e of r.values)n[t].add(e)}}return n});let r=A,i=t.catchall,a;e._zod.parse=(t,o)=>{a??=n.value;let s=t.value;if(!r(s))return t.issues.push({expected:`object`,code:`invalid_type`,input:s,inst:e}),t;t.value={};let c=[],l=a.shape;for(let e of a.keys){let n=l[e],r=n._zod.optout===`optional`,i=n._zod.run({value:s[e],issues:[]},o);i instanceof Promise?c.push(i.then(n=>W(n,t,e,s,r))):W(i,t,e,s,r)}return i?Ee(c,s,t,o,n.value,e):c.length?Promise.all(c).then(()=>t):t}}),Oe=T(`$ZodRecord`,(e,t)=>{H.init(e,t),e._zod.parse=(n,r)=>{let i=n.value;if(!ue(i))return n.issues.push({expected:`record`,code:`invalid_type`,input:i,inst:e}),n;let a=[],o=t.keyType._zod.values;if(o){n.value={};let s=new Set;for(let e of o)if(typeof e==`string`||typeof e==`number`||typeof e==`symbol`){s.add(typeof e==`number`?e.toString():e);let o=t.valueType._zod.run({value:i[e],issues:[]},r);o instanceof Promise?a.push(o.then(t=>{t.issues.length&&n.issues.push(...N(e,t.issues)),n.value[e]=t.value})):(o.issues.length&&n.issues.push(...N(e,o.issues)),n.value[e]=o.value)}let c;for(let e in i)s.has(e)||(c??=[],c.push(e));c&&c.length>0&&n.issues.push({code:`unrecognized_keys`,input:i,inst:e,keys:c})}else{n.value={};for(let o of Reflect.ownKeys(i)){if(o===`__proto__`)continue;let s=t.keyType._zod.run({value:o,issues:[]},r);if(s instanceof Promise)throw Error(`Async schemas not supported in object keys currently`);if(typeof o==`string`&&B.test(o)&&s.issues.length){let e=t.keyType._zod.run({value:Number(o),issues:[]},r);if(e instanceof Promise)throw Error(`Async schemas not supported in object keys currently`);e.issues.length===0&&(s=e)}if(s.issues.length){t.mode===`loose`?n.value[o]=i[o]:n.issues.push({code:`invalid_key`,origin:`record`,issues:s.issues.map(e=>F(e,r,O())),input:o,path:[o],inst:e});continue}let c=t.valueType._zod.run({value:i[o],issues:[]},r);c instanceof Promise?a.push(c.then(e=>{e.issues.length&&n.issues.push(...N(o,e.issues)),n.value[s.value]=e.value})):(c.issues.length&&n.issues.push(...N(o,c.issues)),n.value[s.value]=c.value)}}return a.length?Promise.all(a).then(()=>n):n}}),ke=T(`$ZodTransform`,(e,t)=>{H.init(e,t),e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new re(e.constructor.name);let i=t.transform(n.value,n);if(r.async)return(i instanceof Promise?i:Promise.resolve(i)).then(e=>(n.value=e,n));if(i instanceof Promise)throw new E;return n.value=i,n}});function G(e,t){return e.issues.length&&t===void 0?{issues:[],value:void 0}:e}let Ae=T(`$ZodOptional`,(e,t)=>{H.init(e,t),e._zod.optin=`optional`,e._zod.optout=`optional`,k(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),k(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${se(e.source)})?$`):void 0}),e._zod.parse=(e,n)=>{if(t.innerType._zod.optin===`optional`){let r=t.innerType._zod.run(e,n);return r instanceof Promise?r.then(t=>G(t,e.value)):G(r,e.value)}return e.value===void 0?e:t.innerType._zod.run(e,n)}}),je=T(`$ZodPipe`,(e,t)=>{H.init(e,t),k(e._zod,`values`,()=>t.in._zod.values),k(e._zod,`optin`,()=>t.in._zod.optin),k(e._zod,`optout`,()=>t.out._zod.optout),k(e._zod,`propValues`,()=>t.in._zod.propValues),e._zod.parse=(e,n)=>{if(n.direction===`backward`){let r=t.out._zod.run(e,n);return r instanceof Promise?r.then(e=>K(e,t.in,n)):K(r,t.in,n)}let r=t.in._zod.run(e,n);return r instanceof Promise?r.then(e=>K(e,t.out,n)):K(r,t.out,n)}});function K(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues},n)}var Me,Ne=class{constructor(){this._map=new WeakMap,this._idmap=new Map}add(e,...t){let n=t[0];return this._map.set(e,n),n&&typeof n==`object`&&`id`in n&&this._idmap.set(n.id,e),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(e){let t=this._map.get(e);return t&&typeof t==`object`&&`id`in t&&this._idmap.delete(t.id),this._map.delete(e),this}get(e){let t=e._zod.parent;if(t){let n={...this.get(t)??{}};delete n.id;let r={...n,...this._map.get(e)};return Object.keys(r).length?r:void 0}return this._map.get(e)}has(e){return this._map.has(e)}};function Pe(){return new Ne}(Me=globalThis).__zod_globalRegistry??(Me.__zod_globalRegistry=Pe()),globalThis.__zod_globalRegistry;function Fe(e,t){return new e({type:`string`,...j(t)})}function Ie(e,t){return new e({type:`number`,checks:[],...j(t)})}function Le(e,t){return new ve({check:`min_length`,...j(t),minimum:e})}function Re(e,t){return new be({check:`string_format`,format:`regex`,...j(t),pattern:e})}let q=T(`ZodMiniType`,(e,t)=>{if(!e._zod)throw Error(`Uninitialized schema in ZodMiniType.`);H.init(e,t),e.def=t,e.type=t.type,e.parse=(t,n)=>he(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>R(e,t,n),e.parseAsync=async(t,n)=>ge(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>z(e,t,n),e.check=(...n)=>e.clone({...t,checks:[...t.checks??[],...n.map(e=>typeof e==`function`?{_zod:{check:e,def:{check:`custom`},onattach:[]}}:e)]},{parent:!0}),e.with=e.check,e.clone=(t,n)=>de(e,t,n),e.brand=()=>e,e.register=((t,n)=>(t.add(e,n),e)),e.apply=t=>t(e)}),ze=T(`ZodMiniString`,(e,t)=>{Se.init(e,t),q.init(e,t)});function J(e){return Fe(ze,e)}let Be=T(`ZodMiniNumber`,(e,t)=>{Ce.init(e,t),q.init(e,t)});function Ve(e){return Ie(Be,e)}let He=T(`ZodMiniArray`,(e,t)=>{we.init(e,t),q.init(e,t)});function Ue(e,t){return new He({type:`array`,element:e,...j(t)})}let We=T(`ZodMiniObject`,(e,t)=>{De.init(e,t),q.init(e,t),k(e,`shape`,()=>t.shape)});function Y(e,t){return new We({type:`object`,shape:e??{},...j(t)})}let Ge=T(`ZodMiniRecord`,(e,t)=>{Oe.init(e,t),q.init(e,t)});function Ke(e,t,n){return new Ge({type:`record`,keyType:e,valueType:t,...j(n)})}let qe=T(`ZodMiniTransform`,(e,t)=>{ke.init(e,t),q.init(e,t)});function Je(e){return new qe({type:`transform`,transform:e})}let Ye=T(`ZodMiniOptional`,(e,t)=>{Ae.init(e,t),q.init(e,t)});function X(e){return new Ye({type:`optional`,innerType:e})}let Xe=T(`ZodMiniPipe`,(e,t)=>{je.init(e,t),q.init(e,t)});function Ze(e,t){return new Xe({type:`pipe`,in:e,out:t})}function Qe(){return J().check(Re(/^\\d+(\\.\\d+)?$/,`Invalid amount`))}function $e(e){let t={challenge:{...e.challenge,request:ne(e.challenge.request)},payload:e.payload,...e.source&&{source:e.source}};return`Payment ${te(JSON.stringify(t),{pad:!1,url:!0})}`}function et(e){return e}function tt(e,t){let{context:n,createCredential:r}=t;return{...e,context:n,createCredential:r}}var Z,nt=e((()=>{Z=`2.47.6`}));function rt(e,t){return t?.(e)?e:e&&typeof e==`object`&&`cause`in e&&e.cause!==void 0?rt(e.cause,t):t?null:e}var Q,it;e((()=>{nt(),Q={getDocsUrl:({docsBaseUrl:e,docsPath:t=``,docsSlug:n})=>t?`${e??`https://viem.sh`}${t}${n?`#${n}`:``}`:void 0,version:`viem@${Z}`},it=class e extends Error{constructor(t,n={}){let r=n.cause instanceof e?n.cause.details:n.cause?.message?n.cause.message:n.details,i=n.cause instanceof e&&n.cause.docsPath||n.docsPath,a=Q.getDocsUrl?.({...n,docsPath:i}),o=[t||`An error occurred.`,``,...n.metaMessages?[...n.metaMessages,``]:[],...a?[`Docs: ${a}`]:[],...r?[`Details: ${r}`]:[],...Q.version?[`Version: ${Q.version}`]:[]].join(`\n`);super(o,n.cause?{cause:n.cause}:void 0),Object.defineProperty(this,`details`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`docsPath`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`metaMessages`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`shortMessage`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`version`,{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,`name`,{enumerable:!0,configurable:!0,writable:!0,value:`BaseError`}),this.details=r,this.docsPath=i,this.metaMessages=n.metaMessages,this.name=n.name??this.name,this.shortMessage=t,this.version=Z}walk(e){return rt(this,e)}}}))();var at=class extends it{constructor({value:e}){super(`Number \\`${e}\\` is not a valid decimal number.`,{name:`InvalidDecimalNumberError`})}};function ot(e,t){if(!/^(-?)([0-9]*)\\.?([0-9]*)$/.test(e))throw new at({value:e});let[n,r=`0`]=e.split(`.`),i=n.startsWith(`-`);if(i&&(n=n.slice(1)),r=r.replace(/(0+)$/,``),t===0)Math.round(Number(`.${r}`))===1&&(n=`${BigInt(n)+1n}`),r=``;else if(r.length>t){let[e,i,a]=[r.slice(0,t-1),r.slice(t-1,t),r.slice(t)],o=Math.round(Number(`${i}.${a}`));r=o>9?`${BigInt(e)+BigInt(1)}0`.padStart(e.length+1,`0`):`${e}${o}`,r.length>t&&(r=r.slice(1),n=`${BigInt(n)+1n}`),r=r.slice(0,t)}else r=r.padEnd(t,`0`);return BigInt(`${i?`-`:``}${n}${r}`)}let st=et({name:`stripe`,intent:`charge`,schema:{credential:{payload:Y({externalId:X(J()),spt:J()})},request:Ze(Y({amount:Qe(),currency:J(),decimals:Ve(),description:X(J()),externalId:X(J()),metadata:X(Ke(J(),J())),networkId:J(),paymentMethodTypes:Ue(J()).check(Le(1)),recipient:X(J())}),Je(({amount:e,decimals:t,metadata:n,networkId:r,paymentMethodTypes:i,...a})=>({...a,amount:ot(e,t).toString(),methodDetails:{networkId:r,paymentMethodTypes:i,...n!==void 0&&{metadata:n}}})))}});function ct(e){let{client:t,createToken:n,externalId:r,paymentMethod:i}=e;return tt(st,{context:Y({paymentMethod:X(J())}),async createCredential({challenge:e,context:a}){let o=a?.paymentMethod??i;if(!o)throw Error(`paymentMethod is required (pass via context or parameters)`);let s=e.request.amount,c=e.request.currency,l=e.request.methodDetails?.networkId;if(!l)throw Error(`networkId is required in challenge.methodDetails`);let u=e.request.methodDetails?.metadata;if(u?.externalId)throw Error(`methodDetails.metadata.externalId is reserved; use credential externalId instead`);return $e({challenge:e,payload:{spt:await n({amount:s,challenge:e,client:t,currency:c,expiresAt:e.expires?Math.floor(new Date(e.expires).getTime()/1e3):Math.floor(Date.now()/1e3)+3600,metadata:u,networkId:l,paymentMethod:o}),...r?{externalId:r}:{}}})}})}function lt(e){return[ct(e)]}(function(e){e.charge=ct})(lt||={});var ut=r();async function dt(e){let t=new URL(location.href);t.searchParams.set(`__mppx_worker`,``);let n=await navigator.serviceWorker.register(t.pathname+t.search),r=await new Promise(e=>{let t=n.installing??n.waiting??n.active;if(t?.state===`activated`)return e(t);let r=t??n;r.addEventListener(`statechange`,function t(){let i=n.active;i?.state===`activated`&&(r.removeEventListener(`statechange`,t),e(i))})});await new Promise(t=>{let n=new MessageChannel;n.port1.onmessage=()=>t(),r.postMessage({credential:e},[n.port2])}),location.reload()}let $=JSON.parse(document.getElementById(`__MPPX_DATA__`).textContent),ft=document.getElementById(`root`),pt=document.createElement(`h2`);pt.textContent=`stripe`,ft.appendChild(pt),(async()=>{let e=await(0,ut.loadStripe)($.config.publishableKey);if(!e)throw Error(`Failed to loadStripe`);let t=window.matchMedia(`(prefers-color-scheme: dark)`),n=()=>({theme:t.matches?`night`:`stripe`}),r=e.elements({amount:Number($.challenge.request.amount),appearance:n(),currency:$.challenge.request.currency,mode:`payment`,paymentMethodCreation:`manual`});t.addEventListener(`change`,()=>{r.update({appearance:n()})});let i=document.createElement(`form`);r.create(`payment`).mount(i),ft.appendChild(i);let a=document.createElement(`button`);a.textContent=`Pay`,a.type=`submit`,i.appendChild(a),i.onsubmit=async t=>{t.preventDefault(),a.disabled=!0;try{await r.submit();let{paymentMethod:t,error:n}=await e.createPaymentMethod({elements:r});if(n||!t)throw n??Error(`Failed to create payment method`);await dt(await lt({client:e,createToken:mt})[0].createCredential({challenge:$.challenge,context:{paymentMethod:t.id}}))}finally{a.disabled=!1}}})();async function mt(e){let t=new URL($.config.createTokenUrl,location.origin);if(t.origin!==location.origin)throw Error(`createTokenUrl must be same-origin`);let n=await fetch(t,{method:`POST`,headers:{\"Content-Type\":`application/json`},body:JSON.stringify(e)});if(!n.ok){let e=await n.text().catch(()=>`<response body unavailable>`);throw Error(`Failed to create SPT (${n.status}): ${e}`)}return(await n.json()).spt}})();</script>"
@@ -10,6 +10,7 @@ import {
10
10
  import { tempo as tempo_chain } from 'viem/chains'
11
11
  import { Abis, Transaction } from 'viem/tempo'
12
12
 
13
+ import { PaymentError, VerificationFailedError } from '../../Errors.js'
13
14
  import * as Expires from '../../Expires.js'
14
15
  import type { LooseOmit, NoExtraKeys } from '../../internal/types.js'
15
16
  import * as Method from '../../Method.js'
@@ -24,6 +25,7 @@ import * as Proof from '../internal/proof.js'
24
25
  import * as Selectors from '../internal/selectors.js'
25
26
  import type * as types from '../internal/types.js'
26
27
  import * as Methods from '../Methods.js'
28
+ import { html as htmlContent } from './internal/html.gen.js'
27
29
 
28
30
  /**
29
31
  * Creates a Tempo charge method intent for usage on the server.
@@ -47,6 +49,7 @@ export function charge<const parameters extends charge.Parameters>(
47
49
  decimals = defaults.decimals,
48
50
  description,
49
51
  externalId,
52
+ html,
50
53
  memo,
51
54
  waitForConfirmation = true,
52
55
  } = parameters
@@ -74,6 +77,8 @@ export function charge<const parameters extends charge.Parameters>(
74
77
  recipient,
75
78
  } as unknown as Defaults,
76
79
 
80
+ html: html ? { config: {}, content: htmlContent } : undefined,
81
+
77
82
  // TODO: dedupe `{charge,session}.request`
78
83
  async request({ credential, request }) {
79
84
  const chainId = await (async () => {
@@ -110,16 +115,17 @@ export function charge<const parameters extends charge.Parameters>(
110
115
 
111
116
  async verify({ credential, request }) {
112
117
  const { challenge } = credential
113
- const { chainId, feePayer } = request
118
+ const resolvedRequest = Methods.charge.schema.request.parse(request)
119
+ const chainId = resolvedRequest.methodDetails?.chainId ?? request.chainId
120
+ const feePayer = request.feePayer
114
121
 
115
122
  const client = await getClient({ chainId })
116
123
 
117
- const { request: challengeRequest } = challenge
118
- const { amount, methodDetails } = challengeRequest
124
+ const { amount, methodDetails } = resolvedRequest
119
125
  const expires = challenge.expires
120
126
 
121
- const currency = challengeRequest.currency as `0x${string}`
122
- const recipient = challengeRequest.recipient as `0x${string}`
127
+ const currency = resolvedRequest.currency as `0x${string}`
128
+ const recipient = resolvedRequest.recipient as `0x${string}`
123
129
 
124
130
  Expires.assert(expires, challenge.id)
125
131
 
@@ -292,6 +298,8 @@ export declare namespace charge {
292
298
  type Defaults = LooseOmit<Method.RequestDefaults<typeof Methods.charge>, 'feePayer' | 'recipient'>
293
299
 
294
300
  type Parameters = {
301
+ /** Render payment page when Accept header is text/html (e.g. in browsers) */
302
+ html?: boolean | undefined
295
303
  /** Testnet mode. */
296
304
  testnet?: boolean | undefined
297
305
  /**
@@ -530,7 +538,8 @@ async function assertHashUnused(
530
538
  hash: `0x${string}`,
531
539
  ): Promise<void> {
532
540
  const seen = await store.get(getHashStoreKey(hash))
533
- if (seen !== null) throw new Error('Transaction hash has already been used.')
541
+ if (seen !== null)
542
+ throw new VerificationFailedError({ reason: 'Transaction hash has already been used' })
534
543
  }
535
544
 
536
545
  /** @internal */
@@ -547,7 +556,8 @@ async function assertProofUnused(
547
556
  challengeId: string,
548
557
  ): Promise<void> {
549
558
  const seen = await store.get(getProofStoreKey(challengeId))
550
- if (seen !== null) throw new Error('Proof credential has already been used.')
559
+ if (seen !== null)
560
+ throw new VerificationFailedError({ reason: 'Proof credential has already been used' })
551
561
  }
552
562
 
553
563
  /** @internal */
@@ -573,8 +583,10 @@ function toReceipt(receipt: TransactionReceipt) {
573
583
  }
574
584
 
575
585
  /** @internal */
576
- class MismatchError extends Error {
586
+ class MismatchError extends PaymentError {
577
587
  override readonly name = 'MismatchError'
588
+ readonly title = 'Verification Failed'
589
+ readonly type = 'https://paymentauth.org/problems/verification-failed'
578
590
 
579
591
  constructor(reason: string, details: Record<string, string>) {
580
592
  super([reason, ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`)].join('\n'))
@@ -179,10 +179,11 @@ export function session<const parameters extends session.Parameters>(
179
179
  }
180
180
  },
181
181
 
182
- async verify({ credential }) {
182
+ async verify({ credential, request }) {
183
183
  const { challenge, payload } = credential as Credential.Credential<SessionCredentialPayload>
184
184
 
185
- const methodDetails = challenge.request.methodDetails as SessionMethodDetails
185
+ const resolvedRequest = Methods.session.schema.request.parse(request)
186
+ const methodDetails = resolvedRequest.methodDetails as SessionMethodDetails
186
187
  const client = await getClient({ chainId: methodDetails.chainId })
187
188
 
188
189
  const resolvedFeePayer = methodDetails.feePayer === true ? feePayer : undefined