mppx 0.5.1 → 0.5.4

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 (111) hide show
  1. package/CHANGELOG.md +20 -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/cli/cli.d.ts.map +1 -1
  11. package/dist/cli/cli.js +11 -9
  12. package/dist/cli/cli.js.map +1 -1
  13. package/dist/cli/plugins/tempo.d.ts.map +1 -1
  14. package/dist/cli/plugins/tempo.js +3 -3
  15. package/dist/cli/plugins/tempo.js.map +1 -1
  16. package/dist/cli/utils.d.ts +2 -0
  17. package/dist/cli/utils.d.ts.map +1 -1
  18. package/dist/cli/utils.js +10 -5
  19. package/dist/cli/utils.js.map +1 -1
  20. package/dist/proxy/Proxy.d.ts.map +1 -1
  21. package/dist/proxy/Proxy.js +52 -8
  22. package/dist/proxy/Proxy.js.map +1 -1
  23. package/dist/proxy/internal/Route.d.ts.map +1 -1
  24. package/dist/proxy/internal/Route.js +7 -3
  25. package/dist/proxy/internal/Route.js.map +1 -1
  26. package/dist/server/Mppx.d.ts.map +1 -1
  27. package/dist/server/Mppx.js +90 -71
  28. package/dist/server/Mppx.js.map +1 -1
  29. package/dist/server/Transport.d.ts +5 -1
  30. package/dist/server/Transport.d.ts.map +1 -1
  31. package/dist/server/Transport.js +71 -7
  32. package/dist/server/Transport.js.map +1 -1
  33. package/dist/server/internal/html/config.d.ts +144 -0
  34. package/dist/server/internal/html/config.d.ts.map +1 -0
  35. package/dist/server/internal/html/config.js +303 -0
  36. package/dist/server/internal/html/config.js.map +1 -0
  37. package/dist/server/internal/html/serviceWorker.gen.d.ts +2 -0
  38. package/dist/server/internal/html/serviceWorker.gen.d.ts.map +1 -0
  39. package/dist/server/internal/html/serviceWorker.gen.js +3 -0
  40. package/dist/server/internal/html/serviceWorker.gen.js.map +1 -0
  41. package/dist/stripe/internal/types.d.ts +6 -0
  42. package/dist/stripe/internal/types.d.ts.map +1 -1
  43. package/dist/stripe/server/Charge.d.ts +30 -16
  44. package/dist/stripe/server/Charge.d.ts.map +1 -1
  45. package/dist/stripe/server/Charge.js +35 -6
  46. package/dist/stripe/server/Charge.js.map +1 -1
  47. package/dist/stripe/server/internal/html/types.d.ts +2 -0
  48. package/dist/stripe/server/internal/html/types.d.ts.map +1 -0
  49. package/dist/stripe/server/internal/html/types.js +2 -0
  50. package/dist/stripe/server/internal/html/types.js.map +1 -0
  51. package/dist/stripe/server/internal/html.gen.d.ts +2 -0
  52. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -0
  53. package/dist/stripe/server/internal/html.gen.js +3 -0
  54. package/dist/stripe/server/internal/html.gen.js.map +1 -0
  55. package/dist/tempo/server/Charge.d.ts +33 -26
  56. package/dist/tempo/server/Charge.d.ts.map +1 -1
  57. package/dist/tempo/server/Charge.js +46 -11
  58. package/dist/tempo/server/Charge.js.map +1 -1
  59. package/dist/tempo/server/Session.d.ts.map +1 -1
  60. package/dist/tempo/server/Session.js +3 -2
  61. package/dist/tempo/server/Session.js.map +1 -1
  62. package/dist/tempo/server/internal/html.gen.d.ts +2 -0
  63. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -0
  64. package/dist/tempo/server/internal/html.gen.js +3 -0
  65. package/dist/tempo/server/internal/html.gen.js.map +1 -0
  66. package/dist/tempo/server/internal/transport.d.ts +1 -1
  67. package/dist/tempo/server/internal/transport.d.ts.map +1 -1
  68. package/dist/tempo/server/internal/transport.js +45 -58
  69. package/dist/tempo/server/internal/transport.js.map +1 -1
  70. package/package.json +2 -2
  71. package/src/Credential.ts +28 -4
  72. package/src/Method.ts +6 -1
  73. package/src/cli/cli.ts +11 -8
  74. package/src/cli/plugins/tempo.ts +3 -2
  75. package/src/cli/utils.test.ts +64 -0
  76. package/src/cli/utils.ts +10 -4
  77. package/src/env.d.ts +1 -0
  78. package/src/mcp-sdk/server/Transport.test.ts +6 -0
  79. package/src/proxy/Proxy.test.ts +188 -1
  80. package/src/proxy/Proxy.ts +58 -9
  81. package/src/proxy/internal/Route.test.ts +9 -0
  82. package/src/proxy/internal/Route.ts +5 -2
  83. package/src/server/Mppx.test.ts +171 -18
  84. package/src/server/Mppx.ts +120 -79
  85. package/src/server/Transport.test.ts +232 -2
  86. package/src/server/Transport.ts +84 -7
  87. package/src/server/internal/html/config.ts +414 -0
  88. package/src/server/internal/html/serviceWorker.client.ts +28 -0
  89. package/src/server/internal/html/serviceWorker.gen.ts +2 -0
  90. package/src/server/internal/html/serviceWorker.ts +27 -0
  91. package/src/server/internal/html/tsconfig.worker.client.json +8 -0
  92. package/src/server/internal/html/tsconfig.worker.json +8 -0
  93. package/src/stripe/internal/types.ts +20 -0
  94. package/src/stripe/server/Charge.ts +62 -6
  95. package/src/stripe/server/internal/html/main.ts +174 -0
  96. package/src/stripe/server/internal/html/node_modules/.bin/mppx.src +21 -0
  97. package/src/stripe/server/internal/html/package.json +9 -0
  98. package/src/stripe/server/internal/html/stripe-js-pure.d.ts +7 -0
  99. package/src/stripe/server/internal/html/tsconfig.json +8 -0
  100. package/src/stripe/server/internal/html/types.ts +5 -0
  101. package/src/stripe/server/internal/html.gen.ts +2 -0
  102. package/src/tempo/server/Charge.ts +64 -10
  103. package/src/tempo/server/Session.ts +3 -2
  104. package/src/tempo/server/internal/html/main.ts +111 -0
  105. package/src/tempo/server/internal/html/node_modules/.bin/mppx.src +21 -0
  106. package/src/tempo/server/internal/html/package.json +10 -0
  107. package/src/tempo/server/internal/html/tsconfig.json +8 -0
  108. package/src/tempo/server/internal/html.gen.ts +2 -0
  109. package/src/tempo/server/internal/transport.test.ts +37 -31
  110. package/src/tempo/server/internal/transport.ts +44 -58
  111. package/src/tsconfig.json +1 -1
