@voyage_ai/v402-web-ts 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,94 +0,0 @@
1
- /**
2
- * usePaymentInfo Hook
3
- *
4
- * React hook for fetching payment information from endpoint
5
- */
6
-
7
- import {useEffect, useState} from 'react';
8
- import type {PaymentRequirements} from 'x402/types';
9
- import {NetworkType} from '../../types';
10
- import {getSupportedNetworkTypes, parsePaymentRequired} from '../../utils';
11
- import {PROD_BACK_URL} from "../../types/common";
12
-
13
- export interface UsePaymentInfoReturn {
14
- // State
15
- paymentInfo: PaymentRequirements[] | null;
16
- supportedNetworks: NetworkType[];
17
- isLoading: boolean;
18
- error: string | null;
19
-
20
- // Actions
21
- refetch: () => Promise<void>;
22
- }
23
-
24
- /**
25
- * Hook for fetching payment information
26
- *
27
- * @param endpoint - API endpoint to fetch payment info from
28
- * @param merchantId - @see our website to apply
29
- *
30
- * @example
31
- * ```tsx
32
- * function PaymentInfo() {
33
- * const { paymentInfo, supportedNetworks, isLoading } = usePaymentInfo('/api/protected');
34
- *
35
- * if (isLoading) return <p>Loading...</p>;
36
- *
37
- * return (
38
- * <div>
39
- * <p>Supported networks:</p>
40
- * {supportedNetworks.map(net => <span key={net}>{net}</span>)}
41
- * </div>
42
- * );
43
- * }
44
- * ```
45
- */
46
- export function usePaymentInfo(merchantId: string, endpoint: string = PROD_BACK_URL): UsePaymentInfoReturn {
47
- const [paymentInfo, setPaymentInfo] = useState<PaymentRequirements[] | null>(null);
48
- const [supportedNetworks, setSupportedNetworks] = useState<NetworkType[]>([]);
49
- const [isLoading, setIsLoading] = useState(true);
50
- const [error, setError] = useState<string | null>(null);
51
-
52
- const fetchPaymentInfo = async () => {
53
- setIsLoading(true);
54
- setError(null);
55
-
56
- try {
57
- endpoint = `${endpoint}/${merchantId}`
58
- const response = await fetch(endpoint, {method: 'POST'});
59
-
60
- if (response.status === 402) {
61
- const body = await response.json();
62
- const payment = parsePaymentRequired(body);
63
-
64
- if (payment) {
65
- setPaymentInfo(payment);
66
-
67
- const networks = getSupportedNetworkTypes(payment);
68
- setSupportedNetworks(networks);
69
- }
70
- } else {
71
- // No payment required
72
- setPaymentInfo(null);
73
- setSupportedNetworks([]);
74
- }
75
- } catch (err: any) {
76
- setError(err.message || 'Failed to fetch payment info');
77
- } finally {
78
- setIsLoading(false);
79
- }
80
- };
81
-
82
- useEffect(() => {
83
- fetchPaymentInfo();
84
- }, [endpoint]);
85
-
86
- return {
87
- paymentInfo,
88
- supportedNetworks,
89
- isLoading,
90
- error,
91
- refetch: fetchPaymentInfo,
92
- };
93
- }
94
-
@@ -1,174 +0,0 @@
1
- /**
2
- * useWallet Hook
3
- *
4
- * React hook for wallet connection management
5
- */
6
-
7
- import {useCallback, useEffect, useState} from 'react';
8
- import {NetworkType} from '../../types';
9
- import {
10
- connectWallet as connectWalletUtil,
11
- disconnectWallet as disconnectWalletUtil,
12
- getConnectedNetworkType,
13
- getCurrentWallet,
14
- isWalletManuallyDisconnected,
15
- onAccountsChanged,
16
- onChainChanged,
17
- onWalletDisconnect,
18
- } from '../../utils';
19
-
20
- export interface UseWalletReturn {
21
- // State
22
- address: string | null;
23
- networkType: NetworkType | null;
24
- isConnecting: boolean;
25
- error: string | null;
26
-
27
- // Actions
28
- connect: (networkType: NetworkType) => Promise<void>;
29
- disconnect: () => void;
30
- clearError: () => void;
31
- }
32
-
33
- /**
34
- * Hook for managing wallet connection
35
- *
36
- * @example
37
- * ```tsx
38
- * function MyComponent() {
39
- * const { address, connect, disconnect, isConnecting } = useWallet();
40
- *
41
- * return (
42
- * <div>
43
- * {address ? (
44
- * <button onClick={disconnect}>Disconnect {address}</button>
45
- * ) : (
46
- * <button onClick={() => connect(NetworkType.SOLANA)}>
47
- * Connect Wallet
48
- * </button>
49
- * )}
50
- * </div>
51
- * );
52
- * }
53
- * ```
54
- */
55
- export function useWallet(): UseWalletReturn {
56
- const [address, setAddress] = useState<string | null>(null);
57
- const [networkType, setNetworkType] = useState<NetworkType | null>(null);
58
- const [isConnecting, setIsConnecting] = useState(false);
59
- const [error, setError] = useState<string | null>(null);
60
-
61
- // Initialize wallet on mount
62
- useEffect(() => {
63
- const initWallet = async () => {
64
- if (!isWalletManuallyDisconnected()) {
65
- const connectedType = getConnectedNetworkType();
66
- if (connectedType) {
67
- const currentAddress = await getCurrentWallet(connectedType);
68
- if (currentAddress) {
69
- setAddress(currentAddress);
70
- setNetworkType(connectedType);
71
- console.log('🔄 Auto-reconnected wallet:', currentAddress);
72
- }
73
- }
74
- }
75
- };
76
-
77
- initWallet();
78
-
79
- // Listen for account changes (EVM only)
80
- const unsubscribeAccountChange = onAccountsChanged((accounts) => {
81
- const connectedType = getConnectedNetworkType();
82
- if (connectedType === NetworkType.EVM) {
83
- if (accounts.length === 0) {
84
- setAddress(null);
85
- console.log('🔌 Wallet disconnected');
86
- } else {
87
- if (!isWalletManuallyDisconnected()) {
88
- setAddress(accounts[0]);
89
- console.log('🔄 Account changed:', accounts[0]);
90
- }
91
- }
92
- }
93
- });
94
-
95
- // Listen for network/chain changes (EVM only)
96
- const unsubscribeChainChange = onChainChanged(() => {
97
- const connectedType = getConnectedNetworkType();
98
- if (connectedType === NetworkType.EVM) {
99
- console.log('⚠️ Network changed detected - disconnecting wallet');
100
- disconnectWalletUtil();
101
- setAddress(null);
102
- setNetworkType(null);
103
- setError('Network changed. Please reconnect your wallet.');
104
- }
105
- });
106
-
107
- // Listen for wallet disconnect (Solana only)
108
- const unsubscribeWalletDisconnect = onWalletDisconnect(() => {
109
- const connectedType = getConnectedNetworkType();
110
- if (connectedType === NetworkType.SOLANA || connectedType === NetworkType.SVM) {
111
- console.log('⚠️ Solana wallet disconnected');
112
- disconnectWalletUtil();
113
- setAddress(null);
114
- setNetworkType(null);
115
- }
116
- });
117
-
118
- return () => {
119
- unsubscribeAccountChange();
120
- unsubscribeChainChange();
121
- unsubscribeWalletDisconnect();
122
- };
123
- }, []); // Only run on mount
124
-
125
- // Connect wallet
126
- const connect = useCallback(async (type: NetworkType) => {
127
- setIsConnecting(true);
128
- setError(null);
129
-
130
- try {
131
- const walletAddress = await connectWalletUtil(type);
132
-
133
- console.log('✅ Wallet connected:', walletAddress, 'Network:', type);
134
-
135
- // Update state - this should trigger re-render
136
- setAddress(walletAddress);
137
- setNetworkType(type);
138
-
139
- // Force a small delay to ensure state updates
140
- await new Promise(resolve => setTimeout(resolve, 0));
141
-
142
- console.log('📝 State updated in hook');
143
- } catch (err: any) {
144
- setError(err.message || 'Failed to connect wallet');
145
- throw err;
146
- } finally {
147
- setIsConnecting(false);
148
- }
149
- }, []);
150
-
151
- // Disconnect wallet
152
- const disconnect = useCallback(() => {
153
- disconnectWalletUtil();
154
- setAddress(null);
155
- setNetworkType(null);
156
- setError(null);
157
- }, []);
158
-
159
- // Clear error
160
- const clearError = useCallback(() => {
161
- setError(null);
162
- }, []);
163
-
164
- return {
165
- address,
166
- networkType,
167
- isConnecting,
168
- error,
169
- connect,
170
- disconnect,
171
- clearError,
172
- };
173
- }
174
-
@@ -1,61 +0,0 @@
1
- /**
2
- * useWallet Hook (External Store)
3
- *
4
- * Uses useSyncExternalStore for optimal performance
5
- * No Provider needed!
6
- */
7
-
8
- import {useSyncExternalStore} from 'react';
9
- import {walletStore} from '../store/walletStore';
10
- import {NetworkType} from '../../types';
11
-
12
- export interface UseWalletReturn {
13
- // State
14
- address: string | null;
15
- networkType: NetworkType | null;
16
- isConnecting: boolean;
17
- error: string | null;
18
-
19
- // Actions
20
- connect: (networkType: NetworkType) => Promise<void>;
21
- disconnect: () => void;
22
- clearError: () => void;
23
- }
24
-
25
- /**
26
- * Hook for wallet connection
27
- * No Provider needed - uses external store
28
- *
29
- * @example
30
- * ```tsx
31
- * function MyComponent() {
32
- * const { address, connect, disconnect } = useWallet();
33
- *
34
- * return (
35
- * <div>
36
- * {address ? (
37
- * <button onClick={disconnect}>Disconnect</button>
38
- * ) : (
39
- * <button onClick={() => connect(NetworkType.SOLANA)}>Connect</button>
40
- * )}
41
- * </div>
42
- * );
43
- * }
44
- * ```
45
- */
46
- export function useWallet(): UseWalletReturn {
47
- // Use React 18's useSyncExternalStore for optimal performance
48
- const state = useSyncExternalStore(
49
- (listener) => walletStore.subscribe(listener),
50
- () => walletStore.getState(),
51
- () => walletStore.getState() // Server snapshot
52
- );
53
-
54
- return {
55
- ...state,
56
- connect: (type: NetworkType) => walletStore.connect(type),
57
- disconnect: () => walletStore.disconnect(),
58
- clearError: () => walletStore.clearError(),
59
- };
60
- }
61
-
@@ -1,42 +0,0 @@
1
- /**
2
- * x402 Payment SDK - React Package
3
- *
4
- * Pre-built React hooks and components for easy integration
5
- *
6
- * ## Quick Start
7
- *
8
- * ```tsx
9
- * import { WalletConnect, PaymentButton, useWallet, usePayment } from '@x402/sdk/react';
10
- *
11
- * // No Provider needed! Just use the hooks directly
12
- * function App() {
13
- * const { address } = useWallet();
14
- *
15
- * return (
16
- * <div>
17
- * <WalletConnect />
18
- * {address && <PaymentButton endpoint="/api/protected" />}
19
- * </div>
20
- * );
21
- * }
22
- * ```
23
- */
24
-
25
- // Hooks (No Provider needed!)
26
- export { useWallet } from './hooks/useWalletStore';
27
- export type { UseWalletReturn } from './hooks/useWalletStore';
28
-
29
- // Hooks
30
- export { usePayment } from './hooks/usePayment';
31
- export type { UsePaymentReturn } from './hooks/usePayment';
32
-
33
- export { usePaymentInfo } from './hooks/usePaymentInfo';
34
- export type { UsePaymentInfoReturn } from './hooks/usePaymentInfo';
35
-
36
- // Components
37
- export { WalletConnect } from './components/WalletConnect';
38
- export type { WalletConnectProps } from './components/WalletConnect';
39
-
40
- export { PaymentButton } from './components/PaymentButton';
41
- export type { PaymentButtonProps } from './components/PaymentButton';
42
-
@@ -1,181 +0,0 @@
1
- /**
2
- * Wallet Store (External Store)
3
- *
4
- * Lightweight state management without Context Provider
5
- * Uses singleton pattern + event emitter for reactivity
6
- */
7
-
8
- import {NetworkType} from '../../types';
9
- import {
10
- connectWallet as connectWalletUtil,
11
- disconnectWallet as disconnectWalletUtil,
12
- getConnectedNetworkType,
13
- getCurrentWallet,
14
- isWalletManuallyDisconnected,
15
- onAccountsChanged,
16
- onChainChanged,
17
- onWalletDisconnect,
18
- } from '../../utils';
19
-
20
- type Listener = () => void;
21
-
22
- interface WalletState {
23
- address: string | null;
24
- networkType: NetworkType | null;
25
- isConnecting: boolean;
26
- error: string | null;
27
- }
28
-
29
- class WalletStore {
30
- private state: WalletState = {
31
- address: null,
32
- networkType: null,
33
- isConnecting: false,
34
- error: null,
35
- };
36
-
37
- private listeners = new Set<Listener>();
38
- private initialized = false;
39
-
40
- // Initialize store (call once)
41
- init() {
42
- if (this.initialized) return;
43
- this.initialized = true;
44
-
45
- // Auto-reconnect on init
46
- this.autoReconnect();
47
-
48
- // Listen for account changes (EVM only)
49
- onAccountsChanged((accounts) => {
50
- const connectedType = getConnectedNetworkType();
51
- if (connectedType === NetworkType.EVM) {
52
- if (accounts.length === 0) {
53
- this.setState({address: null});
54
- console.log('🔌 Wallet disconnected');
55
- } else {
56
- if (!isWalletManuallyDisconnected()) {
57
- this.setState({address: accounts[0]});
58
- console.log('🔄 Account changed:', accounts[0]);
59
- }
60
- }
61
- }
62
- });
63
-
64
- // Listen for network/chain changes (EVM only)
65
- onChainChanged(() => {
66
- const connectedType = getConnectedNetworkType();
67
- if (connectedType === NetworkType.EVM) {
68
- console.log('⚠️ Network changed detected - disconnecting wallet');
69
- disconnectWalletUtil();
70
- this.setState({
71
- address: null,
72
- networkType: null,
73
- error: 'Network changed. Please reconnect your wallet.',
74
- });
75
- }
76
- });
77
-
78
- // Listen for wallet disconnect (Solana only)
79
- onWalletDisconnect(() => {
80
- const connectedType = getConnectedNetworkType();
81
- if (connectedType === NetworkType.SOLANA || connectedType === NetworkType.SVM) {
82
- console.log('⚠️ Solana wallet disconnected');
83
- disconnectWalletUtil();
84
- this.setState({
85
- address: null,
86
- networkType: null,
87
- });
88
- }
89
- });
90
- }
91
-
92
- private async autoReconnect() {
93
- if (!isWalletManuallyDisconnected()) {
94
- const connectedType = getConnectedNetworkType();
95
- if (connectedType) {
96
- const currentAddress = await getCurrentWallet(connectedType);
97
- if (currentAddress) {
98
- this.setState({
99
- address: currentAddress,
100
- networkType: connectedType,
101
- });
102
- console.log('🔄 Auto-reconnected wallet:', currentAddress);
103
- }
104
- }
105
- }
106
- }
107
-
108
- // Get current state
109
- getState(): WalletState {
110
- return this.state;
111
- }
112
-
113
- // Update state and notify listeners
114
- private setState(partial: Partial<WalletState>) {
115
- this.state = {...this.state, ...partial};
116
- this.notifyListeners();
117
- }
118
-
119
- // Subscribe to state changes
120
- subscribe(listener: Listener): () => void {
121
- this.listeners.add(listener);
122
- return () => {
123
- this.listeners.delete(listener);
124
- };
125
- }
126
-
127
- // Notify all listeners
128
- private notifyListeners() {
129
- this.listeners.forEach(listener => listener());
130
- }
131
-
132
- // Connect wallet
133
- async connect(type: NetworkType): Promise<void> {
134
- this.setState({isConnecting: true, error: null});
135
-
136
- try {
137
- const walletAddress = await connectWalletUtil(type);
138
-
139
- console.log('✅ Wallet connected:', walletAddress, 'Network:', type);
140
-
141
- this.setState({
142
- address: walletAddress,
143
- networkType: type,
144
- isConnecting: false,
145
- });
146
-
147
- console.log('📝 Store state updated');
148
- } catch (err: any) {
149
- this.setState({
150
- error: err.message || 'Failed to connect wallet',
151
- isConnecting: false,
152
- });
153
- throw err;
154
- }
155
- }
156
-
157
- // Disconnect wallet
158
- disconnect(): void {
159
- disconnectWalletUtil();
160
- this.setState({
161
- address: null,
162
- networkType: null,
163
- error: null,
164
- });
165
- console.log('🔌 Wallet disconnected from store');
166
- }
167
-
168
- // Clear error
169
- clearError(): void {
170
- this.setState({error: null});
171
- }
172
- }
173
-
174
- // Singleton instance
175
- export const walletStore = new WalletStore();
176
-
177
- // Initialize on import (browser only)
178
- if (typeof window !== 'undefined') {
179
- walletStore.init();
180
- }
181
-