uvd-x402-sdk 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +782 -0
  3. package/dist/index-BrBqP1I8.d.ts +199 -0
  4. package/dist/index-D6Sr4ARD.d.mts +429 -0
  5. package/dist/index-D6Sr4ARD.d.ts +429 -0
  6. package/dist/index-DJ4Cvrev.d.mts +199 -0
  7. package/dist/index.d.mts +3 -0
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.js +1178 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +1146 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/dist/providers/evm/index.d.mts +84 -0
  14. package/dist/providers/evm/index.d.ts +84 -0
  15. package/dist/providers/evm/index.js +740 -0
  16. package/dist/providers/evm/index.js.map +1 -0
  17. package/dist/providers/evm/index.mjs +735 -0
  18. package/dist/providers/evm/index.mjs.map +1 -0
  19. package/dist/providers/near/index.d.mts +99 -0
  20. package/dist/providers/near/index.d.ts +99 -0
  21. package/dist/providers/near/index.js +483 -0
  22. package/dist/providers/near/index.js.map +1 -0
  23. package/dist/providers/near/index.mjs +478 -0
  24. package/dist/providers/near/index.mjs.map +1 -0
  25. package/dist/providers/solana/index.d.mts +115 -0
  26. package/dist/providers/solana/index.d.ts +115 -0
  27. package/dist/providers/solana/index.js +771 -0
  28. package/dist/providers/solana/index.js.map +1 -0
  29. package/dist/providers/solana/index.mjs +765 -0
  30. package/dist/providers/solana/index.mjs.map +1 -0
  31. package/dist/providers/stellar/index.d.mts +67 -0
  32. package/dist/providers/stellar/index.d.ts +67 -0
  33. package/dist/providers/stellar/index.js +306 -0
  34. package/dist/providers/stellar/index.js.map +1 -0
  35. package/dist/providers/stellar/index.mjs +301 -0
  36. package/dist/providers/stellar/index.mjs.map +1 -0
  37. package/dist/react/index.d.mts +73 -0
  38. package/dist/react/index.d.ts +73 -0
  39. package/dist/react/index.js +1218 -0
  40. package/dist/react/index.js.map +1 -0
  41. package/dist/react/index.mjs +1211 -0
  42. package/dist/react/index.mjs.map +1 -0
  43. package/dist/utils/index.d.mts +103 -0
  44. package/dist/utils/index.d.ts +103 -0
  45. package/dist/utils/index.js +575 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/dist/utils/index.mjs +562 -0
  48. package/dist/utils/index.mjs.map +1 -0
  49. package/package.json +149 -0
  50. package/src/chains/index.ts +539 -0
  51. package/src/client/X402Client.ts +663 -0
  52. package/src/client/index.ts +1 -0
  53. package/src/index.ts +166 -0
  54. package/src/providers/evm/index.ts +394 -0
  55. package/src/providers/near/index.ts +664 -0
  56. package/src/providers/solana/index.ts +489 -0
  57. package/src/providers/stellar/index.ts +376 -0
  58. package/src/react/index.tsx +417 -0
  59. package/src/types/index.ts +561 -0
  60. package/src/utils/index.ts +20 -0
  61. package/src/utils/x402.ts +295 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * uvd-x402-sdk - x402 Protocol Utilities
