uvd-x402-sdk 2.15.2 → 2.16.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 (77) hide show
  1. package/README.md +209 -1
  2. package/dist/adapters/index.d.mts +1 -1
  3. package/dist/adapters/index.d.ts +1 -1
  4. package/dist/adapters/index.js +82 -1
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/adapters/index.mjs +82 -1
  7. package/dist/adapters/index.mjs.map +1 -1
  8. package/dist/backend/index.d.mts +1 -1
  9. package/dist/backend/index.d.ts +1 -1
  10. package/dist/backend/index.js +82 -1
  11. package/dist/backend/index.js.map +1 -1
  12. package/dist/backend/index.mjs +82 -1
  13. package/dist/backend/index.mjs.map +1 -1
  14. package/dist/{index-D3PO3jLW.d.mts → index-1CWNFuXP.d.mts} +10 -2
  15. package/dist/{index-Cwi_VM05.d.ts → index-BYsQM8ga.d.ts} +10 -2
  16. package/dist/{index-BYIugZlE.d.mts → index-B_reIs-L.d.mts} +46 -5
  17. package/dist/{index-BYIugZlE.d.ts → index-B_reIs-L.d.ts} +46 -5
  18. package/dist/index.d.mts +11 -2
  19. package/dist/index.d.ts +11 -2
  20. package/dist/index.js +111 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +110 -3
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/providers/algorand/index.d.mts +1 -1
  25. package/dist/providers/algorand/index.d.ts +1 -1
  26. package/dist/providers/algorand/index.js +95 -2
  27. package/dist/providers/algorand/index.js.map +1 -1
  28. package/dist/providers/algorand/index.mjs +95 -2
  29. package/dist/providers/algorand/index.mjs.map +1 -1
  30. package/dist/providers/evm/index.d.mts +1 -1
  31. package/dist/providers/evm/index.d.ts +1 -1
  32. package/dist/providers/evm/index.js +82 -1
  33. package/dist/providers/evm/index.js.map +1 -1
  34. package/dist/providers/evm/index.mjs +82 -1
  35. package/dist/providers/evm/index.mjs.map +1 -1
  36. package/dist/providers/near/index.d.mts +1 -1
  37. package/dist/providers/near/index.d.ts +1 -1
  38. package/dist/providers/near/index.js +82 -1
  39. package/dist/providers/near/index.js.map +1 -1
  40. package/dist/providers/near/index.mjs +82 -1
  41. package/dist/providers/near/index.mjs.map +1 -1
  42. package/dist/providers/solana/index.d.mts +1 -1
  43. package/dist/providers/solana/index.d.ts +1 -1
  44. package/dist/providers/solana/index.js +82 -1
  45. package/dist/providers/solana/index.js.map +1 -1
  46. package/dist/providers/solana/index.mjs +82 -1
  47. package/dist/providers/solana/index.mjs.map +1 -1
  48. package/dist/providers/stellar/index.d.mts +1 -1
  49. package/dist/providers/stellar/index.d.ts +1 -1
  50. package/dist/providers/stellar/index.js +82 -1
  51. package/dist/providers/stellar/index.js.map +1 -1
  52. package/dist/providers/stellar/index.mjs +82 -1
  53. package/dist/providers/stellar/index.mjs.map +1 -1
  54. package/dist/providers/sui/index.d.mts +105 -0
  55. package/dist/providers/sui/index.d.ts +105 -0
  56. package/dist/providers/sui/index.js +1026 -0
  57. package/dist/providers/sui/index.js.map +1 -0
  58. package/dist/providers/sui/index.mjs +1021 -0
  59. package/dist/providers/sui/index.mjs.map +1 -0
  60. package/dist/react/index.d.mts +3 -3
  61. package/dist/react/index.d.ts +3 -3
  62. package/dist/react/index.js +82 -1
  63. package/dist/react/index.js.map +1 -1
  64. package/dist/react/index.mjs +82 -1
  65. package/dist/react/index.mjs.map +1 -1
  66. package/dist/utils/index.d.mts +1 -1
  67. package/dist/utils/index.d.ts +1 -1
  68. package/dist/utils/index.js +82 -1
  69. package/dist/utils/index.js.map +1 -1
  70. package/dist/utils/index.mjs +82 -1
  71. package/dist/utils/index.mjs.map +1 -1
  72. package/package.json +15 -4
  73. package/src/chains/index.ts +98 -0
  74. package/src/facilitator.ts +18 -0
  75. package/src/index.ts +20 -1
  76. package/src/providers/sui/index.ts +429 -0
  77. package/src/types/index.ts +53 -3
