stableflow-ai-sdk 2.0.2 → 2.0.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.
package/README.md CHANGED
@@ -23,13 +23,19 @@ pnpm add stableflow-ai-sdk
23
23
  ## Quick Start
24
24
 
25
25
  ```typescript
26
- import { OpenAPI, SFA, tokens, EVMWallet } from 'stableflow-ai-sdk';
26
+ import { OpenAPI, SFA, tokens, EVMWallet, setRpcUrls } from 'stableflow-ai-sdk';
27
27
  import { ethers } from 'ethers';
28
28
 
29
29
  // Initialize the API client
30
30
  OpenAPI.BASE = 'https://api.stableflow.ai';
31
31
  OpenAPI.TOKEN = "your-JSON-Web-Token";
32
32
 
33
+ // (Optional) Configure custom RPC endpoints
34
+ setRpcUrls({
35
+ "eth": ["https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"],
36
+ "arb": ["https://arbitrum-one-rpc.publicnode.com"],
37
+ });
38
+
33
39
  // Get wallet instance (example with EVM)
34
40
  const provider = new ethers.BrowserProvider(window.ethereum);
35
41
  const signer = await provider.getSigner();
@@ -51,14 +57,17 @@ const quotes = await SFA.getAllQuote({
51
57
  refundTo: '0x...', // refund address
52
58
  amountWei: ethers.parseUnits('100', fromToken!.decimals).toString(),
53
59
  slippageTolerance: 0.5, // 0.5%
54
- appFees: [
55
- {
56
- // your fee collection address
57
- recipient: "stableflow.near",
58
- // Fee rate, as a percentage of the amount. 100 = 1%, 1 = 0.01%
59
- fee: 100,
60
- },
61
- ],
60
+ // Optional
61
+ oneclickParams: {
62
+ appFees: [
63
+ {
64
+ // your fee collection address
65
+ recipient: "stableflow.near",
66
+ // Fee rate, as a percentage of the amount. 100 = 1%, 1 = 0.01%
67
+ fee: 100,
68
+ },
69
+ ],
70
+ },
62
71
  });
63
72
 
64
73
  // Select the best quote and send transaction
@@ -115,7 +124,14 @@ const quotes = await SFA.getAllQuote({
115
124
  refundTo: string, // Refund address on source chain
116
125
  amountWei: string, // Amount in smallest units (wei/satoshi/etc.)
117
126
  slippageTolerance: number, // Slippage tolerance percentage (e.g., 0.5 for 0.5%)
118
- appFees?: { recipient: string; fee: number; }[]; // Custom fee rates
127
+ oneclickParams?: {
128
+ // Custom fee rates
129
+ appFees?: { recipient: string; fee: number; }[];
130
+ // default is EXACT_INPUT
131
+ swapType?: "EXACT_INPUT" | "EXACT_OUTPUT";
132
+ // default is true
133
+ isProxy?: boolean;
134
+ };
119
135
  });
120
136
  ```
121
137
 
