@three-ws/x402-payment-modal 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +71 -9
- package/CONTRIBUTING.md +79 -0
- package/LICENSE +38 -180
- package/README.md +238 -63
- package/dist/index.d.ts +14 -3
- package/dist/x402.js +564 -206
- package/dist/x402.min.js +308 -178
- package/docs/EXAMPLES.md +137 -0
- package/docs/api-reference.md +32 -5
- package/docs/architecture.md +7 -1
- package/docs/react.md +163 -0
- package/docs/server-setup.md +63 -6
- package/examples/README.md +2 -1
- package/examples/react/App.jsx +95 -0
- package/examples/react/README.md +34 -31
- package/examples/server-express/server.js +16 -9
- package/examples/solana-crypto-paywall/README.md +81 -0
- package/examples/solana-crypto-paywall/facilitator.mjs +170 -0
- package/examples/solana-crypto-paywall/package.json +17 -0
- package/examples/solana-crypto-paywall/public/index.html +506 -0
- package/examples/solana-crypto-paywall/server.mjs +279 -0
- package/package.json +126 -111
- package/react/index.d.ts +39 -0
- package/react/index.js +112 -0
- package/server/checkout.js +208 -66
- package/server/express.js +7 -4
- package/server/vercel.js +2 -2
- package/src/index.js +563 -205
- package/types/index.d.ts +14 -3
- package/types/server.d.ts +2 -1
- package/examples/react/X402Button.jsx +0 -84
package/types/index.d.ts
CHANGED
|
@@ -58,12 +58,17 @@ export interface PayResult {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/** Branding shown in the modal footer. */
|
|
61
|
+
/** Branding shown in the modal header/footer. */
|
|
62
62
|
export interface BrandConfig {
|
|
63
63
|
name?: string;
|
|
64
64
|
url?: string;
|
|
65
|
+
/** Logo shown in the modal header (URL). */
|
|
66
|
+
logo?: string;
|
|
65
67
|
}
|
|
66
68
|
|
|
69
|
+
/** Forced color scheme. `auto` (default) follows the OS preference. */
|
|
70
|
+
export type X402Theme = 'auto' | 'light' | 'dark';
|
|
71
|
+
|
|
67
72
|
/** ERC-8021 builder-code self-attribution echoed when the 402 challenge declares one. */
|
|
68
73
|
export interface BuilderCodeConfig {
|
|
69
74
|
wallet?: string;
|
|
@@ -84,6 +89,10 @@ export interface X402Config {
|
|
|
84
89
|
footerNote?: string;
|
|
85
90
|
builderCode?: BuilderCodeConfig;
|
|
86
91
|
esm?: EsmConfig;
|
|
92
|
+
/** Force the modal's color scheme. Default `auto` (follow the OS). */
|
|
93
|
+
theme?: X402Theme;
|
|
94
|
+
/** Flat map of `--x402-*` design tokens to brand-match at runtime, e.g. `{ '--x402-accent': '#ff5c00' }`. */
|
|
95
|
+
cssVars?: Record<string, string> | null;
|
|
87
96
|
}
|
|
88
97
|
|
|
89
98
|
/**
|
|
@@ -107,8 +116,10 @@ export const version: string;
|
|
|
107
116
|
|
|
108
117
|
/** Solana USDC mint (mainnet). */
|
|
109
118
|
export const USDC_MINT_SOLANA: string;
|
|
110
|
-
/**
|
|
111
|
-
* `accept` using it renders as THREE without merchant-supplied metadata.
|
|
119
|
+
/** THREE — an optional opt-in SPL token mint recognized by the modal so a 402
|
|
120
|
+
* `accept` using it renders as THREE without merchant-supplied metadata. USDC
|
|
121
|
+
* remains the always-on default; this token is used only when an endpoint
|
|
122
|
+
* chooses to accept it. */
|
|
112
123
|
export const THREE_MINT: string;
|
|
113
124
|
|
|
114
125
|
export interface KnownSolanaToken {
|
package/types/server.d.ts
CHANGED
|
@@ -47,7 +47,8 @@ export const NETWORK_SOLANA_DEVNET: string;
|
|
|
47
47
|
|
|
48
48
|
/** Solana USDC mint (mainnet). */
|
|
49
49
|
export const USDC_MINT_SOLANA: string;
|
|
50
|
-
/**
|
|
50
|
+
/** THREE — an optional opt-in SPL token mint (used only when an endpoint
|
|
51
|
+
* chooses to accept it alongside USDC). */
|
|
51
52
|
export const THREE_MINT: string;
|
|
52
53
|
|
|
53
54
|
export interface WellKnownToken {
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* <X402Button> — a thin React wrapper around @three-ws/x402-payment-modal.
|
|
3
|
-
*
|
|
4
|
-
* The package is a browser-only ES module (it renders a modal and talks to a
|
|
5
|
-
* wallet), so we dynamically import it INSIDE the click handler. That keeps the
|
|
6
|
-
* component SSR-safe: nothing from the package is touched during render or on
|
|
7
|
-
* the server.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
*
|
|
11
|
-
* import X402Button from './X402Button';
|
|
12
|
-
*
|
|
13
|
-
* <X402Button
|
|
14
|
-
* endpoint="https://api.example.com/paid/summarize"
|
|
15
|
-
* method="POST"
|
|
16
|
-
* body={{ url: 'https://en.wikipedia.org/wiki/x402' }}
|
|
17
|
-
* merchant="Acme Summaries"
|
|
18
|
-
* action="Summarize article"
|
|
19
|
-
* label="Summarize for 0.01 USDC"
|
|
20
|
-
* onResult={(r) => console.log('paid', r)}
|
|
21
|
-
* onError={(e) => console.error(e)}
|
|
22
|
-
* />
|
|
23
|
-
*
|
|
24
|
-
* For Solana payments your app must also run the server checkout endpoint
|
|
25
|
-
* (see ../../docs/server-setup.md and examples/server-express). EVM payments
|
|
26
|
-
* sign in-browser and need no server.
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import { useCallback, useState } from 'react';
|
|
30
|
-
|
|
31
|
-
export default function X402Button({
|
|
32
|
-
endpoint,
|
|
33
|
-
method = 'GET',
|
|
34
|
-
body,
|
|
35
|
-
merchant,
|
|
36
|
-
action,
|
|
37
|
-
label = 'Pay',
|
|
38
|
-
onResult,
|
|
39
|
-
onError,
|
|
40
|
-
children,
|
|
41
|
-
...rest
|
|
42
|
-
}) {
|
|
43
|
-
const [processing, setProcessing] = useState(false);
|
|
44
|
-
|
|
45
|
-
const handleClick = useCallback(async () => {
|
|
46
|
-
if (processing) return;
|
|
47
|
-
setProcessing(true);
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
// Dynamic import keeps the browser-only module out of the SSR bundle.
|
|
51
|
-
const { pay } = await import('@three-ws/x402-payment-modal');
|
|
52
|
-
|
|
53
|
-
const result = await pay({
|
|
54
|
-
endpoint,
|
|
55
|
-
method,
|
|
56
|
-
body,
|
|
57
|
-
merchant,
|
|
58
|
-
action,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// result = { ok, result, payment?, siwx?, response }
|
|
62
|
-
onResult?.(result);
|
|
63
|
-
} catch (err) {
|
|
64
|
-
// The modal rejects with err.code === 'cancelled' when the user dismisses
|
|
65
|
-
// it. That is not an error — stay silent so we don't flash a failure.
|
|
66
|
-
if (err && err.code === 'cancelled') return;
|
|
67
|
-
onError?.(err);
|
|
68
|
-
} finally {
|
|
69
|
-
setProcessing(false);
|
|
70
|
-
}
|
|
71
|
-
}, [processing, endpoint, method, body, merchant, action, onResult, onError]);
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<button
|
|
75
|
-
type="button"
|
|
76
|
-
onClick={handleClick}
|
|
77
|
-
disabled={processing}
|
|
78
|
-
aria-busy={processing}
|
|
79
|
-
{...rest}
|
|
80
|
-
>
|
|
81
|
-
{processing ? 'Processing…' : children ?? label}
|
|
82
|
-
</button>
|
|
83
|
-
);
|
|
84
|
-
}
|