package/README.md CHANGED
@@ -118,12 +118,17 @@ const header = stellar.encodePaymentHeader(payload);
118
118
 
119
119
  ### NEAR
120
120
 
121
+ > **Important:** The SDK's `NEARProvider.signPayment()` only works with **injected wallets** (browser extensions).
122
+ > For **browser-redirect wallets** like MyNearWallet via `@near-wallet-selector`, you must use the popup flow below.
123
+
124
+ #### Option 1: Injected Wallet (Browser Extension)
125
+
121
126
  ```typescript
122
127
  import { NEARProvider } from 'uvd-x402-sdk/near';
123
128
  import { getChainByName } from 'uvd-x402-sdk';
124
129
 
125
130
  const near = new NEARProvider();
126
- const accountId = await near.connect(); // MyNearWallet
131
+ const accountId = await near.connect(); // MyNearWallet browser extension
127
132
  const chainConfig = getChainByName('near')!;
128
133
 
129
134
  const payload = await near.signPayment({
@@ -134,6 +139,209 @@ const payload = await near.signPayment({
134
139
  const header = near.encodePaymentHeader(payload);
135
140
  ```
136
141
 
142
+ #### Option 2: Browser-Redirect Wallet (Popup Flow) - Recommended
143
+
144
+ MyNearWallet via `@near-wallet-selector` is a browser-redirect wallet that requires a popup flow.
145
+ This is the recommended approach and works with the custom MyNearWallet deployment that supports NEP-366.
146
+
147
+ ```typescript
148
+ import { setupWalletSelector } from '@near-wallet-selector/core';
149
+ import { setupModal } from '@near-wallet-selector/modal-ui';
150
+ import { setupMyNearWallet } from '@near-wallet-selector/my-near-wallet';
151
+ import '@near-wallet-selector/modal-ui/styles.css';
152
+
153
+ // Configuration
154
+ const NEAR_CONFIG = {
155
+ usdcContract: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1',
156
+ recipientAccount: 'merchant.near',
157
+ // Custom MyNearWallet with NEP-366 signDelegateAction support
158
+ walletUrl: 'https://mynearwallet.ultravioletadao.xyz',
159
+ };
160
+
161
+ // Step 1: Initialize wallet selector
162
+ const selector = await setupWalletSelector({
163
+ network: 'mainnet',
164
+ modules: [
165
+ setupMyNearWallet({ walletUrl: NEAR_CONFIG.walletUrl }),
166
+ ],
167
+ });
168
+
169
+ const modal = setupModal(selector, {
170
+ contractId: NEAR_CONFIG.usdcContract,
171
+ });
172
+
173
+ // Step 2: Connect wallet
174
+ modal.show(); // User selects wallet
175
+ // Wait for connection via selector.store.observable.subscribe()
176
+ const state = selector.store.getState();
177
+ const accountId = state.accounts[0].accountId;
178
+
179
+ // Step 3: Create payment with popup flow
180
+ async function createNearPayment(amount: string): Promise<string> {
181
+ const amountRaw = Math.floor(parseFloat(amount) * 1_000_000); // 6 decimals
182
+
183
+ // Get access key info and block height from RPC
184
+ const [accessKeyInfo, blockInfo] = await Promise.all([
185
+ getNearAccessKeyInfo(accountId),
186
+ getNearBlockHeight(),
187
+ ]);
188
+
189
+ const nonce = accessKeyInfo.nonce + 1;
190
+ const maxBlockHeight = blockInfo.blockHeight + 1000; // ~17 minutes
191
+
192
+ // Build wallet URL for signDelegateAction
193
+ const popupUrl = new URL(NEAR_CONFIG.walletUrl);
194
+ popupUrl.pathname = '/sign-delegate-action';
195
+ popupUrl.searchParams.set('receiverId', NEAR_CONFIG.usdcContract);
196
+ popupUrl.searchParams.set('actions', JSON.stringify([{
197
+ methodName: 'ft_transfer',
198
+ args: {
199
+ receiver_id: NEAR_CONFIG.recipientAccount,
200
+ amount: amountRaw.toString(),
201
+ memo: 'x402 payment',
202
+ },
203
+ gas: '30000000000000', // 30 TGas
204
+ deposit: '1', // 1 yoctoNEAR
205
+ }]));
206
+ popupUrl.searchParams.set('callbackUrl', window.location.origin + '/near-callback');
207
+ popupUrl.searchParams.set('meta', JSON.stringify({
208
+ sender: accountId,
209
+ nonce,
210
+ maxBlockHeight,
211
+ publicKey: accessKeyInfo.publicKey,
212
+ }));
213
+
214
+ // Open popup
215
+ const popup = window.open(popupUrl.toString(), 'nearWallet', 'width=500,height=700');
216
+ if (!popup) throw new Error('Popup blocked. Please allow popups.');
217
+
218
+ // Wait for redirect with signedDelegateAction
219
+ const signedDelegateAction = await new Promise<string>((resolve, reject) => {
220
+ const checkInterval = setInterval(() => {
221
+ if (popup.closed) {
222
+ clearInterval(checkInterval);
223
+ reject(new Error('Wallet popup closed'));
224
+ return;
225
+ }
226
+ try {
227
+ const url = popup.location.href;
228
+ if (url.includes('signedDelegateAction=')) {
229
+ clearInterval(checkInterval);
230
+ popup.close();
231
+ const params = new URLSearchParams(new URL(url).search);
232
+ const errorCode = params.get('errorCode');
233
+ if (errorCode) {
234
+ reject(new Error(params.get('errorMessage') || errorCode));
235
+ return;
236
+ }
237
+ resolve(params.get('signedDelegateAction')!);
238
+ }
239
+ } catch { /* cross-origin, keep waiting */ }
240
+ }, 500);
241
+
242
+ setTimeout(() => {
243
+ clearInterval(checkInterval);
244
+ if (!popup.closed) popup.close();
245
+ reject(new Error('Popup timeout'));
246
+ }, 300000); // 5 min timeout
247
+ });
248
+
249
+ // Return x402 payload
250
+ return JSON.stringify({
251
+ signedDelegateAction,
252
+ network: 'near',
253
+ });
254
+ }
255
+
256
+ // Helper: Get access key info from NEAR RPC
257
+ async function getNearAccessKeyInfo(accountId: string) {
258
+ const rpcUrls = [
259
+ 'https://near.drpc.org',
260
+ 'https://rpc.mainnet.near.org',
261
+ ];
262
+
263
+ for (const rpcUrl of rpcUrls) {
264
+ try {
265
+ const response = await fetch(rpcUrl, {
266
+ method: 'POST',
267
+ headers: { 'Content-Type': 'application/json' },
268
+ body: JSON.stringify({
269
+ jsonrpc: '2.0',
270
+ id: 'dontcare',
271
+ method: 'query',
272
+ params: {
273
+ request_type: 'view_access_key_list',
274
+ finality: 'final',
275
+ account_id: accountId,
276
+ },
277
+ }),
278
+ });
279
+ const data = await response.json();
280
+ if (data.error) continue;
281
+
282
+ const fullAccessKey = data.result.keys.find(
283
+ (k: any) => k.access_key.permission === 'FullAccess'
284
+ );
285
+ return {
286
+ nonce: fullAccessKey.access_key.nonce,
287
+ publicKey: fullAccessKey.public_key,
288
+ };
289
+ } catch { continue; }
290
+ }
291
+ throw new Error('Failed to get NEAR access key info');
292
+ }
293
+
294
+ // Helper: Get block height from NEAR RPC
295
+ async function getNearBlockHeight() {
296
+ const rpcUrls = [
297
+ 'https://near.drpc.org',
298
+ 'https://rpc.mainnet.near.org',
299
+ ];
300
+
301
+ for (const rpcUrl of rpcUrls) {
302
+ try {
303
+ const response = await fetch(rpcUrl, {
304
+ method: 'POST',
305
+ headers: { 'Content-Type': 'application/json' },
306
+ body: JSON.stringify({
307
+ jsonrpc: '2.0',
308
+ id: 'dontcare',
309
+ method: 'block',
310
+ params: { finality: 'final' },
311
+ }),
312
+ });
313
+ const data = await response.json();
314
+ if (data.error) continue;
315
+ return { blockHeight: data.result.header.height };
316
+ } catch { continue; }
317
+ }
318
+ throw new Error('Failed to get NEAR block height');
319
+ }
320
+
321
+ // Step 4: Encode payment header
322
+ function encodeNearPaymentHeader(payload: string): string {
323
+ const parsed = JSON.parse(payload);
324
+ const x402Payload = {
325
+ x402Version: 1,
326
+ scheme: 'exact',
327
+ network: 'near',
328
+ payload: {
329
+ signedDelegateAction: parsed.signedDelegateAction,
330
+ },
331
+ };
332
+ return btoa(JSON.stringify(x402Payload));
333
+ }
334
+
335
+ // Usage
336
+ const payload = await createNearPayment('10.00');
337
+ const header = encodeNearPaymentHeader(payload);
338
+ await fetch('/api/purchase', {
339
+ headers: { 'X-PAYMENT': header },
340
+ });
341
+ ```
342
+
343
+ See [402milly's full implementation](https://github.com/UltravioletaDAO/402milly/blob/main/frontend/src/services/x402-sdk.ts) for a production-ready example.
344
+
137
345
  ## Wagmi/RainbowKit
138
346
 
139
347
  ```typescript
@@ -1,4 +1,4 @@
1
- import { l as X402Version, f as PaymentResult } from '../index-BYIugZlE.mjs';
1
+ import { m as X402Version, f as PaymentResult } from '../index-B_reIs-L.mjs';
2
2
 
3
3
  /**
4
4
  * uvd-x402-sdk - Wagmi/Viem Adapter
@@ -1,4 +1,4 @@
1
- import { l as X402Version, f as PaymentResult } from '../index-BYIugZlE.js';
1
+ import { m as X402Version, f as PaymentResult } from '../index-B_reIs-L.js';
2
2
 
3
3
  /**
4
4
  * uvd-x402-sdk - Wagmi/Viem Adapter
@@ -613,6 +613,84 @@ var SUPPORTED_CHAINS = {
613
613
  facilitatorUrl: DEFAULT_FACILITATOR_URL,
614
614
  enabled: true
615
615
  }
616
+ },
617
+ // ============================================================================
618
+ // SUI (2 networks) - Uses sponsored transactions (facilitator pays gas)
619
+ // ============================================================================
620
+ sui: {
621
+ chainId: 0,
622
+ // Non-EVM
623
+ chainIdHex: "0x0",
624
+ name: "sui",
625
+ displayName: "Sui",
626
+ networkType: "sui",
627
+ rpcUrl: "https://fullnode.mainnet.sui.io:443",
628
+ explorerUrl: "https://suiscan.xyz/mainnet",
629
+ nativeCurrency: {
630
+ name: "Sui",
631
+ symbol: "SUI",
632
+ decimals: 9
633
+ },
634
+ usdc: {
635
+ // USDC coin type on Sui mainnet
636
+ address: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
637
+ decimals: 6,
638
+ name: "USDC",
639
+ version: "1"
640
+ },
641
+ tokens: {
642
+ usdc: {
643
+ address: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
644
+ decimals: 6,
645
+ name: "USDC",
646
+ version: "1"
647
+ },
648
+ ausd: {
649
+ // AUSD (Agora USD) coin type on Sui mainnet
650
+ address: "0x2053d08c1e2bd02791056171aab0fd12bd7cd7efad2ab8f6b9c8902f14df2ff2::ausd::AUSD",
651
+ decimals: 6,
652
+ name: "AUSD",
653
+ version: "1"
654
+ }
655
+ },
656
+ x402: {
657
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
658
+ enabled: true
659
+ }
660
+ },
661
+ "sui-testnet": {
662
+ chainId: 0,
663
+ // Non-EVM
664
+ chainIdHex: "0x0",
665
+ name: "sui-testnet",
666
+ displayName: "Sui Testnet",
667
+ networkType: "sui",
668
+ rpcUrl: "https://fullnode.testnet.sui.io:443",
669
+ explorerUrl: "https://suiscan.xyz/testnet",
670
+ nativeCurrency: {
671
+ name: "Sui",
672
+ symbol: "SUI",
673
+ decimals: 9
674
+ },
675
+ usdc: {
676
+ // USDC coin type on Sui testnet
677
+ address: "0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC",
678
+ decimals: 6,
679
+ name: "USDC",
680
+ version: "1"
681
+ },
682
+ tokens: {
683
+ usdc: {
684
+ address: "0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC",
685
+ decimals: 6,
686
+ name: "USDC",
687
+ version: "1"
688
+ }
689
+ },
690
+ x402: {
691
+ facilitatorUrl: DEFAULT_FACILITATOR_URL,
692
+ enabled: true
693
+ }
616
694
  }
617
695
  };
618
696
  function getChainByName(name) {
@@ -641,7 +719,10 @@ var CAIP2_IDENTIFIERS = {
641
719
  near: "near:mainnet",
642
720
  // Algorand
643
721
  algorand: "algorand:mainnet",
644
- "algorand-testnet": "algorand:testnet"
722
+ "algorand-testnet": "algorand:testnet",
723
+ // Sui
724
+ sui: "sui:mainnet",
725
+ "sui-testnet": "sui:testnet"
645
726
  };
646
727
  Object.fromEntries(
647
728
  Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])