@@ -3,8 +3,16 @@ import { PaymentActionRequiredError, VerificationFailedError } from '../../Error
3
3
  import * as Expires from '../../Expires.js'
4
4
  import type { LooseOmit, OneOf } from '../../internal/types.js'
5
5
  import * as Method from '../../Method.js'
6
- import type { StripeClient } from '../internal/types.js'
6
+ import type * as Html from '../../server/internal/html/config.ts'
7
+ import type * as z from '../../zod.js'
8
+ import type {
9
+ StripeClient,
10
+ CreatePaymentMethodFromElements,
11
+ StripeElementsOptionsMode,
12
+ StripePaymentElementOptions,
13
+ } from '../internal/types.js'
7
14
  import * as Methods from '../Methods.js'
15
+ import { html as htmlContent } from './internal/html.gen.js'
8
16
 
9
17
  /**
10
18
  * Creates a Stripe charge method intent for usage on the server.
@@ -38,6 +46,7 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
38
46
  decimals,
39
47
  description,
40
48
  externalId,
49
+ html: { text: htmlText, theme: htmlTheme, ...htmlConfig } = {},
41
50
  metadata,
42
51
  networkId,
43
52
  paymentMethodTypes,
@@ -59,9 +68,32 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
59
68
  paymentMethodTypes,
60
69
  } as unknown as Defaults,
61
70
 
62
- async verify({ credential }) {
71
+ html:
72
+ 'publishableKey' in htmlConfig && htmlConfig.publishableKey && htmlConfig.createTokenUrl
73
+ ? {
74
+ config: htmlConfig,
75
+ content: htmlContent,
76
+ formatAmount: (request: z.output<typeof Methods.charge.schema.request>) => {
77
+ try {
78
+ const formatter = new Intl.NumberFormat('en', {
79
+ style: 'currency',
80
+ currency: request.currency,
81
+ currencyDisplay: 'narrowSymbol',
82
+ })
83
+ const decimals = formatter.resolvedOptions().maximumFractionDigits ?? 2
84
+ return formatter.format(Number(request.amount) / 10 ** decimals)
85
+ } catch {
86
+ return `${request.currency}${request.amount}`
87
+ }
88
+ },
89
+ text: htmlText,
90
+ theme: htmlTheme,
91
+ }
92
+ : undefined,
93
+
94
+ async verify({ credential, request }) {
63
95
  const { challenge } = credential
64
- const { request } = challenge
96
+ const resolvedRequest = Methods.charge.schema.request.parse(request)
65
97
 
66
98
  Expires.assert(challenge.expires, challenge.id)
67
99
 
@@ -72,15 +104,23 @@ export function charge<const parameters extends charge.Parameters>(parameters: p
72
104
  externalId?: string
73
105
  }
74
106
 
75
- const userMetadata = request.methodDetails?.metadata as Record<string, string> | undefined
107
+ const userMetadata = resolvedRequest.methodDetails?.metadata as
108
+ | Record<string, string>
109
+ | undefined
76
110
  const resolvedMetadata = { ...buildAnalytics({ credential }), ...userMetadata }
77
111
 
78
112
  const pi = client
79
- ? await createWithClient({ client, challenge, request, spt, metadata: resolvedMetadata })
113
+ ? await createWithClient({
114
+ client,
115
+ challenge,
116
+ request: resolvedRequest,
117
+ spt,
118
+ metadata: resolvedMetadata,
119
+ })
80
120
  : await createWithSecretKey({
81
121
  secretKey: secretKey!,
82
122
  challenge,
83
- request,
123
+ request: resolvedRequest,
84
124
  spt,
85
125
  metadata: resolvedMetadata,
86
126
  })
@@ -108,6 +148,22 @@ export declare namespace charge {
108
148
  type Defaults = LooseOmit<Method.RequestDefaults<typeof Methods.charge>, 'recipient'>
109
149
 
110
150
  type Parameters = {
151
+ /** Render payment page when Accept header is text/html (e.g. in browsers) */
152
+ html?:
153
+ | {
154
+ createTokenUrl: string
155
+ elements?:
156
+ | {
157
+ options?: StripeElementsOptionsMode | undefined
158
+ paymentOptions?: StripePaymentElementOptions | undefined
159
+ createPaymentMethodOptions?: CreatePaymentMethodFromElements | undefined
160
+ }
161
+ | undefined
162
+ publishableKey: string
163
+ text?: Html.Text
164
+ theme?: Html.Theme
165
+ }
166
+ | undefined
111
167
  /** Optional metadata to include in SPT creation requests. */
112
168
  metadata?: Record<string, string> | undefined
113
169
  } & Defaults &
