uvd-x402-sdk 2.2.2 → 2.4.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.
Files changed (57) hide show
  1. package/dist/adapters/index.d.mts +1 -1
  2. package/dist/adapters/index.d.ts +1 -1
  3. package/dist/adapters/index.js +83 -5
  4. package/dist/adapters/index.js.map +1 -1
  5. package/dist/adapters/index.mjs +83 -5
  6. package/dist/adapters/index.mjs.map +1 -1
  7. package/dist/{index-OZTSi1rJ.d.ts → index-BYX9BU79.d.ts} +1 -1
  8. package/dist/{index-I60aHxwu.d.mts → index-BrFeSWKm.d.mts} +1 -1
  9. package/dist/{index-BG738nMY.d.mts → index-DR2vXt-c.d.mts} +2 -1
  10. package/dist/{index-BG738nMY.d.ts → index-DR2vXt-c.d.ts} +2 -1
  11. package/dist/index.d.mts +3 -3
  12. package/dist/index.d.ts +3 -3
  13. package/dist/index.js +247 -139
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.mjs +246 -140
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/providers/evm/index.d.mts +1 -1
  18. package/dist/providers/evm/index.d.ts +1 -1
  19. package/dist/providers/evm/index.js +83 -5
  20. package/dist/providers/evm/index.js.map +1 -1
  21. package/dist/providers/evm/index.mjs +83 -5
  22. package/dist/providers/evm/index.mjs.map +1 -1
  23. package/dist/providers/near/index.d.mts +1 -1
  24. package/dist/providers/near/index.d.ts +1 -1
  25. package/dist/providers/near/index.js.map +1 -1
  26. package/dist/providers/near/index.mjs.map +1 -1
  27. package/dist/providers/solana/index.d.mts +1 -1
  28. package/dist/providers/solana/index.d.ts +1 -1
  29. package/dist/providers/solana/index.js +24 -5
  30. package/dist/providers/solana/index.js.map +1 -1
  31. package/dist/providers/solana/index.mjs +24 -5
  32. package/dist/providers/solana/index.mjs.map +1 -1
  33. package/dist/providers/stellar/index.d.mts +1 -1
  34. package/dist/providers/stellar/index.d.ts +1 -1
  35. package/dist/providers/stellar/index.js.map +1 -1
  36. package/dist/providers/stellar/index.mjs.map +1 -1
  37. package/dist/react/index.d.mts +3 -3
  38. package/dist/react/index.d.ts +3 -3
  39. package/dist/react/index.js +83 -5
  40. package/dist/react/index.js.map +1 -1
  41. package/dist/react/index.mjs +83 -5
  42. package/dist/react/index.mjs.map +1 -1
  43. package/dist/utils/index.d.mts +31 -2
  44. package/dist/utils/index.d.ts +31 -2
  45. package/dist/utils/index.js +125 -5
  46. package/dist/utils/index.js.map +1 -1
  47. package/dist/utils/index.mjs +124 -6
  48. package/dist/utils/index.mjs.map +1 -1
  49. package/package.json +2 -2
  50. package/src/adapters/wagmi.ts +4 -1
  51. package/src/chains/index.ts +23 -5
  52. package/src/client/X402Client.ts +4 -0
  53. package/src/index.ts +3 -0
  54. package/src/providers/evm/index.ts +4 -0
  55. package/src/types/index.ts +2 -1
  56. package/src/utils/index.ts +5 -0
  57. package/src/utils/validation.ts +151 -0
package/src/index.ts CHANGED
@@ -116,6 +116,9 @@ export {
116
116
  generatePaymentOptions,
117
117
  isCAIP2Format,
118
118
  convertX402Header,
119
+ // Validation utilities
120
+ validateRecipient,
121
+ validateAmount,
119
122
  } from './utils';
120
123
 
121
124
  // Types
@@ -32,6 +32,7 @@ import type {
32
32
  } from '../../types';
33
33
  import { X402Error } from '../../types';
34
34
  import { getChainByName, getChainById, getTokenConfig } from '../../chains';
35
+ import { validateRecipient } from '../../utils';
35
36
 
36
37
  /**
37
38
  * Ethereum provider interface
@@ -278,6 +279,9 @@ export class EVMProvider implements WalletAdapter {
278
279
  // Get recipient
279
280
  const recipient = paymentInfo.recipients?.evm || paymentInfo.recipient;
280
281
 
282
+ // Validate recipient address - prevents empty/invalid addresses
283
+ validateRecipient(recipient, 'evm');
284
+
281
285
  // Generate random nonce
282
286
  const nonceBytes = new Uint8Array(32);
283
287
  if (typeof window !== 'undefined' && window.crypto) {
@@ -26,8 +26,9 @@ export type NetworkType = 'evm' | 'svm' | 'solana' | 'stellar' | 'near';
26
26
  * - eurc: Euro Coin (Circle) - 6 decimals
27
27
  * - ausd: Agora USD (Agora Finance) - 6 decimals
28
28
  * - pyusd: PayPal USD (PayPal/Paxos) - 6 decimals
29
+ * - usdt: Tether USD (USDT0 omnichain via LayerZero) - 6 decimals
29
30
  */
30
- export type TokenType = 'usdc' | 'eurc' | 'ausd' | 'pyusd';
31
+ export type TokenType = 'usdc' | 'eurc' | 'ausd' | 'pyusd' | 'usdt';
31
32
 
