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.
- package/CHANGELOG.md +20 -0
- package/dist/Credential.d.ts +12 -0
- package/dist/Credential.d.ts.map +1 -1
- package/dist/Credential.js +22 -4
- package/dist/Credential.js.map +1 -1
- package/dist/Method.d.ts +4 -0
- package/dist/Method.d.ts.map +1 -1
- package/dist/Method.js +2 -1
- package/dist/Method.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +11 -9
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/plugins/tempo.d.ts.map +1 -1
- package/dist/cli/plugins/tempo.js +3 -3
- package/dist/cli/plugins/tempo.js.map +1 -1
- package/dist/cli/utils.d.ts +2 -0
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +10 -5
- package/dist/cli/utils.js.map +1 -1
- package/dist/proxy/Proxy.d.ts.map +1 -1
- package/dist/proxy/Proxy.js +52 -8
- package/dist/proxy/Proxy.js.map +1 -1
- package/dist/proxy/internal/Route.d.ts.map +1 -1
- package/dist/proxy/internal/Route.js +7 -3
- package/dist/proxy/internal/Route.js.map +1 -1
- package/dist/server/Mppx.d.ts.map +1 -1
- package/dist/server/Mppx.js +90 -71
- package/dist/server/Mppx.js.map +1 -1
- package/dist/server/Transport.d.ts +5 -1
- package/dist/server/Transport.d.ts.map +1 -1
- package/dist/server/Transport.js +71 -7
- package/dist/server/Transport.js.map +1 -1
- package/dist/server/internal/html/config.d.ts +144 -0
- package/dist/server/internal/html/config.d.ts.map +1 -0
- package/dist/server/internal/html/config.js +303 -0
- package/dist/server/internal/html/config.js.map +1 -0
- package/dist/server/internal/html/serviceWorker.gen.d.ts +2 -0
- package/dist/server/internal/html/serviceWorker.gen.d.ts.map +1 -0
- package/dist/server/internal/html/serviceWorker.gen.js +3 -0
- package/dist/server/internal/html/serviceWorker.gen.js.map +1 -0
- package/dist/stripe/internal/types.d.ts +6 -0
- package/dist/stripe/internal/types.d.ts.map +1 -1
- package/dist/stripe/server/Charge.d.ts +30 -16
- package/dist/stripe/server/Charge.d.ts.map +1 -1
- package/dist/stripe/server/Charge.js +35 -6
- package/dist/stripe/server/Charge.js.map +1 -1
- package/dist/stripe/server/internal/html/types.d.ts +2 -0
- package/dist/stripe/server/internal/html/types.d.ts.map +1 -0
- package/dist/stripe/server/internal/html/types.js +2 -0
- package/dist/stripe/server/internal/html/types.js.map +1 -0
- package/dist/stripe/server/internal/html.gen.d.ts +2 -0
- package/dist/stripe/server/internal/html.gen.d.ts.map +1 -0
- package/dist/stripe/server/internal/html.gen.js +3 -0
- package/dist/stripe/server/internal/html.gen.js.map +1 -0
- package/dist/tempo/server/Charge.d.ts +33 -26
- package/dist/tempo/server/Charge.d.ts.map +1 -1
- package/dist/tempo/server/Charge.js +46 -11
- package/dist/tempo/server/Charge.js.map +1 -1
- package/dist/tempo/server/Session.d.ts.map +1 -1
- package/dist/tempo/server/Session.js +3 -2
- package/dist/tempo/server/Session.js.map +1 -1
- package/dist/tempo/server/internal/html.gen.d.ts +2 -0
- package/dist/tempo/server/internal/html.gen.d.ts.map +1 -0
- package/dist/tempo/server/internal/html.gen.js +3 -0
- package/dist/tempo/server/internal/html.gen.js.map +1 -0
- package/dist/tempo/server/internal/transport.d.ts +1 -1
- package/dist/tempo/server/internal/transport.d.ts.map +1 -1
- package/dist/tempo/server/internal/transport.js +45 -58
- package/dist/tempo/server/internal/transport.js.map +1 -1
- package/package.json +2 -2
- package/src/Credential.ts +28 -4
- package/src/Method.ts +6 -1
- package/src/cli/cli.ts +11 -8
- package/src/cli/plugins/tempo.ts +3 -2
- package/src/cli/utils.test.ts +64 -0
- package/src/cli/utils.ts +10 -4
- package/src/env.d.ts +1 -0
- package/src/mcp-sdk/server/Transport.test.ts +6 -0
- package/src/proxy/Proxy.test.ts +188 -1
- package/src/proxy/Proxy.ts +58 -9
- package/src/proxy/internal/Route.test.ts +9 -0
- package/src/proxy/internal/Route.ts +5 -2
- package/src/server/Mppx.test.ts +171 -18
- package/src/server/Mppx.ts +120 -79
- package/src/server/Transport.test.ts +232 -2
- package/src/server/Transport.ts +84 -7
- package/src/server/internal/html/config.ts +414 -0
- package/src/server/internal/html/serviceWorker.client.ts +28 -0
- package/src/server/internal/html/serviceWorker.gen.ts +2 -0
- package/src/server/internal/html/serviceWorker.ts +27 -0
- package/src/server/internal/html/tsconfig.worker.client.json +8 -0
- package/src/server/internal/html/tsconfig.worker.json +8 -0
- package/src/stripe/internal/types.ts +20 -0
- package/src/stripe/server/Charge.ts +62 -6
- package/src/stripe/server/internal/html/main.ts +174 -0
- package/src/stripe/server/internal/html/node_modules/.bin/mppx.src +21 -0
- package/src/stripe/server/internal/html/package.json +9 -0
- package/src/stripe/server/internal/html/stripe-js-pure.d.ts +7 -0
- package/src/stripe/server/internal/html/tsconfig.json +8 -0
- package/src/stripe/server/internal/html/types.ts +5 -0
- package/src/stripe/server/internal/html.gen.ts +2 -0
- package/src/tempo/server/Charge.ts +64 -10
- package/src/tempo/server/Session.ts +3 -2
- package/src/tempo/server/internal/html/main.ts +111 -0
- package/src/tempo/server/internal/html/node_modules/.bin/mppx.src +21 -0
- package/src/tempo/server/internal/html/package.json +10 -0
- package/src/tempo/server/internal/html/tsconfig.json +8 -0
- package/src/tempo/server/internal/html.gen.ts +2 -0
- package/src/tempo/server/internal/transport.test.ts +37 -31
- package/src/tempo/server/internal/transport.ts +44 -58
- 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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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({
|
|
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,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 {
|
|
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
|
|
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 {
|
|
118
|
-
const { amount, methodDetails } = challengeRequest
|
|
160
|
+
const { amount, methodDetails } = resolvedRequest
|
|
119
161
|
const expires = challenge.expires
|
|
120
162
|
|
|
121
|
-
const currency =
|
|
122
|
-
const recipient =
|
|
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)
|
|
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)
|
|
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
|
|
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
|
|
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
|