@@ -299,11 +315,12 @@ const finalStatus = await pollTransactionStatus(Service.OneClick, {
299
315
 
300
316
  ## Supported Bridge Services
301
317
 
302
- The SDK supports three bridge services:
318
+ The SDK supports three bridge services for general cross-chain swaps, plus a dedicated Hyperliquid deposit flow:
303
319
 
304
320
  - **OneClick** (`Service.OneClick`) - Native StableFlow bridge service
305
321
  - **CCTP** (`Service.CCTP`) - Circle's Cross-Chain Transfer Protocol
306
322
  - **USDT0** (`Service.Usdt0`) - LayerZero-based USDT bridge
323
+ - **Hyperliquid** – Deposit from multiple chains into Hyperliquid (destination: Arbitrum USDC). See [Hyperliquid Service](#hyperliquid-service) below.
307
324
 
308
325
  Each service has different characteristics:
309
326
  - Different fee structures
@@ -311,14 +328,113 @@ Each service has different characteristics:
311
328
  - Different processing times
312
329
  - Different minimum/maximum amounts
313
330
 
331
+ ### USDT0 Service Features
332
+
333
+ The USDT0 service provides LayerZero-based USDT bridging with the following capabilities:
334
+
335
+ - **Multi-chain Support**: Supports bridging from EVM chains (Ethereum, Arbitrum, Polygon, Optimism, etc.), Solana, and Tron
336
+ - **Multi-hop Routing**: Automatically handles multi-hop transfers when direct routes are not available (e.g., Solana → Arbitrum → Ethereum)
337
+ - **Dynamic Time Estimation**: Calculates estimated completion time based on source and destination chain block times and confirmations
338
+ - **Accurate Fee Estimation**: Improved fee calculation including LayerZero message fees, gas costs, and legacy mesh transfer fees (0.03% for legacy routes)
339
+ - **Legacy and Upgradeable Support**: Seamlessly handles both legacy and upgradeable OFT contracts
340
+
314
341
  Use `getAllQuote` to compare all available routes and select the best one for your use case.
315
342
 
343
+ ### Hyperliquid Service
344
+
345
+ The Hyperliquid service enables depositing tokens from multiple source chains into Hyperliquid. The destination is fixed as **USDC on Arbitrum**; the SDK uses the OneClick bridge under the hood to swap/bridge from your chosen source token to Arbitrum USDC, then submits a deposit with permit to the Hyperliquid deposit API.
346
+
347
+ **Exports:**
348
+
349
+ - `Hyperliquid` – singleton service instance
350
+ - `HyperliquidFromTokens` – list of supported source tokens (all tokens except Arbitrum USDC)
351
+ - `HyperliuquidToToken` – destination token config (Arbitrum USDC)
352
+ - `HyperliuquidMinAmount` – minimum amount in wei (e.g. 5 USDC)
353
+ - Types: `HyperliquidQuoteParams`, `HyperliquidTransferParams`, `HyperliquidDepositParams`, `HyperliquidGetStatusParams`, `HyperliquidDepositResponse`, `HyperliquidDepositStatusResponse`, etc.
354
+
355
+ **Methods:**
356
+
357
+ | Method | Description |
358
+ |--------|-------------|
359
+ | `quote(params)` | Get a quote for depositing to Hyperliquid. Returns `{ quote, error }`. |
360
+ | `transfer(params)` | Send tokens from the user's wallet to the bridge (uses OneClick). Returns source chain tx hash. |
361
+ | `deposit(params)` | After transfer, submit deposit with EIP-2612 permit. Returns `{ code, data: { depositId } }`. |
362
+ | `getStatus(params)` | Query deposit status by `depositId`. Returns `{ code, data: { status, txHash } }`. |
363
+
364
+ **Flow (typical):**
365
+
366
+ 1. User selects source token from `HyperliquidFromTokens` and amount (≥ `HyperliuquidMinAmount`).
367
+ 2. Call `Hyperliquid.quote(params)` (optionally with `dry: true` for preview, then `dry: false` to get `depositAddress`).
368
+ 3. Call `Hyperliquid.transfer({ wallet, quote, evmWallet, evmWalletAddress })` to send tokens; receive `txhash`.
369
+ 4. Optionally switch the wallet to Arbitrum, then call `Hyperliquid.deposit({ ...transferParams, txhash })` to submit the deposit and get `depositId`.
370
+ 5. Poll or one-off check with `Hyperliquid.getStatus({ depositId })` for `status` and `txHash`. `status` enum is `type HyperliquidDepositStatus = "PROCESSING" | "SUCCESS" | "REFUNDED" | "FAILED";`
371
+
372
+ **Example:**
373
+
374
+ ```typescript
375
+ import {
376
+ Hyperliquid,
377
+ HyperliquidFromTokens,
378
+ HyperliuquidToToken,
379
+ HyperliuquidMinAmount,
380
+ OpenAPI,
381
+ } from 'stableflow-ai-sdk';
382
+ import Big from 'big.js';
383
+
384
+ OpenAPI.BASE = 'https://api.stableflow.ai';
385
+ OpenAPI.TOKEN = 'your-JWT';
386
+
387
+ // 1. Quote (dry: false to get deposit address for transfer)
388
+ const quoteRes = await Hyperliquid.quote({
389
+ dry: false,
390
+ slippageTolerance: 0.05,
391
+ refundTo: evmAddress,
392
+ recipient: evmAddress,
393
+ wallet,
394
+ fromToken: selectedFromToken,
395
+ prices: {},
396
+ amountWei: Big(amount).times(10 ** HyperliuquidToToken.decimals).toFixed(0, 0),
397
+ });
398
+ if (quoteRes.error || !quoteRes.quote) throw new Error(quoteRes.error || 'No quote');
399
+ const quote = quoteRes.quote;
400
+
401
+ // 2. Transfer on source chain
402
+ const txhash = await Hyperliquid.transfer({
403
+ wallet,
404
+ evmWallet,
405
+ evmWalletAddress,
406
+ quote,
407
+ });
408
+
409
+ // 3. Submit deposit (after switching to Arbitrum if needed)
410
+ const depositRes = await Hyperliquid.deposit({
411
+ wallet,
412
+ evmWallet,
413
+ evmWalletAddress,
414
+ quote,
415
+ txhash,
416
+ });
417
+ const depositId = depositRes.data?.depositId;
418
+
419
+ // 4. Check status
420
+ const statusRes = await Hyperliquid.getStatus({ depositId: String(depositId) });
421
+ // statusRes.data.status, statusRes.data.txHash
422
+ ```
423
+
424
+ **Token configs:**
425
+
426
+ - Use `HyperliquidFromTokens` for the source token list (filter by `chainType === 'evm'` if you only support EVM).
427
+ - Destination is always `HyperliuquidToToken` (Arbitrum USDC).
428
+ - Enforce minimum amount with `HyperliuquidMinAmount` so users do not send below the bridge minimum.
429
+
316
430
  ## Wallet Integration
317
431
 
318
432
  The SDK supports multiple wallet types:
319
433
 
320
434
  ### EVM Wallets (Ethereum, Arbitrum, Polygon, etc.)
321
435
 
436
+ **Using ethers.js with BrowserProvider:**
437
+
322
438
  ```typescript
323
439
  import { EVMWallet } from 'stableflow-ai-sdk';
324
440
  import { ethers } from 'ethers';
@@ -328,40 +444,145 @@ const signer = await provider.getSigner();
328
444
  const wallet = new EVMWallet(provider, signer);
329
445
  ```
330
446
 
447
+ **Using wagmi/viem (recommended for React apps):**
448
+
449
+ ```typescript
450
+ import { EVMWallet } from 'stableflow-ai-sdk';
451
+ import { ethers } from 'ethers';
452
+ import { usePublicClient, useWalletClient } from 'wagmi';
453
+
454
+ // In your React component
455
+ const publicClient = usePublicClient();
456
+ const { data: walletClient } = useWalletClient();
457
+
458
+ const provider = new ethers.BrowserProvider(publicClient);
459
+ const signer = walletClient
460
+ ? await new ethers.BrowserProvider(walletClient).getSigner()
461
+ : null;
462
+
463
+ const wallet = new EVMWallet(provider, signer);
464
+ ```
465
+
331
466
  ### Solana Wallets
332
467
 
468
+ **Using @solana/wallet-adapter-react (recommended for React apps):**
469
+
470
+ ```typescript
471
+ import { SolanaWallet } from 'stableflow-ai-sdk';
472
+ import { useWallet } from '@solana/wallet-adapter-react';
473
+
474
+ // In your React component
475
+ const { publicKey, signTransaction } = useWallet();
476
+
477
+ const wallet = new SolanaWallet({
478
+ publicKey: publicKey,
479
+ signer: { signTransaction }
480
+ });
481
+ ```
482
+
483
+ **Using wallet adapter directly:**
484
+
333
485
  ```typescript
334
486
  import { SolanaWallet } from 'stableflow-ai-sdk';
335
487
  import { Connection, PublicKey } from '@solana/web3.js';
336
488
 
337
489
  const connection = new Connection('https://api.mainnet-beta.solana.com');
338
- const wallet = new SolanaWallet(connection, publicKey, signTransaction);
490
+ const publicKey = new PublicKey('YOUR_SOLANA_ADDRESS');
491
+
492
+ const wallet = new SolanaWallet({
493
+ publicKey: publicKey,
494
+ signer: {
495
+ signTransaction: async (transaction) => {
496
+ // Sign transaction using your wallet adapter
497
+ // Example with Phantom:
498
+ // const provider = window.solana;
499
+ // return await provider.signTransaction(transaction);
500
+ return signedTransaction;
501
+ }
502
+ }
503
+ });
339
504
  ```
340
505
 
506
+ **Note**: Solana wallets can be used as the source chain for USDT0 bridging, enabling cross-chain transfers from Solana to EVM chains, Tron, and other supported networks.
507
+
341
508
  ### Near Wallets
342
509
 
343
510
  ```typescript
344
511
  import { NearWallet } from 'stableflow-ai-sdk';
512
+ import { setupWalletSelector } from '@near-wallet-selector/core';
513
+
514
+ // Setup wallet selector (e.g., using @near-wallet-selector)
515
+ const selector = await setupWalletSelector({
516
+ network: 'mainnet',
517
+ modules: [
518
+ // Add your wallet modules here
519
+ ]
520
+ });
345
521
 
346
- const wallet = new NearWallet(connection, accountId, keyPair);
522
+ const wallet = new NearWallet(selector);
347
523
  ```
348
524
 
525
+ **Note**: NearWallet requires a wallet selector instance from `@near-wallet-selector/core`. The selector handles wallet connection and transaction signing.
526
+
349
527
  ### Tron Wallets
350
528
 
351
529
  ```typescript
352
530
  import { TronWallet } from 'stableflow-ai-sdk';
353
531
 
354
- const wallet = new TronWallet(tronWeb);
532
+ // Using TronLink or other Tron wallet adapters
533
+ const wallet = new TronWallet({
534
+ signAndSendTransaction: async (transaction: any) => {
535
+ // Sign transaction using TronWeb
536
+ const signedTransaction = await window.tronWeb.trx.sign(transaction);
537
+ // Send signed transaction
538
+ return await window.tronWeb.trx.sendRawTransaction(signedTransaction);
539
+ },
540
+ address: window.tronWeb?.defaultAddress?.base58, // User's Tron address
541
+ });
542
+ ```
543
+
544
+ **With TronLink Wallet:**
545
+
546
+ ```typescript
547
+ import { TronWallet } from 'stableflow-ai-sdk';
548
+
549
+ // Wait for TronLink to be available
550
+ if (window.tronWeb && window.tronWeb.ready) {
551
+ const wallet = new TronWallet({
552
+ signAndSendTransaction: async (transaction: any) => {
553
+ const signedTransaction = await window.tronWeb.trx.sign(transaction);
554
+ const result = await window.tronWeb.trx.sendRawTransaction(signedTransaction);
555
+ // Return transaction ID (txid)
556
+ return typeof result === 'string' ? result : result.txid;
557
+ },
558
+ address: window.tronWeb.defaultAddress.base58,
559
+ });
560
+ }
355
561
  ```
356
562
 
563
+ **Note:** The `signAndSendTransaction` function should:
564
+ - Accept a transaction object as parameter
565
+ - Sign the transaction using the connected wallet
566
+ - Send the signed transaction to the network
567
+ - Return the transaction ID (txid) as a string, or an object with a `txid` property
568
+
357
569
  ### Aptos Wallets
358
570
 
359
571
  ```typescript
360
572
  import { AptosWallet } from 'stableflow-ai-sdk';
573
+ import { useWallet } from '@aptos-labs/wallet-adapter-react';
574
+
575
+ // Using Aptos wallet adapter
576
+ const { account, signAndSubmitTransaction } = useWallet();
361
577
 
362
- const wallet = new AptosWallet(provider, signer);
578
+ const wallet = new AptosWallet({
579
+ account: account,
580
+ signAndSubmitTransaction: signAndSubmitTransaction,
581
+ });
363
582
  ```
364
583
 
584
+ **Note**: AptosWallet requires an account object and a `signAndSubmitTransaction` function from the Aptos wallet adapter (e.g., `@aptos-labs/wallet-adapter-react`).
585
+
365
586
  ## Token Configuration
366
587
 
367
588
  The SDK provides pre-configured token information:
@@ -395,20 +616,28 @@ Each token configuration includes:
395
616
  - `contractAddress` - Token contract address
396
617
  - `assetId` - StableFlow asset identifier
397
618
  - `services` - Array of supported bridge services
398
- - `rpcUrl` - RPC endpoint URL
619
+ - `rpcUrls` - RPC endpoint URLs
399
620
 
400
621
  ## Complete Example
401
622
 
623
+ ### Example 1: EVM to EVM Bridge (Ethereum → Arbitrum)
624
+
402
625
  Here's a complete example of a cross-chain swap:
403
626
 
404
627
  ```typescript
405
- import { SFA, OpenAPI, tokens, EVMWallet, Service, TransactionStatus } from 'stableflow-ai-sdk';
628
+ import { SFA, OpenAPI, tokens, EVMWallet, Service, TransactionStatus, setRpcUrls } from 'stableflow-ai-sdk';
406
629
  import { ethers } from 'ethers';
407
630
 
408
631
  // 1. Initialize SDK
409
632
  OpenAPI.BASE = 'https://api.stableflow.ai';
410
633
  OpenAPI.TOKEN = 'your-jwt-token';
411
634
 
635
+ // (Optional) Configure custom RPC endpoints
636
+ setRpcUrls({
637
+ "eth": ["https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"],
638
+ "arb": ["https://arbitrum-one-rpc.publicnode.com"],
639
+ });
640
+
412
641
  // 2. Setup wallet
413
642
  const provider = new ethers.BrowserProvider(window.ethereum);
414
643
  await provider.send('eth_requestAccounts', []);
@@ -448,6 +677,7 @@ if (!selectedQuote || !selectedQuote.quote) {
448
677
  }
449
678
 
450
679
  console.log(`Selected route: ${selectedQuote.serviceType}`);
680
+ console.log(`Estimated time: ${selectedQuote.quote.estimateTime}s`);
451
681
 
452
682
  // 6. Handle approval if needed
453
683
  if (selectedQuote.quote.needApprove) {
@@ -496,6 +726,106 @@ const checkStatus = async () => {
496
726
  checkStatus();
497
727
  ```
498
728
 
729
+ ### Example 2: Solana to EVM Bridge (Solana → Ethereum)
730
+
731
+ Bridge USDT from Solana to Ethereum using USDT0:
732
+
733
+ ```typescript
734
+ import { SFA, OpenAPI, tokens, SolanaWallet, Service, TransactionStatus, setRpcUrls } from 'stableflow-ai-sdk';
735
+ import { Connection, PublicKey } from '@solana/web3.js';
736
+
737
+ // 1. Initialize SDK
738
+ OpenAPI.BASE = 'https://api.stableflow.ai';
739
+ OpenAPI.TOKEN = 'your-jwt-token';
740
+
741
+ // (Optional) Configure custom RPC endpoints
742
+ setRpcUrls({
743
+ "sol": ["https://api.mainnet-beta.solana.com"],
744
+ "eth": ["https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"],
745
+ });
746
+
747
+ // 2. Setup Solana wallet
748
+ // Note: In a real application, get these from your wallet adapter
749
+ // Example with @solana/wallet-adapter-react:
750
+ // const { publicKey, signTransaction } = useWallet();
751
+ // const wallet = new SolanaWallet({
752
+ // publicKey: publicKey,
753
+ // signer: { signTransaction }
754
+ // });
755
+
756
+ const connection = new Connection('https://api.mainnet-beta.solana.com');
757
+ const publicKey = new PublicKey('YOUR_SOLANA_ADDRESS');
758
+ const wallet = new SolanaWallet({
759
+ publicKey: publicKey,
760
+ signer: {
761
+ signTransaction: async (tx) => {
762
+ // Sign transaction using your Solana wallet adapter
763
+ // Example with Phantom:
764
+ // const provider = window.solana;
765
+ // return await provider.signTransaction(tx);
766
+ throw new Error('Implement wallet signing');
767
+ }
768
+ }
769
+ });
770
+
771
+ // 3. Select tokens
772
+ const fromToken = tokens.find(t =>
773
+ t.chainName === 'Solana' && t.symbol === 'USDT'
774
+ );
775
+ const toToken = tokens.find(t =>
776
+ t.chainName === 'Ethereum' && t.symbol === 'USDT'
777
+ );
778
+
779
+ if (!fromToken || !toToken) {
780
+ throw new Error('Token pair not supported');
781
+ }
782
+
783
+ // 4. Get quotes (USDT0 will automatically use multi-hop routing if needed)
784
+ const quotes = await SFA.getAllQuote({
785
+ dry: false,
786
+ prices: {},
787
+ fromToken,
788
+ toToken,
789
+ wallet,
790
+ recipient: '0x...', // Ethereum recipient address
791
+ refundTo: publicKey.toString(), // Solana refund address
792
+ amountWei: '1000000', // 1 USDT (6 decimals)
793
+ slippageTolerance: 0.5,
794
+ });
795
+
796
+ // 5. Find USDT0 quote
797
+ const usdt0Quote = quotes.find(q => q.serviceType === Service.Usdt0 && q.quote && !q.error);
798
+ if (usdt0Quote && usdt0Quote.quote) {
799
+ console.log(`USDT0 route available`);
800
+ console.log(`Estimated time: ${usdt0Quote.quote.estimateTime}s`);
801
+ console.log(`Total fees: $${usdt0Quote.quote.totalFeesUsd}`);
802
+
803
+ // 6. Send transaction
804
+ const txHash = await SFA.send(Service.Usdt0, {
805
+ wallet,
806
+ quote: usdt0Quote.quote,
807
+ });
808
+
809
+ console.log('Transaction submitted:', txHash);
810
+
811
+ // 7. Poll for status
812
+ const checkStatus = async () => {
813
+ const status = await SFA.getStatus(Service.Usdt0, { hash: txHash });
814
+ console.log('Current status:', status.status);
815
+
816
+ if (status.status === TransactionStatus.Success) {
817
+ console.log('Bridge completed! Destination tx:', status.toChainTxHash);
818
+ } else if (status.status === TransactionStatus.Failed) {
819
+ console.log('Bridge failed or refunded');
820
+ } else {
821
+ setTimeout(checkStatus, 5000);
822
+ }
823
+ };
824
+
825
+ checkStatus();
826
+ }
827
+ ```
828
+
499
829
  ## Error Handling
500
830
 
501
831
  The SDK throws typed errors that you can catch and handle:
@@ -543,6 +873,137 @@ The SDK provides full TypeScript type definitions:
543
873
  - `WalletConfig` - Wallet interface
544
874
  - `TransactionStatus` - Transaction status enum
545
875
 
876
+ ## Custom RPC Configuration
877
+
878
+ The SDK allows you to configure custom RPC endpoints for different blockchains. This is useful when you want to use your own RPC providers, private endpoints, or RPC services with API keys.
879
+
880
+ ### Setting Custom RPC URLs
881
+
882
+ You can set custom RPC URLs using the `setRpcUrls` function. The function accepts a record where keys are blockchain identifiers and values are arrays of RPC URLs.
883
+
884
+ **Supported Blockchain Identifiers:**
885
+ - `"eth"` - Ethereum
886
+ - `"arb"` - Arbitrum
887
+ - `"bsc"` - BNB Smart Chain
888
+ - `"avax"` - Avalanche
889
+ - `"base"` - Base
890
+ - `"pol"` - Polygon
891
+ - `"gnosis"` - Gnosis Chain
892
+ - `"op"` - Optimism
893
+ - `"bera"` - Berachain
894
+ - `"tron"` - Tron
895
+ - `"aptos"` - Aptos
896
+ - `"sol"` - Solana
897
+ - `"near"` - NEAR Protocol
898
+ - `"xlayer"` - X Layer
899
+
900
+ **Basic Usage:**
901
+
902
+ ```typescript
903
+ import { setRpcUrls } from 'stableflow-ai-sdk';
904
+
905
+ // Set custom RPC URLs for specific blockchains
906
+ setRpcUrls({
907
+ "eth": ["https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"],
908
+ "arb": ["https://arbitrum-one-rpc.publicnode.com"],
909
+ "sol": ["https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY"],
910
+ "near": ["https://rpc.mainnet.near.org"],
911
+ });
912
+ ```
913
+
914
+ **Multiple RPC URLs (Fallback Support):**
915
+
916
+ You can provide multiple RPC URLs for the same blockchain. The SDK will use them in order, with the first URL being the primary endpoint:
917
+
918
+ ```typescript
919
+ setRpcUrls({
920
+ "eth": [
921
+ "https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY",
922
+ "https://eth.merkle.io",
923
+ "https://cloudflare-eth.com"
924
+ ],
925
+ "arb": [
926
+ "https://arbitrum-one-rpc.publicnode.com",
927
+ "https://arb1.arbitrum.io/rpc"
928
+ ],
929
+ });
930
+ ```
931
+
932
+ **How It Works:**
933
+
934
+ - Custom RPC URLs are prepended to the default RPC URLs for each blockchain
935
+ - If a custom URL already exists in the default list, it won't be duplicated
936
+ - The SDK will prioritize custom URLs over default ones
937
+ - Multiple URLs can be provided for redundancy and fallback support
938
+
939
+ **Getting Current RPC URLs:**
940
+
941
+ You can access the current RPC configuration using `NetworkRpcUrlsMap`:
942
+
943
+ ```typescript
944
+ import { NetworkRpcUrlsMap, getRpcUrls } from 'stableflow-ai-sdk';
945
+
946
+ // Get all RPC URLs for a specific blockchain
947
+ const ethRpcUrls = getRpcUrls("eth");
948
+ console.log(ethRpcUrls); // ["https://custom-rpc.com", "https://eth.merkle.io", ...]
949
+
950
+ // Access the full RPC URLs map
951
+ console.log(NetworkRpcUrlsMap);
952
+ ```
953
+
954
+ **Complete Example:**
955
+
956
+ ```typescript
957
+ import { OpenAPI, SFA, tokens, EVMWallet, setRpcUrls } from 'stableflow-ai-sdk';
958
+ import { ethers } from 'ethers';
959
+
960
+ // Initialize the API client
961
+ OpenAPI.BASE = 'https://api.stableflow.ai';
962
+ OpenAPI.TOKEN = "your-JSON-Web-Token";
963
+
964
+ // Configure custom RPC endpoints
965
+ setRpcUrls({
966
+ "eth": ["https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY"],
967
+ "arb": ["https://arbitrum-one-rpc.publicnode.com"],
968
+ "sol": ["https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY"],
969
+ });
970
+
971
+ // Get wallet instance (will use custom RPC if configured)
972
+ const provider = new ethers.BrowserProvider(window.ethereum);
973
+ const signer = await provider.getSigner();
974
+ const wallet = new EVMWallet(provider, signer);
975
+
976
+ // Continue with your swap flow...
977
+ const fromToken = tokens.find(t => t.chainName === 'Ethereum' && t.symbol === 'USDT');
978
+ const toToken = tokens.find(t => t.chainName === 'Arbitrum' && t.symbol === 'USDT');
979
+
980
+ const quotes = await SFA.getAllQuote({
981
+ dry: false,
982
+ minInputAmount: "0.1",
983
+ prices: {},
984
+ fromToken: fromToken!,
985
+ toToken: toToken!,
986
+ wallet: wallet,
987
+ recipient: '0x...',
988
+ refundTo: '0x...',
989
+ amountWei: ethers.parseUnits('100', fromToken!.decimals).toString(),
990
+ slippageTolerance: 0.5,
991
+ });
992
+ ```
993
+
994
+ **Best Practices:**
995
+
996
+ 1. **Set RPC URLs Early**: Configure custom RPC URLs before initializing wallets or making API calls
997
+ 2. **Use Multiple URLs**: Provide fallback RPC URLs for better reliability
998
+ 3. **API Key Security**: Never commit API keys to version control. Use environment variables:
999
+ ```typescript
1000
+ setRpcUrls({
1001
+ "eth": [process.env.ETH_RPC_URL || "https://eth.merkle.io"],
1002
+ "sol": [process.env.SOL_RPC_URL || "https://solana-rpc.publicnode.com"],
1003
+ });
1004
+ ```
1005
+ 4. **Test Your RPCs**: Ensure your custom RPC endpoints are working correctly before deploying
1006
+
546
1007
  ## Examples
547
1008
 
548
1009
  ### 🌐 Web Application Demo 2.0
@@ -618,6 +1079,12 @@ For issues or support:
618
1079
  - Support for multiple bridge services (OneClick, CCTP, USDT0)
619
1080
  - Wallet integration for multiple chains
620
1081
  - Pre-configured token information
1082
+ - **USDT0 Improvements**:
1083
+ - Support for bridging from Solana as source chain
1084
+ - Multi-hop routing support for cross-chain transfers
1085
+ - Improved fee estimation accuracy
1086
+ - Dynamic time estimation based on chain block times
1087
+ - Fixed multi-hop composer issues
621
1088
 
622
1089
  ### v1.0.0
623
1090
  - Initial release