stableflow-ai-sdk 2.0.1 → 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,6 +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%
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
+ },
54
71
  });
55
72
 
56
73
  // Select the best quote and send transaction
@@ -107,6 +124,14 @@ const quotes = await SFA.getAllQuote({
107
124
  refundTo: string, // Refund address on source chain
108
125
  amountWei: string, // Amount in smallest units (wei/satoshi/etc.)
109
126
  slippageTolerance: number, // Slippage tolerance percentage (e.g., 0.5 for 0.5%)
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
+ };
110
135
  });
111
136
  ```
112
137
 
@@ -290,11 +315,12 @@ const finalStatus = await pollTransactionStatus(Service.OneClick, {
290
315
 
291
316
  ## Supported Bridge Services
292
317
 
293
- The SDK supports three bridge services:
318
+ The SDK supports three bridge services for general cross-chain swaps, plus a dedicated Hyperliquid deposit flow:
294
319
 
295
320
  - **OneClick** (`Service.OneClick`) - Native StableFlow bridge service
296
321
  - **CCTP** (`Service.CCTP`) - Circle's Cross-Chain Transfer Protocol
297
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.
298
324
 
299
325
  Each service has different characteristics:
300
326
  - Different fee structures
@@ -302,14 +328,113 @@ Each service has different characteristics:
302
328
  - Different processing times
303
329
  - Different minimum/maximum amounts
304
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
+
305
341
  Use `getAllQuote` to compare all available routes and select the best one for your use case.
306
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
+
307
430
  ## Wallet Integration
308
431
 
309
432
  The SDK supports multiple wallet types:
310
433
 
311
434
  ### EVM Wallets (Ethereum, Arbitrum, Polygon, etc.)
312
435
 
436
+ **Using ethers.js with BrowserProvider:**
437
+
313
438
  ```typescript
314
439
  import { EVMWallet } from 'stableflow-ai-sdk';
315
440
  import { ethers } from 'ethers';
@@ -319,40 +444,145 @@ const signer = await provider.getSigner();
319
444
  const wallet = new EVMWallet(provider, signer);
320
445
  ```
321
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
+
322
466
  ### Solana Wallets
323
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
+
324
485
  ```typescript
325
486
  import { SolanaWallet } from 'stableflow-ai-sdk';
326
487
  import { Connection, PublicKey } from '@solana/web3.js';
327
488
 
328
489
  const connection = new Connection('https://api.mainnet-beta.solana.com');
329
- 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
+ });
330
504
  ```
331
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
+
332
508
  ### Near Wallets
333
509
 
334
510
  ```typescript
335
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
+ });
336
521
 
337
- const wallet = new NearWallet(connection, accountId, keyPair);
522
+ const wallet = new NearWallet(selector);
338
523
  ```
339
524
 
525
+ **Note**: NearWallet requires a wallet selector instance from `@near-wallet-selector/core`. The selector handles wallet connection and transaction signing.
526
+
340
527
  ### Tron Wallets
341
528
 
342
529
  ```typescript
343
530
  import { TronWallet } from 'stableflow-ai-sdk';
344
531
 
345
- 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
+ });
346
542
  ```
347
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
+ }
561
+ ```
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
+
348
569
  ### Aptos Wallets
349
570
 
350
571
  ```typescript
351
572
  import { AptosWallet } from 'stableflow-ai-sdk';
573
+ import { useWallet } from '@aptos-labs/wallet-adapter-react';
352
574
 
353
- const wallet = new AptosWallet(provider, signer);
575
+ // Using Aptos wallet adapter
576
+ const { account, signAndSubmitTransaction } = useWallet();
577
+
578
+ const wallet = new AptosWallet({
579
+ account: account,
580
+ signAndSubmitTransaction: signAndSubmitTransaction,
581
+ });
354
582
  ```
355
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
+
356
586
  ## Token Configuration
357
587
 
358
588
  The SDK provides pre-configured token information:
@@ -386,20 +616,28 @@ Each token configuration includes:
386
616
  - `contractAddress` - Token contract address
387
617
  - `assetId` - StableFlow asset identifier
388
618
  - `services` - Array of supported bridge services
389
- - `rpcUrl` - RPC endpoint URL
619
+ - `rpcUrls` - RPC endpoint URLs
390
620
 
391
621
  ## Complete Example
392
622
 
623
+ ### Example 1: EVM to EVM Bridge (Ethereum → Arbitrum)
624
+
393
625
  Here's a complete example of a cross-chain swap:
394
626
 
395
627
  ```typescript
396
- import { SFA, OpenAPI, tokens, EVMWallet, Service, TransactionStatus } from 'stableflow-ai-sdk';
628
+ import { SFA, OpenAPI, tokens, EVMWallet, Service, TransactionStatus, setRpcUrls } from 'stableflow-ai-sdk';
397
629
  import { ethers } from 'ethers';
398
630
 
399
631
  // 1. Initialize SDK
400
632
  OpenAPI.BASE = 'https://api.stableflow.ai';
401
633
  OpenAPI.TOKEN = 'your-jwt-token';
402
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
+
403
641
  // 2. Setup wallet
404
642
  const provider = new ethers.BrowserProvider(window.ethereum);
405
643
  await provider.send('eth_requestAccounts', []);
@@ -439,6 +677,7 @@ if (!selectedQuote || !selectedQuote.quote) {
439
677
  }
440
678
 
441
679
  console.log(`Selected route: ${selectedQuote.serviceType}`);
680
+ console.log(`Estimated time: ${selectedQuote.quote.estimateTime}s`);
442
681
 
443
682
  // 6. Handle approval if needed
444
683
  if (selectedQuote.quote.needApprove) {
@@ -487,6 +726,106 @@ const checkStatus = async () => {
487
726
  checkStatus();
488
727
  ```
489
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
+
490
829
  ## Error Handling
491
830
 
492
831
  The SDK throws typed errors that you can catch and handle:
@@ -534,6 +873,137 @@ The SDK provides full TypeScript type definitions:
534
873
  - `WalletConfig` - Wallet interface
535
874
  - `TransactionStatus` - Transaction status enum
536
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
+
537
1007
  ## Examples
538
1008
 
539
1009
  ### 🌐 Web Application Demo 2.0
@@ -609,6 +1079,12 @@ For issues or support:
609
1079
  - Support for multiple bridge services (OneClick, CCTP, USDT0)
610
1080
  - Wallet integration for multiple chains
611
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
612
1088
 
613
1089
  ### v1.0.0
614
1090
  - Initial release