uvd-x402-sdk 2.0.3 → 2.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/README.md +282 -15
- package/dist/adapters/index.d.mts +139 -0
- package/dist/adapters/index.d.ts +139 -0
- package/dist/adapters/index.js +724 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/index.mjs +720 -0
- package/dist/adapters/index.mjs.map +1 -0
- package/dist/{index-MTBgC_SL.d.mts → index-BHwtdJrt.d.mts} +45 -4
- package/dist/{index-MTBgC_SL.d.ts → index-BHwtdJrt.d.ts} +45 -4
- package/dist/{index-Db8dWNam.d.ts → index-CkDdnSNx.d.mts} +33 -2
- package/dist/{index-D0N_SYpK.d.mts → index-UTj85ZDJ.d.ts} +33 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +210 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +207 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/evm/index.d.mts +19 -3
- package/dist/providers/evm/index.d.ts +19 -3
- package/dist/providers/evm/index.js +228 -12
- package/dist/providers/evm/index.js.map +1 -1
- package/dist/providers/evm/index.mjs +228 -12
- package/dist/providers/evm/index.mjs.map +1 -1
- package/dist/providers/near/index.d.mts +1 -1
- package/dist/providers/near/index.d.ts +1 -1
- package/dist/providers/near/index.js.map +1 -1
- package/dist/providers/near/index.mjs.map +1 -1
- package/dist/providers/solana/index.d.mts +1 -1
- package/dist/providers/solana/index.d.ts +1 -1
- package/dist/providers/solana/index.js +168 -0
- package/dist/providers/solana/index.js.map +1 -1
- package/dist/providers/solana/index.mjs +168 -0
- package/dist/providers/solana/index.mjs.map +1 -1
- package/dist/providers/stellar/index.d.mts +1 -1
- package/dist/providers/stellar/index.d.ts +1 -1
- package/dist/providers/stellar/index.js.map +1 -1
- package/dist/providers/stellar/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js +168 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +168 -0
- package/dist/react/index.mjs.map +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +168 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +168 -0
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +10 -2
- package/src/adapters/index.ts +13 -0
- package/src/adapters/wagmi.ts +294 -0
- package/src/chains/index.ts +255 -1
- package/src/index.ts +9 -0
- package/src/providers/evm/index.ts +64 -16
- package/src/types/index.ts +46 -3
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* uvd-x402-sdk - Wagmi/Viem Adapter
|
|
3
|
+
*
|
|
4
|
+
* Provides integration with wagmi/viem for projects using RainbowKit,
|
|
5
|
+
* ConnectKit, or other wagmi-based wallet connection libraries.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { useWalletClient } from 'wagmi';
|
|
10
|
+
* import { createPaymentFromWalletClient } from 'uvd-x402-sdk/wagmi';
|
|
11
|
+
*
|
|
12
|
+
* function PayButton() {
|
|
13
|
+
* const { data: walletClient } = useWalletClient();
|
|
14
|
+
*
|
|
15
|
+
* const handlePay = async () => {
|
|
16
|
+
* const paymentHeader = await createPaymentFromWalletClient(walletClient, {
|
|
17
|
+
* recipient: '0x...',
|
|
18
|
+
* amount: '1.00',
|
|
19
|
+
* chainName: 'base',
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Use in your API request
|
|
23
|
+
* await fetch('/api/paid-endpoint', {
|
|
24
|
+
* headers: { 'X-PAYMENT': paymentHeader }
|
|
25
|
+
* });
|
|
26
|
+
* };
|
|
27
|
+
*
|
|
28
|
+
* return <button onClick={handlePay}>Pay $1.00</button>;
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { getChainByName } from '../chains';
|
|
34
|
+
import { createX402V1Header, encodeX402Header } from '../utils';
|
|
35
|
+
import { X402Error } from '../types';
|
|
36
|
+
import type { PaymentResult } from '../types';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Viem WalletClient interface (minimal type to avoid viem dependency)
|
|
40
|
+
*/
|
|
41
|
+
export interface WalletClient {
|
|
42
|
+
account: {
|
|
43
|
+
address: `0x${string}`;
|
|
44
|
+
};
|
|
45
|
+
signTypedData: (args: {
|
|
46
|
+
domain: {
|
|
47
|
+
name: string;
|
|
48
|
+
version: string;
|
|
49
|
+
chainId: number;
|
|
50
|
+
verifyingContract: `0x${string}`;
|
|
51
|
+
};
|
|
52
|
+
types: Record<string, Array<{ name: string; type: string }>>;
|
|
53
|
+
primaryType: string;
|
|
54
|
+
message: Record<string, unknown>;
|
|
55
|
+
}) => Promise<`0x${string}`>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Payment options for wagmi adapter
|
|
60
|
+
*/
|
|
61
|
+
export interface WagmiPaymentOptions {
|
|
62
|
+
/** Recipient address */
|
|
63
|
+
recipient: string;
|
|
64
|
+
/** Amount in USDC (e.g., "1.00", "10.50") */
|
|
65
|
+
amount: string;
|
|
66
|
+
/** Chain name (default: 'base') */
|
|
67
|
+
chainName?: string;
|
|
68
|
+
/** Validity window in seconds (default: 300 = 5 minutes) */
|
|
69
|
+
validitySeconds?: number;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Generate a random 32-byte nonce as hex string
|
|
74
|
+
*/
|
|
75
|
+
function generateNonce(): `0x${string}` {
|
|
76
|
+
const bytes = new Uint8Array(32);
|
|
77
|
+
if (typeof globalThis !== 'undefined' && globalThis.crypto?.getRandomValues) {
|
|
78
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
79
|
+
} else if (typeof window !== 'undefined' && window.crypto?.getRandomValues) {
|
|
80
|
+
window.crypto.getRandomValues(bytes);
|
|
81
|
+
} else {
|
|
82
|
+
// Fallback for non-browser environments
|
|
83
|
+
for (let i = 0; i < 32; i++) {
|
|
84
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return ('0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('')) as `0x${string}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Parse amount string to atomic units (BigInt)
|
|
92
|
+
*/
|
|
93
|
+
function parseUnits(amount: string, decimals: number): bigint {
|
|
94
|
+
const [integer, fraction = ''] = amount.split('.');
|
|
95
|
+
const paddedFraction = fraction.padEnd(decimals, '0').slice(0, decimals);
|
|
96
|
+
return BigInt(integer + paddedFraction);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Create an x402 payment header using a wagmi/viem WalletClient
|
|
101
|
+
*
|
|
102
|
+
* This function allows you to use the x402 SDK with wagmi-based wallet
|
|
103
|
+
* connections (RainbowKit, ConnectKit, etc.) instead of the built-in
|
|
104
|
+
* wallet connection.
|
|
105
|
+
*
|
|
106
|
+
* @param walletClient - The WalletClient from wagmi's useWalletClient hook
|
|
107
|
+
* @param options - Payment options (recipient, amount, chainName)
|
|
108
|
+
* @returns Base64-encoded payment header ready for X-PAYMENT HTTP header
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* import { useWalletClient } from 'wagmi';
|
|
113
|
+
* import { createPaymentFromWalletClient } from 'uvd-x402-sdk/wagmi';
|
|
114
|
+
*
|
|
115
|
+
* const { data: walletClient } = useWalletClient();
|
|
116
|
+
*
|
|
117
|
+
* const paymentHeader = await createPaymentFromWalletClient(walletClient, {
|
|
118
|
+
* recipient: '0xRecipientAddress',
|
|
119
|
+
* amount: '5.00',
|
|
120
|
+
* chainName: 'base',
|
|
121
|
+
* });
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export async function createPaymentFromWalletClient(
|
|
125
|
+
walletClient: WalletClient | undefined | null,
|
|
126
|
+
options: WagmiPaymentOptions
|
|
127
|
+
): Promise<string> {
|
|
128
|
+
if (!walletClient) {
|
|
129
|
+
throw new X402Error('WalletClient is not available. Make sure wallet is connected.', 'WALLET_NOT_CONNECTED');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const {
|
|
133
|
+
recipient,
|
|
134
|
+
amount,
|
|
135
|
+
chainName = 'base',
|
|
136
|
+
validitySeconds = 300,
|
|
137
|
+
} = options;
|
|
138
|
+
|
|
139
|
+
// Get chain configuration
|
|
140
|
+
const chain = getChainByName(chainName);
|
|
141
|
+
if (!chain) {
|
|
142
|
+
throw new X402Error(`Unsupported chain: ${chainName}`, 'CHAIN_NOT_SUPPORTED');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (chain.networkType !== 'evm') {
|
|
146
|
+
throw new X402Error(
|
|
147
|
+
`wagmi adapter only supports EVM chains. For ${chain.networkType}, use the appropriate provider.`,
|
|
148
|
+
'CHAIN_NOT_SUPPORTED'
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const from = walletClient.account.address;
|
|
153
|
+
const to = recipient as `0x${string}`;
|
|
154
|
+
const nonce = generateNonce();
|
|
155
|
+
const validAfter = 0;
|
|
156
|
+
const validBefore = Math.floor(Date.now() / 1000) + validitySeconds;
|
|
157
|
+
const value = parseUnits(amount, chain.usdc.decimals);
|
|
158
|
+
|
|
159
|
+
// EIP-712 domain
|
|
160
|
+
const domain = {
|
|
161
|
+
name: chain.usdc.name,
|
|
162
|
+
version: chain.usdc.version,
|
|
163
|
+
chainId: chain.chainId,
|
|
164
|
+
verifyingContract: chain.usdc.address as `0x${string}`,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// EIP-712 types for TransferWithAuthorization (ERC-3009)
|
|
168
|
+
const types = {
|
|
169
|
+
TransferWithAuthorization: [
|
|
170
|
+
{ name: 'from', type: 'address' },
|
|
171
|
+
{ name: 'to', type: 'address' },
|
|
172
|
+
{ name: 'value', type: 'uint256' },
|
|
173
|
+
{ name: 'validAfter', type: 'uint256' },
|
|
174
|
+
{ name: 'validBefore', type: 'uint256' },
|
|
175
|
+
{ name: 'nonce', type: 'bytes32' },
|
|
176
|
+
],
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Message to sign
|
|
180
|
+
const message = {
|
|
181
|
+
from,
|
|
182
|
+
to,
|
|
183
|
+
value,
|
|
184
|
+
validAfter: BigInt(validAfter),
|
|
185
|
+
validBefore: BigInt(validBefore),
|
|
186
|
+
nonce,
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Sign with viem
|
|
190
|
+
let signature: `0x${string}`;
|
|
191
|
+
try {
|
|
192
|
+
signature = await walletClient.signTypedData({
|
|
193
|
+
domain,
|
|
194
|
+
types,
|
|
195
|
+
primaryType: 'TransferWithAuthorization',
|
|
196
|
+
message,
|
|
197
|
+
});
|
|
198
|
+
} catch (error: unknown) {
|
|
199
|
+
if (error instanceof Error) {
|
|
200
|
+
if (error.message.includes('User rejected') || error.message.includes('denied')) {
|
|
201
|
+
throw new X402Error('Signature rejected by user', 'SIGNATURE_REJECTED');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
throw new X402Error(
|
|
205
|
+
`Failed to sign payment: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
206
|
+
'PAYMENT_FAILED',
|
|
207
|
+
error
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Create x402 header with correct format
|
|
212
|
+
// IMPORTANT: validAfter, validBefore, and value must be STRINGS
|
|
213
|
+
const header = createX402V1Header(chainName, {
|
|
214
|
+
signature,
|
|
215
|
+
authorization: {
|
|
216
|
+
from,
|
|
217
|
+
to: recipient,
|
|
218
|
+
value: value.toString(),
|
|
219
|
+
validAfter: validAfter.toString(),
|
|
220
|
+
validBefore: validBefore.toString(),
|
|
221
|
+
nonce,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
return encodeX402Header(header);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Create payment with full result object (includes metadata)
|
|
230
|
+
*
|
|
231
|
+
* Same as createPaymentFromWalletClient but returns a PaymentResult
|
|
232
|
+
* object with additional metadata.
|
|
233
|
+
*
|
|
234
|
+
* @param walletClient - The WalletClient from wagmi
|
|
235
|
+
* @param options - Payment options
|
|
236
|
+
* @returns PaymentResult with paymentHeader and metadata
|
|
237
|
+
*/
|
|
238
|
+
export async function createPaymentWithResult(
|
|
239
|
+
walletClient: WalletClient | undefined | null,
|
|
240
|
+
options: WagmiPaymentOptions
|
|
241
|
+
): Promise<PaymentResult> {
|
|
242
|
+
const paymentHeader = await createPaymentFromWalletClient(walletClient, options);
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
success: true,
|
|
246
|
+
paymentHeader,
|
|
247
|
+
network: options.chainName || 'base',
|
|
248
|
+
payer: walletClient?.account.address,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* React hook helper for wagmi integration
|
|
254
|
+
*
|
|
255
|
+
* Returns a function that creates payments using the connected wallet.
|
|
256
|
+
* This is a simple wrapper - for more control, use createPaymentFromWalletClient directly.
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```tsx
|
|
260
|
+
* import { useWalletClient } from 'wagmi';
|
|
261
|
+
* import { useX402Wagmi } from 'uvd-x402-sdk/wagmi';
|
|
262
|
+
*
|
|
263
|
+
* function PayButton() {
|
|
264
|
+
* const { data: walletClient } = useWalletClient();
|
|
265
|
+
* const { createPayment, isReady } = useX402Wagmi(walletClient);
|
|
266
|
+
*
|
|
267
|
+
* return (
|
|
268
|
+
* <button
|
|
269
|
+
* disabled={!isReady}
|
|
270
|
+
* onClick={() => createPayment({ recipient: '0x...', amount: '1.00' })}
|
|
271
|
+
* >
|
|
272
|
+
* Pay
|
|
273
|
+
* </button>
|
|
274
|
+
* );
|
|
275
|
+
* }
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export function useX402Wagmi(walletClient: WalletClient | undefined | null) {
|
|
279
|
+
const isReady = !!walletClient;
|
|
280
|
+
|
|
281
|
+
const createPayment = async (options: WagmiPaymentOptions): Promise<string> => {
|
|
282
|
+
return createPaymentFromWalletClient(walletClient, options);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const createPaymentFull = async (options: WagmiPaymentOptions): Promise<PaymentResult> => {
|
|
286
|
+
return createPaymentWithResult(walletClient, options);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
isReady,
|
|
291
|
+
createPayment,
|
|
292
|
+
createPaymentFull,
|
|
293
|
+
};
|
|
294
|
+
}
|
package/src/chains/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* NEAR (1): Uses NEP-366 meta-transactions
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { ChainConfig, NetworkType } from '../types';
|
|
11
|
+
import type { ChainConfig, NetworkType, TokenType, TokenConfig } from '../types';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Default facilitator URL for x402 payments
|
|
@@ -47,6 +47,26 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
47
47
|
name: 'USD Coin',
|
|
48
48
|
version: '2',
|
|
49
49
|
},
|
|
50
|
+
tokens: {
|
|
51
|
+
usdc: {
|
|
52
|
+
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
53
|
+
decimals: 6,
|
|
54
|
+
name: 'USD Coin',
|
|
55
|
+
version: '2',
|
|
56
|
+
},
|
|
57
|
+
eurc: {
|
|
58
|
+
address: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
59
|
+
decimals: 6,
|
|
60
|
+
name: 'EURC',
|
|
61
|
+
version: '2',
|
|
62
|
+
},
|
|
63
|
+
gho: {
|
|
64
|
+
address: '0x6Bb7a212910682DCFdbd5BCBb3e28FB4E8da10Ee',
|
|
65
|
+
decimals: 18,
|
|
66
|
+
name: 'Gho Token',
|
|
67
|
+
version: '1',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
50
70
|
x402: {
|
|
51
71
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
52
72
|
enabled: true,
|
|
@@ -72,6 +92,26 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
72
92
|
name: 'USD Coin',
|
|
73
93
|
version: '2',
|
|
74
94
|
},
|
|
95
|
+
tokens: {
|
|
96
|
+
usdc: {
|
|
97
|
+
address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
|
|
98
|
+
decimals: 6,
|
|
99
|
+
name: 'USD Coin',
|
|
100
|
+
version: '2',
|
|
101
|
+
},
|
|
102
|
+
eurc: {
|
|
103
|
+
address: '0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD',
|
|
104
|
+
decimals: 6,
|
|
105
|
+
name: 'EURC',
|
|
106
|
+
version: '2',
|
|
107
|
+
},
|
|
108
|
+
ausd: {
|
|
109
|
+
address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
110
|
+
decimals: 6,
|
|
111
|
+
name: 'Agora USD',
|
|
112
|
+
version: '1',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
75
115
|
x402: {
|
|
76
116
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
77
117
|
enabled: true,
|
|
@@ -97,6 +137,44 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
97
137
|
name: 'USD Coin',
|
|
98
138
|
version: '2',
|
|
99
139
|
},
|
|
140
|
+
tokens: {
|
|
141
|
+
usdc: {
|
|
142
|
+
address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
|
|
143
|
+
decimals: 6,
|
|
144
|
+
name: 'USD Coin',
|
|
145
|
+
version: '2',
|
|
146
|
+
},
|
|
147
|
+
eurc: {
|
|
148
|
+
address: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
|
|
149
|
+
decimals: 6,
|
|
150
|
+
name: 'EURC',
|
|
151
|
+
version: '2',
|
|
152
|
+
},
|
|
153
|
+
ausd: {
|
|
154
|
+
address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
155
|
+
decimals: 6,
|
|
156
|
+
name: 'Agora USD',
|
|
157
|
+
version: '1',
|
|
158
|
+
},
|
|
159
|
+
pyusd: {
|
|
160
|
+
address: '0x6c3ea9036406852006290770BEdFcAbA0e23A0e8',
|
|
161
|
+
decimals: 6,
|
|
162
|
+
name: 'PayPal USD',
|
|
163
|
+
version: '1',
|
|
164
|
+
},
|
|
165
|
+
gho: {
|
|
166
|
+
address: '0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f',
|
|
167
|
+
decimals: 18,
|
|
168
|
+
name: 'Gho Token',
|
|
169
|
+
version: '1',
|
|
170
|
+
},
|
|
171
|
+
crvusd: {
|
|
172
|
+
address: '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E',
|
|
173
|
+
decimals: 18,
|
|
174
|
+
name: 'Curve.Fi USD Stablecoin',
|
|
175
|
+
version: '1',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
100
178
|
x402: {
|
|
101
179
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
102
180
|
enabled: true,
|
|
@@ -122,6 +200,20 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
122
200
|
name: 'USD Coin',
|
|
123
201
|
version: '2',
|
|
124
202
|
},
|
|
203
|
+
tokens: {
|
|
204
|
+
usdc: {
|
|
205
|
+
address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',
|
|
206
|
+
decimals: 6,
|
|
207
|
+
name: 'USD Coin',
|
|
208
|
+
version: '2',
|
|
209
|
+
},
|
|
210
|
+
ausd: {
|
|
211
|
+
address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
212
|
+
decimals: 6,
|
|
213
|
+
name: 'Agora USD',
|
|
214
|
+
version: '1',
|
|
215
|
+
},
|
|
216
|
+
},
|
|
125
217
|
x402: {
|
|
126
218
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
127
219
|
enabled: true,
|
|
@@ -147,6 +239,32 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
147
239
|
name: 'USD Coin',
|
|
148
240
|
version: '2',
|
|
149
241
|
},
|
|
242
|
+
tokens: {
|
|
243
|
+
usdc: {
|
|
244
|
+
address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
|
|
245
|
+
decimals: 6,
|
|
246
|
+
name: 'USD Coin',
|
|
247
|
+
version: '2',
|
|
248
|
+
},
|
|
249
|
+
ausd: {
|
|
250
|
+
address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
251
|
+
decimals: 6,
|
|
252
|
+
name: 'Agora USD',
|
|
253
|
+
version: '1',
|
|
254
|
+
},
|
|
255
|
+
gho: {
|
|
256
|
+
address: '0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33',
|
|
257
|
+
decimals: 18,
|
|
258
|
+
name: 'Gho Token',
|
|
259
|
+
version: '1',
|
|
260
|
+
},
|
|
261
|
+
crvusd: {
|
|
262
|
+
address: '0x498Bf2B1e120FeD3ad3D42EA2165E9b73f99C1e5',
|
|
263
|
+
decimals: 18,
|
|
264
|
+
name: 'Curve.Fi USD Stablecoin',
|
|
265
|
+
version: '1',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
150
268
|
x402: {
|
|
151
269
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
152
270
|
enabled: true,
|
|
@@ -172,6 +290,14 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
172
290
|
name: 'USD Coin',
|
|
173
291
|
version: '2',
|
|
174
292
|
},
|
|
293
|
+
tokens: {
|
|
294
|
+
usdc: {
|
|
295
|
+
address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
|
|
296
|
+
decimals: 6,
|
|
297
|
+
name: 'USD Coin',
|
|
298
|
+
version: '2',
|
|
299
|
+
},
|
|
300
|
+
},
|
|
175
301
|
x402: {
|
|
176
302
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
177
303
|
enabled: true,
|
|
@@ -197,6 +323,14 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
197
323
|
name: 'USDC', // Celo uses "USDC" not "USD Coin" for EIP-712
|
|
198
324
|
version: '2',
|
|
199
325
|
},
|
|
326
|
+
tokens: {
|
|
327
|
+
usdc: {
|
|
328
|
+
address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',
|
|
329
|
+
decimals: 6,
|
|
330
|
+
name: 'USDC', // Celo uses "USDC" not "USD Coin" for EIP-712
|
|
331
|
+
version: '2',
|
|
332
|
+
},
|
|
333
|
+
},
|
|
200
334
|
x402: {
|
|
201
335
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
202
336
|
enabled: true,
|
|
@@ -222,6 +356,14 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
222
356
|
name: 'USDC', // HyperEVM uses "USDC" not "USD Coin"
|
|
223
357
|
version: '2',
|
|
224
358
|
},
|
|
359
|
+
tokens: {
|
|
360
|
+
usdc: {
|
|
361
|
+
address: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',
|
|
362
|
+
decimals: 6,
|
|
363
|
+
name: 'USDC', // HyperEVM uses "USDC" not "USD Coin"
|
|
364
|
+
version: '2',
|
|
365
|
+
},
|
|
366
|
+
},
|
|
225
367
|
x402: {
|
|
226
368
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
227
369
|
enabled: true,
|
|
@@ -247,6 +389,14 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
247
389
|
name: 'USDC', // Unichain uses "USDC" not "USD Coin"
|
|
248
390
|
version: '2',
|
|
249
391
|
},
|
|
392
|
+
tokens: {
|
|
393
|
+
usdc: {
|
|
394
|
+
address: '0x078d782b760474a361dda0af3839290b0ef57ad6',
|
|
395
|
+
decimals: 6,
|
|
396
|
+
name: 'USDC', // Unichain uses "USDC" not "USD Coin"
|
|
397
|
+
version: '2',
|
|
398
|
+
},
|
|
399
|
+
},
|
|
250
400
|
x402: {
|
|
251
401
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
252
402
|
enabled: true,
|
|
@@ -272,6 +422,20 @@ export const SUPPORTED_CHAINS: Record<string, ChainConfig> = {
|
|
|
272
422
|
name: 'USDC', // Monad uses "USDC" not "USD Coin"
|
|
273
423
|
version: '2',
|
|
274
424
|
},
|
|
425
|
+
tokens: {
|
|
426
|
+
usdc: {
|
|
427
|
+
address: '0x754704bc059f8c67012fed69bc8a327a5aafb603',
|
|
428
|
+
decimals: 6,
|
|
429
|
+
name: 'USDC', // Monad uses "USDC" not "USD Coin"
|
|
430
|
+
version: '2',
|
|
431
|
+
},
|
|
432
|
+
ausd: {
|
|
433
|
+
address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
434
|
+
decimals: 6,
|
|
435
|
+
name: 'Agora USD',
|
|
436
|
+
version: '1',
|
|
437
|
+
},
|
|
438
|
+
},
|
|
275
439
|
x402: {
|
|
276
440
|
facilitatorUrl: DEFAULT_FACILITATOR_URL,
|
|
277
441
|
enabled: true,
|
|
@@ -511,3 +675,93 @@ export function getExplorerAddressUrl(chainName: string, address: string): strin
|
|
|
511
675
|
return null;
|
|
512
676
|
}
|
|
513
677
|
}
|
|
678
|
+
|
|
679
|
+
// ============================================================================
|
|
680
|
+
// MULTI-TOKEN SUPPORT FUNCTIONS
|
|
681
|
+
// ============================================================================
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Get token configuration for a specific chain and token type
|
|
685
|
+
* Falls back to USDC config if token not found (for backward compatibility)
|
|
686
|
+
*
|
|
687
|
+
* @param chainName - Chain name (e.g., 'ethereum', 'base')
|
|
688
|
+
* @param tokenType - Token type (e.g., 'usdc', 'eurc', 'gho')
|
|
689
|
+
* @returns Token configuration or undefined if chain not found
|
|
690
|
+
*/
|
|
691
|
+
export function getTokenConfig(
|
|
692
|
+
chainName: string,
|
|
693
|
+
tokenType: TokenType = 'usdc'
|
|
694
|
+
): TokenConfig | undefined {
|
|
695
|
+
const chain = getChainByName(chainName);
|
|
696
|
+
if (!chain) return undefined;
|
|
697
|
+
|
|
698
|
+
// Try to get from tokens map first (new multi-token support)
|
|
699
|
+
if (chain.tokens && chain.tokens[tokenType]) {
|
|
700
|
+
return chain.tokens[tokenType];
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Fall back to usdc config for backward compatibility
|
|
704
|
+
if (tokenType === 'usdc') {
|
|
705
|
+
return chain.usdc;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return undefined;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Get list of supported tokens for a chain
|
|
713
|
+
*
|
|
714
|
+
* @param chainName - Chain name (e.g., 'ethereum', 'base')
|
|
715
|
+
* @returns Array of supported token types, or empty array if chain not found
|
|
716
|
+
*/
|
|
717
|
+
export function getSupportedTokens(chainName: string): TokenType[] {
|
|
718
|
+
const chain = getChainByName(chainName);
|
|
719
|
+
if (!chain) return [];
|
|
720
|
+
|
|
721
|
+
// If tokens map exists, return its keys
|
|
722
|
+
if (chain.tokens) {
|
|
723
|
+
return Object.keys(chain.tokens) as TokenType[];
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// Default to just USDC for chains without explicit tokens map
|
|
727
|
+
return ['usdc'];
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Check if a token is supported on a specific chain
|
|
732
|
+
*
|
|
733
|
+
* @param chainName - Chain name (e.g., 'ethereum', 'base')
|
|
734
|
+
* @param tokenType - Token type (e.g., 'usdc', 'eurc', 'gho')
|
|
735
|
+
* @returns true if token is supported on the chain
|
|
736
|
+
*/
|
|
737
|
+
export function isTokenSupported(chainName: string, tokenType: TokenType): boolean {
|
|
738
|
+
const chain = getChainByName(chainName);
|
|
739
|
+
if (!chain) return false;
|
|
740
|
+
|
|
741
|
+
// Check tokens map
|
|
742
|
+
if (chain.tokens && chain.tokens[tokenType]) {
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// USDC is always supported (backward compatibility)
|
|
747
|
+
if (tokenType === 'usdc') {
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Get all chains that support a specific token
|
|
756
|
+
*
|
|
757
|
+
* @param tokenType - Token type (e.g., 'usdc', 'eurc', 'gho')
|
|
758
|
+
* @returns Array of chain configs that support the token
|
|
759
|
+
*/
|
|
760
|
+
export function getChainsByToken(tokenType: TokenType): ChainConfig[] {
|
|
761
|
+
return Object.values(SUPPORTED_CHAINS).filter(chain => {
|
|
762
|
+
if (!chain.x402.enabled) return false;
|
|
763
|
+
if (chain.tokens && chain.tokens[tokenType]) return true;
|
|
764
|
+
if (tokenType === 'usdc') return true; // USDC is universal
|
|
765
|
+
return false;
|
|
766
|
+
});
|
|
767
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -95,6 +95,11 @@ export {
|
|
|
95
95
|
getNetworkType,
|
|
96
96
|
getExplorerTxUrl,
|
|
97
97
|
getExplorerAddressUrl,
|
|
98
|
+
// Multi-token support functions
|
|
99
|
+
getTokenConfig,
|
|
100
|
+
getSupportedTokens,
|
|
101
|
+
isTokenSupported,
|
|
102
|
+
getChainsByToken,
|
|
98
103
|
} from './chains';
|
|
99
104
|
|
|
100
105
|
// x402 utilities
|
|
@@ -121,6 +126,10 @@ export type {
|
|
|
121
126
|
NativeCurrency,
|
|
122
127
|
NetworkType,
|
|
123
128
|
|
|
129
|
+
// Token types (multi-token support)
|
|
130
|
+
TokenType,
|
|
131
|
+
TokenConfig,
|
|
132
|
+
|
|
124
133
|
// Wallet types
|
|
125
134
|
WalletState,
|
|
126
135
|
WalletAdapter,
|