32
33
  /**
33
34
  * Token configuration for EIP-712 signing and transfers
@@ -18,3 +18,8 @@ export {
18
18
  isCAIP2Format,
19
19
  convertX402Header,
20
20
  } from './x402';
21
+
22
+ export {
23
+ validateRecipient,
24
+ validateAmount,
25
+ } from './validation';
@@ -0,0 +1,151 @@
1
+ /**
2
+ * uvd-x402-sdk - Validation Utilities
3
+ *
4
+ * Functions for validating payment parameters to prevent
5
+ * invalid or empty values from being processed.
6
+ */
7
+
8
+ import { X402Error } from '../types';
9
+
10
+ /**
11
+ * Regular expression for validating Ethereum addresses
12
+ */
13
+ const ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
14
+
15
+ /**
16
+ * Regular expression for validating Solana addresses (base58, 32-44 chars)
17
+ */
18
+ const SOLANA_ADDRESS_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
19
+
20
+ /**
21
+ * Regular expression for validating Stellar addresses (G... format)
22
+ */
23
+ const STELLAR_ADDRESS_REGEX = /^G[A-Z2-7]{55}$/;
24
+
25
+ /**
26
+ * Regular expression for validating NEAR addresses
27
+ */
28
+ const NEAR_ADDRESS_REGEX = /^[a-z0-9._-]+$/;
29
+
30
+ /**
31
+ * Validate that a recipient address is present and valid
32
+ *
33
+ * This function ensures that:
34
+ * 1. The recipient is not null, undefined, or empty
35
+ * 2. The recipient is not just whitespace
36
+ * 3. For EVM, it's a valid checksummed or lowercase 0x address
37
+ *
38
+ * @param recipient - The recipient address to validate
39
+ * @param networkType - Optional network type for format validation
40
+ * @throws X402Error with code 'INVALID_RECIPIENT' if validation fails
41
+ */
42
+ export function validateRecipient(
43
+ recipient: string | undefined | null,
44
+ networkType?: 'evm' | 'svm' | 'solana' | 'stellar' | 'near'
45
+ ): asserts recipient is string {
46
+ // Check for null, undefined, or empty
47
+ if (!recipient) {
48
+ throw new X402Error(
49
+ 'Recipient address is required. The payTo/recipient field cannot be empty. ' +
50
+ 'Please provide a valid recipient address where payments should be sent.',
51
+ 'INVALID_RECIPIENT'
52
+ );
53
+ }
54
+
55
+ // Check for whitespace-only
56
+ const trimmed = recipient.trim();
57
+ if (trimmed === '') {
58
+ throw new X402Error(
59
+ 'Recipient address cannot be empty or whitespace. ' +
60
+ 'Please provide a valid recipient address.',
61
+ 'INVALID_RECIPIENT'
62
+ );
63
+ }
64
+
65
+ // Network-specific validation
66
+ if (networkType) {
67
+ switch (networkType) {
68
+ case 'evm':
69
+ if (!ETH_ADDRESS_REGEX.test(trimmed)) {
70
+ throw new X402Error(
71
+ `Invalid EVM recipient address: "${trimmed}". ` +
72
+ 'Expected a 40-character hexadecimal address starting with 0x.',
73
+ 'INVALID_RECIPIENT'
74
+ );
75
+ }
76
+ break;
77
+
78
+ case 'svm':
79
+ case 'solana':
80
+ if (!SOLANA_ADDRESS_REGEX.test(trimmed)) {
81
+ throw new X402Error(
82
+ `Invalid Solana recipient address: "${trimmed}". ` +
83
+ 'Expected a base58-encoded public key (32-44 characters).',
84
+ 'INVALID_RECIPIENT'
85
+ );
86
+ }
87
+ break;
88
+
89
+ case 'stellar':
90
+ if (!STELLAR_ADDRESS_REGEX.test(trimmed)) {
91
+ throw new X402Error(
92
+ `Invalid Stellar recipient address: "${trimmed}". ` +
93
+ 'Expected a G-prefixed public key (56 characters).',
94
+ 'INVALID_RECIPIENT'
95
+ );
96
+ }
97
+ break;
98
+
99
+ case 'near':
100
+ if (!NEAR_ADDRESS_REGEX.test(trimmed) || trimmed.length > 64) {
101
+ throw new X402Error(
102
+ `Invalid NEAR recipient address: "${trimmed}". ` +
103
+ 'Expected a valid NEAR account ID.',
104
+ 'INVALID_RECIPIENT'
105
+ );
106
+ }
107
+ break;
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Validate payment amount
114
+ *
115
+ * Ensures the amount is a valid positive number string
116
+ *
117
+ * @param amount - The amount string to validate
118
+ * @throws X402Error with code 'INVALID_AMOUNT' if validation fails
119
+ */
120
+ export function validateAmount(amount: string | undefined | null): asserts amount is string {
121
+ if (!amount) {
122
+ throw new X402Error(
123
+ 'Payment amount is required.',
124
+ 'INVALID_AMOUNT'
125
+ );
126
+ }
127
+
128
+ const trimmed = amount.trim();
129
+ if (trimmed === '') {
130
+ throw new X402Error(
131
+ 'Payment amount cannot be empty.',
132
+ 'INVALID_AMOUNT'
133
+ );
134
+ }
135
+
136
+ // Parse as number
137
+ const num = parseFloat(trimmed);
138
+ if (isNaN(num)) {
139
+ throw new X402Error(
140
+ `Invalid payment amount: "${trimmed}". Expected a valid number.`,
141
+ 'INVALID_AMOUNT'
142
+ );
143
+ }
144
+
145
+ if (num <= 0) {
146
+ throw new X402Error(
147
+ `Payment amount must be positive. Got: ${trimmed}`,
148
+ 'INVALID_AMOUNT'
149
+ );
150
+ }
151
+ }