3
+ *
4
+ * Utilities for working with x402 v1 and v2 protocols.
5
+ * Handles version detection, payload encoding, and CAIP-2 conversions.
6
+ */
7
+
8
+ import type {
9
+ X402Header,
10
+ X402HeaderV1,
11
+ X402HeaderV2,
12
+ X402PayloadData,
13
+ X402PaymentOption,
14
+ X402Version,
15
+ ChainConfig,
16
+ } from '../types';
17
+ import { CAIP2_IDENTIFIERS, CAIP2_TO_CHAIN } from '../types';
18
+ import { getChainByName } from '../chains';
19
+
20
+ /**
21
+ * Detect x402 version from a response header or body
22
+ *
23
+ * @param data - The 402 response data (parsed JSON or header value)
24
+ * @returns The detected version (1 or 2)
25
+ */
26
+ export function detectX402Version(data: unknown): X402Version {
27
+ if (typeof data !== 'object' || data === null) {
28
+ return 1; // Default to v1
29
+ }
30
+
31
+ const obj = data as Record<string, unknown>;
32
+
33
+ // Check explicit version field
34
+ if (obj.x402Version === 2) {
35
+ return 2;
36
+ }
37
+
38
+ // Check for v2 indicators
39
+ if (obj.accepts && Array.isArray(obj.accepts)) {
40
+ return 2;
41
+ }
42
+
43
+ // Check if network is in CAIP-2 format
44
+ if (typeof obj.network === 'string') {
45
+ if (obj.network.includes(':')) {
46
+ return 2;
47
+ }
48
+ }
49
+
50
+ return 1;
51
+ }
52
+
53
+ /**
54
+ * Convert chain name to CAIP-2 identifier
55
+ *
56
+ * @param chainName - Chain name (e.g., 'base', 'solana')
57
+ * @returns CAIP-2 identifier (e.g., 'eip155:8453', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')
58
+ */
59
+ export function chainToCAIP2(chainName: string): string {
60
+ const caip2 = CAIP2_IDENTIFIERS[chainName.toLowerCase()];
61
+ if (caip2) {
62
+ return caip2;
63
+ }
64
+
65
+ // Try to construct from chain config
66
+ const chain = getChainByName(chainName);
67
+ if (chain) {
68
+ if (chain.networkType === 'evm') {
69
+ return `eip155:${chain.chainId}`;
70
+ }
71
+ // For non-EVM, return the name as-is with network prefix
72
+ return `${chain.networkType}:${chainName}`;
73
+ }
74
+
75
+ return chainName; // Return as-is if unknown
76
+ }
77
+
78
+ /**
79
+ * Convert CAIP-2 identifier to chain name
80
+ *
81
+ * @param caip2 - CAIP-2 identifier
82
+ * @returns Chain name or null if unknown
83
+ */
84
+ export function caip2ToChain(caip2: string): string | null {
85
+ // Check direct mapping
86
+ if (CAIP2_TO_CHAIN[caip2]) {
87
+ return CAIP2_TO_CHAIN[caip2];
88
+ }
89
+
90
+ // Try to extract from EIP-155 format
91
+ const match = caip2.match(/^eip155:(\d+)$/);
92
+ if (match) {
93
+ const chainId = parseInt(match[1], 10);
94
+ // Find chain by ID
95
+ for (const [name, _config] of Object.entries(CAIP2_IDENTIFIERS)) {
96
+ const chain = getChainByName(name);
97
+ if (chain?.chainId === chainId) {
98
+ return name;
99
+ }
100
+ }
101
+ }
102
+
103
+ // Try to extract from network:name format
104
+ const parts = caip2.split(':');
105
+ if (parts.length === 2) {
106
+ const networkName = parts[1];
107
+ if (getChainByName(networkName)) {
108
+ return networkName;
109
+ }
110
+ }
111
+
112
+ return null;
113
+ }
114
+
115
+ /**
116
+ * Parse network identifier from either v1 or v2 format
117
+ *
118
+ * @param network - Network identifier (v1 string or v2 CAIP-2)
119
+ * @returns Normalized chain name
120
+ */
121
+ export function parseNetworkIdentifier(network: string): string {
122
+ // If it contains a colon, it's likely CAIP-2
123
+ if (network.includes(':')) {
124
+ return caip2ToChain(network) || network;
125
+ }
126
+ return network.toLowerCase();
127
+ }
128
+
129
+ /**
130
+ * Encode x402 payload as base64 header value
131
+ *
132
+ * @param header - The x402 header object
133
+ * @returns Base64-encoded string
134
+ */
135
+ export function encodeX402Header(header: X402Header): string {
136
+ return btoa(JSON.stringify(header));
137
+ }
138
+
139
+ /**
140
+ * Decode x402 header from base64 string
141
+ *
142
+ * @param encoded - Base64-encoded header value
143
+ * @returns Parsed x402 header
144
+ */
145
+ export function decodeX402Header(encoded: string): X402Header {
146
+ const json = atob(encoded);
147
+ return JSON.parse(json) as X402Header;
148
+ }
149
+
150
+ /**
151
+ * Create x402 v1 header
152
+ *
153
+ * @param network - Chain name (e.g., 'base')
154
+ * @param payload - Network-specific payload
155
+ * @returns x402 v1 header object
156
+ */
157
+ export function createX402V1Header(
158
+ network: string,
159
+ payload: X402PayloadData
160
+ ): X402HeaderV1 {
161
+ return {
162
+ x402Version: 1,
163
+ scheme: 'exact',
164
+ network,
165
+ payload,
166
+ };
167
+ }
168
+
169
+ /**
170
+ * Create x402 v2 header
171
+ *
172
+ * @param network - CAIP-2 network identifier
173
+ * @param payload - Network-specific payload
174
+ * @param accepts - Optional array of payment options
175
+ * @returns x402 v2 header object
176
+ */
177
+ export function createX402V2Header(
178
+ network: string,
179
+ payload: X402PayloadData,
180
+ accepts?: X402PaymentOption[]
181
+ ): X402HeaderV2 {
182
+ const header: X402HeaderV2 = {
183
+ x402Version: 2,
184
+ scheme: 'exact',
185
+ network: network.includes(':') ? network : chainToCAIP2(network),
186
+ payload,
187
+ };
188
+
189
+ if (accepts && accepts.length > 0) {
190
+ header.accepts = accepts;
191
+ }
192
+
193
+ return header;
194
+ }
195
+
196
+ /**
197
+ * Create x402 header with automatic version selection
198
+ *
199
+ * @param chainConfig - Chain configuration
200
+ * @param payload - Network-specific payload
201
+ * @param version - Version to use (1, 2, or 'auto')
202
+ * @returns x402 header object
203
+ */
204
+ export function createX402Header(
205
+ chainConfig: ChainConfig,
206
+ payload: X402PayloadData,
207
+ version: X402Version | 'auto' = 'auto'
208
+ ): X402Header {
209
+ // Default to v1 for maximum compatibility
210
+ const effectiveVersion = version === 'auto' ? 1 : version;
211
+
212
+ if (effectiveVersion === 2) {
213
+ return createX402V2Header(chainConfig.name, payload);
214
+ }
215
+
216
+ return createX402V1Header(chainConfig.name, payload);
217
+ }
218
+
219
+ /**
220
+ * Generate payment options array for multi-network support
221
+ *
222
+ * @param chainConfigs - Array of chain configurations
223
+ * @param amount - Amount in USDC (e.g., "10.00")
224
+ * @param facilitator - Optional facilitator URL override
225
+ * @returns Array of x402 v2 payment options
226
+ */
227
+ export function generatePaymentOptions(
228
+ chainConfigs: ChainConfig[],
229
+ amount: string,
230
+ facilitator?: string
231
+ ): X402PaymentOption[] {
232
+ // Convert amount to atomic units for each chain
233
+ return chainConfigs
234
+ .filter(chain => chain.x402.enabled)
235
+ .map(chain => {
236
+ const atomicAmount = Math.floor(
237
+ parseFloat(amount) * Math.pow(10, chain.usdc.decimals)
238
+ ).toString();
239
+
240
+ return {
241
+ network: chainToCAIP2(chain.name),
242
+ asset: chain.usdc.address,
243
+ amount: atomicAmount,
244
+ facilitator: facilitator || chain.x402.facilitatorUrl,
245
+ };
246
+ });
247
+ }
248
+
249
+ /**
250
+ * Check if a network string is in CAIP-2 format
251
+ *
252
+ * @param network - Network identifier
253
+ * @returns True if CAIP-2 format
254
+ */
255
+ export function isCAIP2Format(network: string): boolean {
256
+ return network.includes(':');
257
+ }
258
+
259
+ /**
260
+ * Convert between x402 v1 and v2 header formats
261
+ *
262
+ * @param header - Source header
263
+ * @param targetVersion - Target version
264
+ * @returns Converted header
265
+ */
266
+ export function convertX402Header(
267
+ header: X402Header,
268
+ targetVersion: X402Version
269
+ ): X402Header {
270
+ if (header.x402Version === targetVersion) {
271
+ return header;
272
+ }
273
+
274
+ if (targetVersion === 2) {
275
+ // v1 -> v2
276
+ return {
277
+ x402Version: 2,
278
+ scheme: 'exact',
279
+ network: chainToCAIP2(header.network),
280
+ payload: header.payload,
281
+ };
282
+ } else {
283
+ // v2 -> v1
284
+ const chainName = isCAIP2Format(header.network)
285
+ ? caip2ToChain(header.network) || header.network
286
+ : header.network;
287
+
288
+ return {
289
+ x402Version: 1,
290
+ scheme: 'exact',
291
+ network: chainName,
292
+ payload: header.payload,
293
+ };
294
+ }
295
+ }