@@ -0,0 +1,174 @@
1
+ import type { Appearance } from '@stripe/stripe-js'
2
+ import { loadStripe } from '@stripe/stripe-js/pure'
3
+ import { Json } from 'ox'
4
+
5
+ import { stripe } from '../../../../client/index.js'
6
+ import * as Html from '../../../../server/internal/html/config.js'
7
+ import { submitCredential } from '../../../../server/internal/html/serviceWorker.client.js'
8
+ import type { charge as chargeClient } from '../../../../stripe/client/Charge.js'
9
+ import type { charge } from '../../../../stripe/server/Charge.js'
10
+ import type * as Methods from '../../../Methods.js'
11
+
12
+ const dataElement = document.getElementById(Html.dataId)!
13
+ const data = Json.parse(dataElement.textContent) as Html.Data<
14
+ typeof Methods.charge,
15
+ NonNullable<charge.Parameters['html']>
16
+ >
17
+
18
+ const root = document.getElementById(Html.rootId)!
19
+
20
+ const css = String.raw
21
+ const style = document.createElement('style')
22
+ style.textContent = css`
23
+ form {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: calc(${Html.vars.spacingUnit} * 8);
27
+ }
28
+ button {
29
+ background: ${Html.vars.accent};
30
+ border-radius: ${Html.vars.radius};
31
+ color: ${Html.vars.background};
32
+ cursor: pointer;
33
+ font-weight: 500;
34
+ padding: calc(${Html.vars.spacingUnit} * 4) calc(${Html.vars.spacingUnit} * 8);
35
+ width: 100%;
36
+ }
37
+ button:hover:not(:disabled) {
38
+ opacity: 0.85;
39
+ }
40
+ button:disabled {
41
+ cursor: default;
42
+ opacity: 0.5;
43
+ }
44
+ `
45
+ root.append(style)
46
+
47
+ ;(async () => {
48
+ if (import.meta.env.MODE === 'test') {
49
+ const button = document.createElement('button')
50
+ button.textContent = data.text.pay
51
+ root.appendChild(button)
52
+ button.onclick = async () => {
53
+ try {
54
+ button.disabled = true
55
+ const method = stripe({ createToken })[0]
56
+ const credential = await method.createCredential({
57
+ challenge: data.challenge,
58
+ context: { paymentMethod: 'pm_card_visa' },
59
+ })
60
+ await submitCredential(credential)
61
+ } catch (e) {
62
+ Html.showError(e instanceof Error ? e.message : 'Payment failed')
63
+ } finally {
64
+ button.disabled = false
65
+ }
66
+ }
67
+ return
68
+ }
69
+
70
+ const stripeJs = await loadStripe(data.config.publishableKey)
71
+ if (!stripeJs) throw new Error('Failed to loadStripe')
72
+
73
+ const darkQuery = window.matchMedia('(prefers-color-scheme: dark)')
74
+ const getAppearance = () => {
75
+ const theme = (() => {
76
+ if (data.config.elements?.options?.appearance?.theme)
77
+ return data.config.elements?.options?.appearance?.theme
78
+ switch (data.theme.colorScheme) {
79
+ case 'light dark':
80
+ return (darkQuery.matches ? 'night' : 'stripe') as 'night' | 'stripe'
81
+ case 'light':
82
+ return 'stripe' as const
83
+ case 'dark':
84
+ return 'night' as const
85
+ }
86
+ })()
87
+ const resolvedColorSchemeIndex = darkQuery.matches ? 1 : 0
88
+ return Html.mergeDefined(
89
+ {
90
+ disableAnimations: true,
91
+ theme,
92
+ variables: {
93
+ borderRadius: data.theme.radius,
94
+ colorBackground: data.theme.surface[resolvedColorSchemeIndex],
95
+ colorDanger: data.theme.negative[resolvedColorSchemeIndex],
96
+ colorPrimary: data.theme.accent[resolvedColorSchemeIndex],
97
+ colorText: data.theme.foreground[resolvedColorSchemeIndex],
98
+ colorTextSecondary: data.theme.muted[resolvedColorSchemeIndex],
99
+ fontSizeBase: data.theme.fontSizeBase,
100
+ fontFamily: data.theme.fontFamily,
101
+ spacingUnit: data.theme.spacingUnit,
102
+ },
103
+ } satisfies Appearance,
104
+ (data.config.elements?.options?.appearance as never) ?? {},
105
+ )
106
+ }
107
+
108
+ const elements = stripeJs.elements({
109
+ appearance: getAppearance(),
110
+ ...data.config.elements?.options,
111
+ amount: Number(data.challenge.request.amount),
112
+ currency: data.challenge.request.currency,
113
+ mode: 'payment',
114
+ paymentMethodCreation: 'manual',
115
+ paymentMethodTypes: data.challenge.request.methodDetails.paymentMethodTypes,
116
+ })
117
+
118
+ darkQuery.addEventListener('change', () => {
119
+ elements.update({ appearance: getAppearance() })
120
+ })
121
+
122
+ const form = document.createElement('form')
123
+ elements.create('payment', data.config.elements?.paymentOptions).mount(form)
124
+ root.appendChild(form)
125
+
126
+ const button = document.createElement('button')
127
+ button.textContent = data.text.pay
128
+ button.type = 'submit'
129
+ form.appendChild(button)
130
+
131
+ form.onsubmit = async (event) => {
132
+ event.preventDefault()
133
+ document.getElementById(Html.errorId)?.remove()
134
+ button.disabled = true
135
+ try {
136
+ await elements.submit()
137
+ const { paymentMethod, error: stripeError } = await stripeJs.createPaymentMethod({
138
+ ...data.config.elements?.createPaymentMethodOptions,
139
+ elements,
140
+ })
141
+ if (stripeError || !paymentMethod)
142
+ throw stripeError ?? new Error('Failed to create payment method')
143
+ const method = stripe({ client: stripeJs, createToken })[0]
144
+ const credential = await method.createCredential({
145
+ challenge: data.challenge,
146
+ context: { paymentMethod: paymentMethod.id },
147
+ })
148
+ await submitCredential(credential)
149
+ } catch (e) {
150
+ Html.showError(e instanceof Error ? e.message : 'Payment failed')
151
+ } finally {
152
+ button.disabled = false
153
+ }
154
+ }
155
+ })()
156
+
157
+ async function createToken(opts: chargeClient.OnChallengeParameters) {
158
+ const createTokenUrl = new URL(data.config.createTokenUrl, location.origin)
159
+ if (createTokenUrl.origin !== location.origin)
160
+ throw new Error('createTokenUrl must be same-origin')
161
+ const res = await fetch(createTokenUrl, {
162
+ method: 'POST',
163
+ headers: { 'Content-Type': 'application/json' },
164
+ body: JSON.stringify(opts),
165
+ })
166
+ if (!res.ok) {
167
+ const text = await res.text().catch(() => '<response body unavailable>')
168
+ throw new Error(`Failed to create SPT (${res.status}): ${text}`)
169
+ }
170
+ const json = (await res.json()) as { spt: string }
171
+ return json.spt
172
+ }
173
+
174
+ dataElement.remove()
@@ -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,5 @@
1
+ export type {
2
+ CreatePaymentMethodFromElements,
3
+ StripeElementsOptionsMode,
4
+ StripePaymentElementOptions,
5
+ } from '@stripe/stripe-js'
@@ -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}))}},ee=function(e,t){return function(){window.Stripe?e(window.Stripe):t(Error(`Stripe.js not available`))}},te=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=ee(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},ne=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},_=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)},v,y=!1,b=function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];y=!0;var r=Date.now();return te(v).then(function(e){return ne(e,t,r)})};b.setLoadParameters=function(e){if(y&&v){var t=_(e);if(Object.keys(t).reduce(function(t,n){return t&&e[n]===v?.[n]},!0))return}if(y)throw Error(`You cannot change load parameters after calling loadStripe`);v=_(e)},e.loadStripe=b})),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(_(e)>t)throw new y({givenSize:_(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 b({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((()=>{re()}));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(`,`)}}`}function h(e,t){return JSON.parse(e,(e,n)=>{let r=n;return typeof r==`string`&&r.endsWith(g)?BigInt(r.slice(0,-9)):typeof t==`function`?t(e,r):r})}var g,ee=e((()=>{g=`#__bigint`}));function te(e,t={}){let{size:n}=t,r=v.encode(e);return typeof n==`number`?(d(r,n),ne(r,n)):r}function ne(e,t){return f(e,{dir:`right`,size:t})}function _(e){return e.length}var v,y,b,re=e((()=>{u(),p(),ee(),v=new TextEncoder,y=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`})}},b=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`})}}}));re();let ie=new TextDecoder,x=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 ae(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]=x[r>>18],i[t+1]=x[r>>12&63],i[t+2]=x[r>>6&63],i[t+3]=x[r&63]}let a=e.length%3,o=Math.floor(e.length/3)*4+(a&&a+1),s=ie.decode(new Uint8Array(i.buffer,0,o));return n&&a===1&&(s+=`==`),n&&a===2&&(s+=`=`),r&&(s=s.replaceAll(`+`,`-`).replaceAll(`/`,`_`)),s}function S(e,t={}){return ae(te(e),t)}function oe(e){return S(m(e),{pad:!1,url:!0})}Object.freeze({status:`aborted`});function C(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 w=class extends Error{constructor(){super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`)}},se=class extends Error{constructor(e){super(`Encountered unidirectional transform during encode: ${e}`),this.name=`ZodEncodeError`}};let ce={};function T(e){return e&&Object.assign(ce,e),ce}function le(e,t){return typeof t==`bigint`?t.toString():t}function ue(e){return{get value(){{let t=e();return Object.defineProperty(this,`value`,{value:t}),t}throw Error(`cached value already set`)}}}function de(e){return e==null}function fe(e){let t=e.startsWith(`^`)?1:0,n=e.endsWith(`$`)?e.length-1:e.length;return e.slice(t,n)}let pe=Symbol(`evaluating`);function E(e,t,n){let r;Object.defineProperty(e,t,{get(){if(r!==pe)return r===void 0&&(r=pe,r=n()),r},set(n){Object.defineProperty(e,t,{value:n})},configurable:!0})}let D=`captureStackTrace`in Error?Error.captureStackTrace:(...e)=>{};function O(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function me(e){if(O(e)===!1)return!1;let t=e.constructor;if(t===void 0||typeof t!=`function`)return!0;let n=t.prototype;return!(O(n)===!1||Object.prototype.hasOwnProperty.call(n,`isPrototypeOf`)===!1)}function he(e,t,n){let r=new e._zod.constr(t??e._zod.def);return(!t||n?.parent)&&(r._zod.parent=e),r}function k(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 ge(e){return Object.keys(e).filter(t=>e[t]._zod.optin===`optional`&&e[t]._zod.optout===`optional`)}-Number.MAX_VALUE,Number.MAX_VALUE;function A(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 j(e,t){return t.map(t=>{var n;return(n=t).path??(n.path=[]),t.path.unshift(e),t})}function M(e){return typeof e==`string`?e:e?.message}function N(e,t,n){let r={...e,path:e.path??[]};return e.message||(r.message=M(e.inst?._zod.def?.error?.(e))??M(t?.error?.(e))??M(n.customError?.(e))??M(n.localeError?.(e))??`Invalid input`),delete r.inst,delete r.continue,t?.reportInput||delete r.input,r}function _e(e){return Array.isArray(e)?`array`:typeof e==`string`?`string`:`unknown`}let ve=(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,le,2),Object.defineProperty(e,`toString`,{value:()=>e.message,enumerable:!1})},ye=C(`$ZodError`,ve),P=C(`$ZodError`,ve,{Parent:Error}),be=(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 w;if(o.issues.length){let t=new(i?.Err??e)(o.issues.map(e=>N(e,a,T())));throw D(t,i?.callee),t}return o.value})(P),xe=(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=>N(e,a,T())));throw D(t,i?.callee),t}return o.value})(P),F=(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 w;return a.issues.length?{success:!1,error:new(e??ye)(a.issues.map(e=>N(e,i,T())))}:{success:!0,data:a.value}})(P),I=(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=>N(e,i,T())))}:{success:!0,data:a.value}})(P),Se=e=>{let t=e?`[\\\\s\\\\S]{${e?.minimum??0},${e?.maximum??``}}`:`[\\\\s\\\\S]*`;return RegExp(`^${t}$`)},Ce=/^-?\\d+(?:\\.\\d+)?$/,we=C(`$ZodCheck`,(e,t)=>{var n;e._zod??={},e._zod.def=t,(n=e._zod).onattach??(n.onattach=[])}),Te=C(`$ZodCheckMinLength`,(e,t)=>{var n;we.init(e,t),(n=e._zod.def).when??(n.when=e=>{let t=e.value;return!de(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=_e(r);n.issues.push({origin:i,code:`too_small`,minimum:t.minimum,inclusive:!0,input:r,inst:e,continue:!t.abort})}}),Ee=C(`$ZodCheckStringFormat`,(e,t)=>{var n,r;we.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=()=>{})}),De=C(`$ZodCheckRegex`,(e,t)=>{Ee.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})}}),Oe={major:4,minor:3,patch:6},L=C(`$ZodType`,(e,t)=>{var n;e??={},e._zod.def=t,e._zod.bag=e._zod.bag||{},e._zod.version=Oe;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=A(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 w;if(i||o instanceof Promise)i=(i??Promise.resolve()).then(async()=>{await o,e.issues.length!==t&&(r||=A(e,t))});else{if(e.issues.length===t)continue;r||=A(e,t)}}return i?i.then(()=>e):e},n=(n,i,a)=>{if(A(n))return n.aborted=!0,n;let o=t(i,r,a);if(o instanceof Promise){if(a.async===!1)throw new w;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 w;return o.then(e=>t(e,r,a))}return t(o,r,a)}}E(e,`~standard`,()=>({validate:t=>{try{let n=F(e,t);return n.success?{value:n.data}:{issues:n.error?.issues}}catch{return I(e,t).then(e=>e.success?{value:e.data}:{issues:e.error?.issues})}},vendor:`zod`,version:1}))}),ke=C(`$ZodString`,(e,t)=>{L.init(e,t),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??Se(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}}),Ae=C(`$ZodNumber`,(e,t)=>{L.init(e,t),e._zod.pattern=e._zod.bag.pattern??Ce,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 je(e,t,n){e.issues.length&&t.issues.push(...j(n,e.issues)),t.value[n]=e.value}let Me=C(`$ZodArray`,(e,t)=>{L.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=>je(t,n,e))):je(s,n,e)}return a.length?Promise.all(a).then(()=>n):n}});function R(e,t,n,r,i){if(e.issues.length){if(i&&!(n in r))return;t.issues.push(...j(n,e.issues))}e.value===void 0?n in r&&(t.value[n]=void 0):t.value[n]=e.value}function Ne(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=ge(e.shape);return{...e,keys:t,keySet:new Set(t),numKeys:t.length,optionalKeys:new Set(n)}}function Pe(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=>R(e,n,i,t,u))):R(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 Fe=C(`$ZodObject`,(e,t)=>{if(L.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=ue(()=>Ne(t));E(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=O,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=>R(n,t,e,s,r))):R(i,t,e,s,r)}return i?Pe(c,s,t,o,n.value,e):c.length?Promise.all(c).then(()=>t):t}}),Ie=C(`$ZodRecord`,(e,t)=>{L.init(e,t),e._zod.parse=(n,r)=>{let i=n.value;if(!me(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(...j(e,t.issues)),n.value[e]=t.value})):(o.issues.length&&n.issues.push(...j(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`&&Ce.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=>N(e,r,T())),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(...j(o,e.issues)),n.value[s.value]=e.value})):(c.issues.length&&n.issues.push(...j(o,c.issues)),n.value[s.value]=c.value)}}return a.length?Promise.all(a).then(()=>n):n}}),Le=C(`$ZodTransform`,(e,t)=>{L.init(e,t),e._zod.parse=(n,r)=>{if(r.direction===`backward`)throw new se(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 w;return n.value=i,n}});function z(e,t){return e.issues.length&&t===void 0?{issues:[],value:void 0}:e}let Re=C(`$ZodOptional`,(e,t)=>{L.init(e,t),e._zod.optin=`optional`,e._zod.optout=`optional`,E(e._zod,`values`,()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),E(e._zod,`pattern`,()=>{let e=t.innerType._zod.pattern;return e?RegExp(`^(${fe(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=>z(t,e.value)):z(r,e.value)}return e.value===void 0?e:t.innerType._zod.run(e,n)}}),ze=C(`$ZodPipe`,(e,t)=>{L.init(e,t),E(e._zod,`values`,()=>t.in._zod.values),E(e._zod,`optin`,()=>t.in._zod.optin),E(e._zod,`optout`,()=>t.out._zod.optout),E(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=>B(e,t.in,n)):B(r,t.in,n)}let r=t.in._zod.run(e,n);return r instanceof Promise?r.then(e=>B(e,t.out,n)):B(r,t.out,n)}});function B(e,t,n){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues},n)}var V,Be=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 Ve(){return new Be}(V=globalThis).__zod_globalRegistry??(V.__zod_globalRegistry=Ve()),globalThis.__zod_globalRegistry;function He(e,t){return new e({type:`string`,...k(t)})}function Ue(e,t){return new e({type:`number`,checks:[],...k(t)})}function We(e,t){return new Te({check:`min_length`,...k(t),minimum:e})}function Ge(e,t){return new De({check:`string_format`,format:`regex`,...k(t),pattern:e})}let H=C(`ZodMiniType`,(e,t)=>{if(!e._zod)throw Error(`Uninitialized schema in ZodMiniType.`);L.init(e,t),e.def=t,e.type=t.type,e.parse=(t,n)=>be(e,t,n,{callee:e.parse}),e.safeParse=(t,n)=>F(e,t,n),e.parseAsync=async(t,n)=>xe(e,t,n,{callee:e.parseAsync}),e.safeParseAsync=async(t,n)=>I(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)=>he(e,t,n),e.brand=()=>e,e.register=((t,n)=>(t.add(e,n),e)),e.apply=t=>t(e)}),Ke=C(`ZodMiniString`,(e,t)=>{ke.init(e,t),H.init(e,t)});function U(e){return He(Ke,e)}let qe=C(`ZodMiniNumber`,(e,t)=>{Ae.init(e,t),H.init(e,t)});function Je(e){return Ue(qe,e)}let Ye=C(`ZodMiniArray`,(e,t)=>{Me.init(e,t),H.init(e,t)});function Xe(e,t){return new Ye({type:`array`,element:e,...k(t)})}let Ze=C(`ZodMiniObject`,(e,t)=>{Fe.init(e,t),H.init(e,t),E(e,`shape`,()=>t.shape)});function W(e,t){return new Ze({type:`object`,shape:e??{},...k(t)})}let Qe=C(`ZodMiniRecord`,(e,t)=>{Ie.init(e,t),H.init(e,t)});function $e(e,t,n){return new Qe({type:`record`,keyType:e,valueType:t,...k(n)})}let et=C(`ZodMiniTransform`,(e,t)=>{Le.init(e,t),H.init(e,t)});function tt(e){return new et({type:`transform`,transform:e})}let nt=C(`ZodMiniOptional`,(e,t)=>{Re.init(e,t),H.init(e,t)});function G(e){return new nt({type:`optional`,innerType:e})}let rt=C(`ZodMiniPipe`,(e,t)=>{ze.init(e,t),H.init(e,t)});function it(e,t){return new rt({type:`pipe`,in:e,out:t})}function at(){return U().check(Ge(/^\\d+(\\.\\d+)?$/,`Invalid amount`))}function ot(e){let t={challenge:{...e.challenge,request:oe(e.challenge.request)},payload:e.payload,...e.source&&{source:e.source}};return`Payment ${S(JSON.stringify(t),{pad:!1,url:!0})}`}function st(e){return e}function ct(e,t){let{context:n,createCredential:r}=t;return{...e,context:n,createCredential:r}}var K,lt=e((()=>{K=`2.47.6`}));function ut(e,t){return t?.(e)?e:e&&typeof e==`object`&&`cause`in e&&e.cause!==void 0?ut(e.cause,t):t?null:e}var q,dt;e((()=>{lt(),q={getDocsUrl:({docsBaseUrl:e,docsPath:t=``,docsSlug:n})=>t?`${e??`https://viem.sh`}${t}${n?`#${n}`:``}`:void 0,version:`viem@${K}`},dt=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=K}walk(e){return ut(this,e)}}}))();var ft=class extends dt{constructor({value:e}){super(`Number \\`${e}\\` is not a valid decimal number.`,{name:`InvalidDecimalNumberError`})}};function pt(e,t){if(!/^(-?)([0-9]*)\\.?([0-9]*)$/.test(e))throw new ft({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 mt=st({name:`stripe`,intent:`charge`,schema:{credential:{payload:W({externalId:G(U()),spt:U()})},request:it(W({amount:at(),currency:U(),decimals:Je(),description:G(U()),externalId:G(U()),metadata:G($e(U(),U())),networkId:U(),paymentMethodTypes:Xe(U()).check(We(1)),recipient:G(U())}),tt(({amount:e,decimals:t,metadata:n,networkId:r,paymentMethodTypes:i,...a})=>({...a,amount:pt(e,t).toString(),methodDetails:{networkId:r,paymentMethodTypes:i,...n!==void 0&&{metadata:n}}})))}});function ht(e){let{client:t,createToken:n,externalId:r,paymentMethod:i}=e;return ct(mt,{context:W({paymentMethod:G(U())}),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 ot({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 gt(e){return[ht(e)]}(function(e){e.charge=ht})(gt||={});var _t=r();let J=`root_error`,vt=`root`,yt={error:`mppx-error`,header:`mppx-header`,logo:`mppx-logo`,logoColorScheme:e=>e===`dark`||e===`light`?`${yt.logo}--${e}`:void 0,summary:`mppx-summary`,summaryAmount:`mppx-summary-amount`,summaryDescription:`mppx-summary-description`,summaryExpires:`mppx-summary-expires`},bt=String.raw;var Y=class{name;constructor(e){this.name=`--mppx-${e}`}toString(){return`var(${this.name})`}};let X={accent:new Y(`accent`),background:new Y(`background`),border:new Y(`border`),foreground:new Y(`foreground`),muted:new Y(`muted`),negative:new Y(`negative`),positive:new Y(`positive`),surface:new Y(`surface`),fontFamily:new Y(`font-family`),fontSizeBase:new Y(`font-size-base`),radius:new Y(`radius`),spacingUnit:new Y(`spacing-unit`)};function xt(e){let t=document.getElementById(J);if(t){t.textContent=e;return}let n=document.createElement(`p`);n.id=J,n.className=yt.error,n.role=`alert`,n.textContent=e,document.getElementById(vt)?.after(n)}function Z(e,t){if(t===void 0)return e;if(!Q(e)||!Q(t))return t??e;let n={...e};for(let[e,r]of Object.entries(t)){if(r===void 0)continue;let t=n[e];n[e]=Q(t)&&Q(r)?Z(t,r):r}return n}function Q(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}bt`\n *, ::after, ::before, ::backdrop, ::file-selector-button { box-sizing: border-box; margin: 0;\n padding: 0; border: 0 solid; border-color: ${X.border}; } html, :host { line-height: 1.5;\n -webkit-text-size-adjust: 100%; tab-size: 4; -webkit-tap-highlight-color: transparent; } h1, h2,\n h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; } a { color: inherit;\n -webkit-text-decoration: inherit; text-decoration: inherit; } b, strong { font-weight: bolder; }\n code, kbd, samp, pre { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,\n 'Liberation Mono', 'Courier New', monospace; font-size: 1em; } small { font-size: 80%; } ol, ul,\n menu { list-style: none; } img, svg, video, canvas, audio, iframe, embed, object { display: block;\n vertical-align: middle; } img, video { max-width: 100%; height: auto; } button, input, select,\n optgroup, textarea, ::file-selector-button { font: inherit; font-feature-settings: inherit;\n font-variation-settings: inherit; letter-spacing: inherit; color: inherit; border-radius: 0;\n background-color: transparent; opacity: 1; } ::file-selector-button { margin-inline-end: 4px; }\n ::placeholder { opacity: 1; } @supports (not (-webkit-appearance: -apple-pay-button)) or\n (contain-intrinsic-size: 1px) { ::placeholder { color: color-mix(in oklab, currentcolor 50%,\n transparent); } } textarea { resize: vertical; } ::-webkit-search-decoration { -webkit-appearance:\n none; } :-moz-ui-invalid { box-shadow: none; } button, input:where([type='button'],\n [type='reset'], [type='submit']), ::file-selector-button { appearance: button; }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; }\n [hidden]:where(:not([hidden='until-found'])) { display: none !important; }\n`;async function St(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 Ct=document.getElementById(`__MPPX_DATA__`),$=h(Ct.textContent),wt=document.getElementById(vt),Tt=String.raw,Et=document.createElement(`style`);Et.textContent=Tt`\n form {\n display: flex;\n flex-direction: column;\n gap: calc(${X.spacingUnit} * 8);\n }\n button {\n background: ${X.accent};\n border-radius: ${X.radius};\n color: ${X.background};\n cursor: pointer;\n font-weight: 500;\n padding: calc(${X.spacingUnit} * 4) calc(${X.spacingUnit} * 8);\n width: 100%;\n }\n button:hover:not(:disabled) {\n opacity: 0.85;\n }\n button:disabled {\n cursor: default;\n opacity: 0.5;\n }\n`,wt.append(Et),(async()=>{let e=await(0,_t.loadStripe)($.config.publishableKey);if(!e)throw Error(`Failed to loadStripe`);let t=window.matchMedia(`(prefers-color-scheme: dark)`),n=()=>{let e=(()=>{if($.config.elements?.options?.appearance?.theme)return $.config.elements?.options?.appearance?.theme;switch($.theme.colorScheme){case`light dark`:return t.matches?`night`:`stripe`;case`light`:return`stripe`;case`dark`:return`night`}})(),n=t.matches?1:0;return Z({disableAnimations:!0,theme:e,variables:{borderRadius:$.theme.radius,colorBackground:$.theme.surface[n],colorDanger:$.theme.negative[n],colorPrimary:$.theme.accent[n],colorText:$.theme.foreground[n],colorTextSecondary:$.theme.muted[n],fontSizeBase:$.theme.fontSizeBase,fontFamily:$.theme.fontFamily,spacingUnit:$.theme.spacingUnit}},$.config.elements?.options?.appearance??{})},r=e.elements({appearance:n(),...$.config.elements?.options,amount:Number($.challenge.request.amount),currency:$.challenge.request.currency,mode:`payment`,paymentMethodCreation:`manual`,paymentMethodTypes:$.challenge.request.methodDetails.paymentMethodTypes});t.addEventListener(`change`,()=>{r.update({appearance:n()})});let i=document.createElement(`form`);r.create(`payment`,$.config.elements?.paymentOptions).mount(i),wt.appendChild(i);let a=document.createElement(`button`);a.textContent=$.text.pay,a.type=`submit`,i.appendChild(a),i.onsubmit=async t=>{t.preventDefault(),document.getElementById(J)?.remove(),a.disabled=!0;try{await r.submit();let{paymentMethod:t,error:n}=await e.createPaymentMethod({...$.config.elements?.createPaymentMethodOptions,elements:r});if(n||!t)throw n??Error(`Failed to create payment method`);await St(await gt({client:e,createToken:Dt})[0].createCredential({challenge:$.challenge,context:{paymentMethod:t.id}}))}catch(e){xt(e instanceof Error?e.message:`Payment failed`)}finally{a.disabled=!1}}})();async function Dt(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}Ct.remove()})();</script>"
@@ -1,4 +1,10 @@
1
- import { decodeFunctionData, keccak256, parseEventLogs, type TransactionReceipt } from 'viem'
1
+ import {
2
+ decodeFunctionData,
3
+ formatUnits,
4
+ keccak256,
5
+ parseEventLogs,
6
+ type TransactionReceipt,
7
+ } from 'viem'
2
8
  import {
3
9
  getTransactionReceipt,
4
10
  sendRawTransaction,
@@ -8,13 +14,16 @@ import {
8
14
  call as viem_call,
9
15
  } from 'viem/actions'
10
16
  import { tempo as tempo_chain } from 'viem/chains'
11
- import { Abis, Transaction } from 'viem/tempo'
17
+ import { Abis, Actions, Transaction } from 'viem/tempo'
12
18
 
19
+ import { PaymentError, VerificationFailedError } from '../../Errors.js'
13
20
  import * as Expires from '../../Expires.js'
14
21
  import type { LooseOmit, NoExtraKeys } from '../../internal/types.js'
15
22
  import * as Method from '../../Method.js'
23
+ import type * as Html from '../../server/internal/html/config.ts'
16
24
  import * as Store from '../../Store.js'
17
25
  import * as Client from '../../viem/Client.js'
26
+ import type * as z from '../../zod.js'
18
27
  import * as Account from '../internal/account.js'
19
28
  import * as TempoAddress from '../internal/address.js'
20
29
  import * as Charge_internal from '../internal/charge.js'
@@ -24,6 +33,7 @@ import * as Proof from '../internal/proof.js'
24
33
  import * as Selectors from '../internal/selectors.js'
25
34
  import type * as types from '../internal/types.js'
26
35
  import * as Methods from '../Methods.js'
36
+ import { html as htmlContent } from './internal/html.gen.js'
27
37
 
28
38
  /**
29
39
  * Creates a Tempo charge method intent for usage on the server.
@@ -47,6 +57,7 @@ export function charge<const parameters extends charge.Parameters>(
47
57
  decimals = defaults.decimals,
48
58
  description,
49
59
  externalId,
60
+ html,
50
61
  memo,
51
62
  waitForConfirmation = true,
52
63
  } = parameters
@@ -74,6 +85,36 @@ export function charge<const parameters extends charge.Parameters>(
74
85
  recipient,
75
86
  } as unknown as Defaults,
76
87
 
88
+ html: html
89
+ ? {
90
+ config: {},
91
+ content: htmlContent,
92
+ formatAmount: async (request: z.output<typeof Methods.charge.schema.request>) => {
93
+ try {
94
+ const chainId = request.methodDetails?.chainId
95
+ if (chainId === undefined) throw new Error('no chainId')
96
+ const client = await getClient({ chainId })
97
+ const metadata = await Actions.token.getMetadata(client, {
98
+ token: request.currency as `0x${string}`,
99
+ })
100
+ const symbol =
101
+ new Intl.NumberFormat('en', {
102
+ style: 'currency',
103
+ currency: metadata.currency,
104
+ currencyDisplay: 'narrowSymbol',
105
+ })
106
+ .formatToParts(0)
107
+ .find((p) => p.type === 'currency')?.value ?? metadata.currency
108
+ return `${symbol}${formatUnits(BigInt(request.amount), metadata.decimals)}`
109
+ } catch {
110
+ return `$${request.amount}`
111
+ }
112
+ },
113
+ text: typeof html === 'object' ? html.text : undefined,
114
+ theme: typeof html === 'object' ? html.theme : undefined,
115
+ }
116
+ : undefined,
117
+
77
118
  // TODO: dedupe `{charge,session}.request`
78
119
  async request({ credential, request }) {
79
120
  const chainId = await (async () => {
@@ -110,16 +151,17 @@ export function charge<const parameters extends charge.Parameters>(
110
151
 
111
152
  async verify({ credential, request }) {
112
153
  const { challenge } = credential
113
- const { chainId, feePayer } = request
154
+ const resolvedRequest = Methods.charge.schema.request.parse(request)
155
+ const chainId = resolvedRequest.methodDetails?.chainId ?? request.chainId
156
+ const feePayer = request.feePayer
114
157
 
115
158
  const client = await getClient({ chainId })
116
159
 
117
- const { request: challengeRequest } = challenge
118
- const { amount, methodDetails } = challengeRequest
160
+ const { amount, methodDetails } = resolvedRequest
119
161
  const expires = challenge.expires
120
162
 
121
- const currency = challengeRequest.currency as `0x${string}`
122
- const recipient = challengeRequest.recipient as `0x${string}`
163
+ const currency = resolvedRequest.currency as `0x${string}`
164
+ const recipient = resolvedRequest.recipient as `0x${string}`
123
165
 
124
166
  Expires.assert(expires, challenge.id)
125
167
 
@@ -292,6 +334,14 @@ export declare namespace charge {
292
334
  type Defaults = LooseOmit<Method.RequestDefaults<typeof Methods.charge>, 'feePayer' | 'recipient'>
293
335
 
294
336
  type Parameters = {
337
+ /** Render payment page when Accept header is text/html (e.g. in browsers) */
338
+ html?:
339
+ | boolean
340
+ | {
341
+ text?: Html.Text
342
+ theme?: Html.Theme
343
+ }
344
+ | undefined
295
345
  /** Testnet mode. */
296
346
  testnet?: boolean | undefined
297
347
  /**
@@ -530,7 +580,8 @@ async function assertHashUnused(
530
580
  hash: `0x${string}`,
531
581
  ): Promise<void> {
532
582
  const seen = await store.get(getHashStoreKey(hash))
533
- if (seen !== null) throw new Error('Transaction hash has already been used.')
583
+ if (seen !== null)
584
+ throw new VerificationFailedError({ reason: 'Transaction hash has already been used' })
534
585
  }
535
586
 
536
587
  /** @internal */
@@ -547,7 +598,8 @@ async function assertProofUnused(
547
598
  challengeId: string,
548
599
  ): Promise<void> {
549
600
  const seen = await store.get(getProofStoreKey(challengeId))
550
- if (seen !== null) throw new Error('Proof credential has already been used.')
601
+ if (seen !== null)
602
+ throw new VerificationFailedError({ reason: 'Proof credential has already been used' })
551
603
  }
552
604
 
553
605
  /** @internal */
@@ -573,8 +625,10 @@ function toReceipt(receipt: TransactionReceipt) {
573
625
  }
574
626
 
575
627
  /** @internal */
576
- class MismatchError extends Error {
628
+ class MismatchError extends PaymentError {
577
629
  override readonly name = 'MismatchError'
630
+ readonly title = 'Verification Failed'
631
+ readonly type = 'https://paymentauth.org/problems/verification-failed'
578
632
 
579
633
  constructor(reason: string, details: Record<string, string>) {
580
634
  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