@silentswap/sdk 0.1.63 → 0.1.65
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/dist/assets.d.ts +1 -1
- package/dist/assets.js +20 -5
- package/dist/bridge.js +113 -42
- package/dist/chain.js +11 -12
- package/dist/index.d.ts +29 -20
- package/dist/index.js +29 -23
- package/dist/order.d.ts +5 -0
- package/dist/order.js +14 -0
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.js +2 -2
- package/package.json +2 -1
package/dist/assets.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface AssetsData {
|
|
|
27
27
|
chains: Record<Caip2, ChainInfo>;
|
|
28
28
|
assets: Record<Caip19, AssetInfo>;
|
|
29
29
|
}
|
|
30
|
-
export declare function loadAssetsData(): AssetsData
|
|
30
|
+
export declare function loadAssetsData(): Promise<AssetsData>;
|
|
31
31
|
export declare function getAllAssets(): Record<Caip19, AssetInfo>;
|
|
32
32
|
export declare function getAllChains(): Record<Caip2, ChainInfo>;
|
|
33
33
|
export declare function getAllAssetsArray(): AssetInfo[];
|
package/dist/assets.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
// Lazy-loaded assets data — avoids loading the 96KB JSON at module import time.
|
|
2
|
+
// Dynamic import works with Vite/webpack code-splitting; bundlers treat .json imports as modules.
|
|
3
|
+
let _filteredDataPromise = null;
|
|
4
|
+
async function getFilteredDataAsync() {
|
|
5
|
+
if (!_filteredDataPromise) {
|
|
6
|
+
_filteredDataPromise = import('./data/filtered.json').then((module) => (module.default ?? module));
|
|
7
|
+
}
|
|
8
|
+
return _filteredDataPromise;
|
|
9
|
+
}
|
|
10
|
+
// Synchronous accessor — returns cached data after loadAssetsData() resolves.
|
|
11
|
+
// Throws if data hasn't been loaded yet; callers should await loadAssetsData() first.
|
|
12
|
+
let _filteredData = null;
|
|
2
13
|
function getFilteredData() {
|
|
3
|
-
|
|
14
|
+
if (!_filteredData) {
|
|
15
|
+
throw new Error('Assets data not loaded. Call loadAssetsData() first.');
|
|
16
|
+
}
|
|
17
|
+
return _filteredData;
|
|
4
18
|
}
|
|
5
|
-
// Load assets data from filtered.json
|
|
6
|
-
export function loadAssetsData() {
|
|
7
|
-
|
|
19
|
+
// Load assets data from filtered.json (async — call once at app startup)
|
|
20
|
+
export async function loadAssetsData() {
|
|
21
|
+
_filteredData = await getFilteredDataAsync();
|
|
22
|
+
return _filteredData;
|
|
8
23
|
}
|
|
9
24
|
// Get all assets from the filtered data
|
|
10
25
|
export function getAllAssets() {
|
package/dist/bridge.js
CHANGED
|
@@ -2,6 +2,12 @@ import { encodeFunctionData, erc20Abi } from 'viem';
|
|
|
2
2
|
import BigNumber from 'bignumber.js';
|
|
3
3
|
import { NI_CHAIN_ID_AVALANCHE, S0X_ADDR_USDC_AVALANCHE, S0X_ADDR_EVM_ZERO, UINT256_MAX, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_SUI, N_RELAY_CHAIN_ID_TRON, S0X_ADDR_TRON_NATIVE, SB58_ADDR_SOL_PROGRAM_SYSTEM, } from './constants.js';
|
|
4
4
|
import { createPhonyDepositCalldata } from './wallet.js';
|
|
5
|
+
// TTL cache for solveOptimalUsdcAmount — avoids re-fetching identical quotes
|
|
6
|
+
const QUOTE_CACHE_TTL = 30_000; // 30 seconds
|
|
7
|
+
const quoteCache = new Map();
|
|
8
|
+
function getQuoteCacheKey(srcChainId, srcToken, srcAmount, forceProvider) {
|
|
9
|
+
return `${srcChainId}:${srcToken}:${srcAmount}:${forceProvider ?? 'any'}`;
|
|
10
|
+
}
|
|
5
11
|
/**
|
|
6
12
|
* Map relay.link chain IDs to deBridge chain IDs
|
|
7
13
|
* Different bridge providers use different chain ID schemes
|
|
@@ -349,7 +355,6 @@ export async function fetchDebridgeOrder(params, signal) {
|
|
|
349
355
|
* Note: DLN does not support same-chain swaps via create-tx endpoint
|
|
350
356
|
*/
|
|
351
357
|
async function fetchDebridgeSingleChainOrder(params, signal) {
|
|
352
|
-
console.log('fetchDebridgeSingleChainOrder');
|
|
353
358
|
// Build query parameters for single-chain swap endpoint
|
|
354
359
|
const queryParams = new URLSearchParams({
|
|
355
360
|
chainId: params.srcChainId.toString(),
|
|
@@ -359,6 +364,16 @@ async function fetchDebridgeSingleChainOrder(params, signal) {
|
|
|
359
364
|
tokenOutRecipient: params.dstChainTokenOutRecipient || params.account || '',
|
|
360
365
|
senderAddress: params.senderAddress || params.account || '',
|
|
361
366
|
});
|
|
367
|
+
// EXACT_OUTPUT support: when caller passes a concrete dstChainTokenOutAmount
|
|
368
|
+
// (and srcChainTokenInAmount === 'auto'), forward it as `tokenOutAmount`.
|
|
369
|
+
// Without this the convergence loop in solveDebridgeSingleChainUsdcAmount
|
|
370
|
+
// sends `tokenInAmount=auto` with no target → deBridge returns
|
|
371
|
+
// INTERNAL_SERVER_ERROR on every iteration after the first, so the loop
|
|
372
|
+
// never finds the optimal price and surfaces as "Failed to find optimal
|
|
373
|
+
// bridge price".
|
|
374
|
+
if (params.dstChainTokenOutAmount && params.dstChainTokenOutAmount !== 'auto') {
|
|
375
|
+
queryParams.set('tokenOutAmount', params.dstChainTokenOutAmount);
|
|
376
|
+
}
|
|
362
377
|
// Add optional parameters if provided
|
|
363
378
|
if (params.prependOperatingExpenses !== undefined) {
|
|
364
379
|
queryParams.set('prependOperatingExpenses', String(params.prependOperatingExpenses));
|
|
@@ -520,8 +535,11 @@ async function solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress
|
|
|
520
535
|
if (impactPercent > maxImpactPercent) {
|
|
521
536
|
throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
|
|
522
537
|
}
|
|
523
|
-
// Amount in is within our budget
|
|
524
|
-
|
|
538
|
+
// Amount in is within our budget — accept up to 0.5% over to absorb
|
|
539
|
+
// rounding noise from the bridge's internal pricing (otherwise the loop
|
|
540
|
+
// bounces on quotes that are e.g. 0.1% over, until convergence breaks).
|
|
541
|
+
const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
|
|
542
|
+
if (amountIn <= budgetWithTolerance) {
|
|
525
543
|
console.log('[SilentSwap:SolveRelay] Found optimal amount', {
|
|
526
544
|
usdcOut: amountOut.toString(),
|
|
527
545
|
amountIn: amountIn.toString(),
|
|
@@ -536,7 +554,13 @@ async function solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress
|
|
|
536
554
|
.minus(srcAmount)
|
|
537
555
|
.times(yg_utoken_price)
|
|
538
556
|
.div(yg_uusdc_price);
|
|
539
|
-
|
|
557
|
+
// Anchor the next target on the *current target* (what we asked for),
|
|
558
|
+
// not on `currencyOut.amount` (what the bridge's quote estimates we'd
|
|
559
|
+
// get). For some endpoints — notably deBridge single-chain —
|
|
560
|
+
// `amount > requested target` because of a built-in slippage buffer,
|
|
561
|
+
// and using it as the base produces new_target > previous_target on
|
|
562
|
+
// tight iterations, breaking convergence.
|
|
563
|
+
const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
|
|
540
564
|
.minus(yg_uusdc_over)
|
|
541
565
|
.toFixed(0);
|
|
542
566
|
console.log(`[SilentSwap:SolveRelay] Reducing target`, {
|
|
@@ -622,8 +646,10 @@ async function solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddr
|
|
|
622
646
|
throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
|
|
623
647
|
}
|
|
624
648
|
const amountIn = BigInt(quote.estimation.srcChainTokenIn.amount);
|
|
625
|
-
// Amount in is within our budget
|
|
626
|
-
|
|
649
|
+
// Amount in is within our budget — accept up to 0.5% over to absorb
|
|
650
|
+
// rounding noise from deBridge's internal pricing.
|
|
651
|
+
const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
|
|
652
|
+
if (amountIn <= budgetWithTolerance) {
|
|
627
653
|
// quote.tx can be undefined when DeBridge returns an estimation-only response
|
|
628
654
|
// (e.g. unroutable edge cases, takers without capacity for the route, or non-EVM
|
|
629
655
|
// sources like Solana/Tron where no ERC-20 allowance is needed at all).
|
|
@@ -641,7 +667,14 @@ async function solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddr
|
|
|
641
667
|
.minus(srcAmount)
|
|
642
668
|
.times(yg_utoken_price)
|
|
643
669
|
.div(yg_uusdc_price);
|
|
644
|
-
|
|
670
|
+
// Anchor on the *requested target* (targetUsdcOut), not the bridge's
|
|
671
|
+
// estimated `amount`. deBridge's single-chain endpoint returns
|
|
672
|
+
// `amount > minAmount` (built-in slippage buffer), which makes the
|
|
673
|
+
// current iteration's `dstChainTokenOut.amount` larger than the
|
|
674
|
+
// requested target. Subtracting a small overshoot from that larger
|
|
675
|
+
// value yields a new target that's still bigger than the previous
|
|
676
|
+
// target, and the convergence guard fires.
|
|
677
|
+
const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
|
|
645
678
|
.minus(yg_uusdc_over)
|
|
646
679
|
.toFixed(0);
|
|
647
680
|
if (BigInt(sg_uusdc_target) >= targetUsdcOut) {
|
|
@@ -714,8 +747,10 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
|
|
|
714
747
|
throw new Error(`Price impact too high: ${impactPercent.toFixed(2)}%`);
|
|
715
748
|
}
|
|
716
749
|
const amountIn = BigInt(quote.estimation.srcChainTokenIn.amount);
|
|
717
|
-
// Amount in is within our budget
|
|
718
|
-
|
|
750
|
+
// Amount in is within our budget — accept up to 0.5% over to absorb
|
|
751
|
+
// rounding noise from deBridge's internal pricing.
|
|
752
|
+
const budgetWithTolerance = BigInt(srcAmount) * 1005n / 1000n;
|
|
753
|
+
if (amountIn <= budgetWithTolerance) {
|
|
719
754
|
// quote.tx can be undefined when DeBridge returns an estimation-only response
|
|
720
755
|
// (e.g. unroutable edge cases, takers without capacity for the route, or non-EVM
|
|
721
756
|
// sources like Solana/Tron where no ERC-20 allowance is needed at all).
|
|
@@ -733,7 +768,14 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
|
|
|
733
768
|
.minus(srcAmount)
|
|
734
769
|
.times(yg_utoken_price)
|
|
735
770
|
.div(yg_uusdc_price);
|
|
736
|
-
|
|
771
|
+
// Anchor on the *requested target* (targetUsdcOut), not the bridge's
|
|
772
|
+
// estimated `amount`. deBridge's single-chain endpoint returns
|
|
773
|
+
// `amount > minAmount` (built-in slippage buffer), which makes the
|
|
774
|
+
// current iteration's `dstChainTokenOut.amount` larger than the
|
|
775
|
+
// requested target. Subtracting a small overshoot from that larger
|
|
776
|
+
// value yields a new target that's still bigger than the previous
|
|
777
|
+
// target, and the convergence guard fires.
|
|
778
|
+
const sg_uusdc_target = BigNumber(targetUsdcOut.toString())
|
|
737
779
|
.minus(yg_uusdc_over)
|
|
738
780
|
.toFixed(0);
|
|
739
781
|
if (BigInt(sg_uusdc_target) >= targetUsdcOut) {
|
|
@@ -758,6 +800,12 @@ async function solveDebridgeSingleChainUsdcAmount(chainId, srcToken, srcAmount,
|
|
|
758
800
|
*/
|
|
759
801
|
export async function solveOptimalUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, depositCalldata, maxImpactPercent, depositorAddress, evmSignerAddress, // Optional EVM address for deposit calldata (required for non-EVM swaps: Solana, Bitcoin)
|
|
760
802
|
forceProvider) {
|
|
803
|
+
// Check cache first
|
|
804
|
+
const cacheKey = getQuoteCacheKey(srcChainId, srcToken, srcAmount, forceProvider);
|
|
805
|
+
const cached = quoteCache.get(cacheKey);
|
|
806
|
+
if (cached && Date.now() - cached.timestamp < QUOTE_CACHE_TTL) {
|
|
807
|
+
return cached.result;
|
|
808
|
+
}
|
|
761
809
|
// Check if this is a non-EVM chain (Solana, Bitcoin, etc.)
|
|
762
810
|
const isNonEvmChain = isNonEvmRelayChainId(srcChainId);
|
|
763
811
|
// For non-EVM chains (Solana, Bitcoin), we need an EVM address for deposit calldata
|
|
@@ -775,15 +823,33 @@ forceProvider) {
|
|
|
775
823
|
const recipientAddress = isNonEvmChain && evmSignerAddress ? evmSignerAddress : userAddress;
|
|
776
824
|
const useRelay = forceProvider !== 'debridge';
|
|
777
825
|
const useDebridge = forceProvider !== 'relay';
|
|
778
|
-
//
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
:
|
|
786
|
-
|
|
826
|
+
// Build promise array only for enabled providers to avoid creating unnecessary promises
|
|
827
|
+
const promises = [];
|
|
828
|
+
if (useRelay) {
|
|
829
|
+
promises.push(solveRelayUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress, recipientAddress)
|
|
830
|
+
.then(([usdcAmountOut, actualAmountIn, allowanceTarget]) => ({
|
|
831
|
+
usdcAmountOut,
|
|
832
|
+
actualAmountIn,
|
|
833
|
+
provider: 'relay',
|
|
834
|
+
allowanceTarget,
|
|
835
|
+
})));
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
promises.push(Promise.resolve(null));
|
|
839
|
+
}
|
|
840
|
+
if (useDebridge) {
|
|
841
|
+
promises.push(solveDebridgeUsdcAmount(srcChainId, srcToken, srcAmount, userAddress, calldata, maxImpactPercent, depositorAddress)
|
|
842
|
+
.then(([usdcAmountOut, actualAmountIn, allowanceTarget]) => ({
|
|
843
|
+
usdcAmountOut,
|
|
844
|
+
actualAmountIn,
|
|
845
|
+
provider: 'debridge',
|
|
846
|
+
allowanceTarget,
|
|
847
|
+
})));
|
|
848
|
+
}
|
|
849
|
+
else {
|
|
850
|
+
promises.push(Promise.resolve(null));
|
|
851
|
+
}
|
|
852
|
+
const [relayResult, debridgeResult] = await Promise.allSettled(promises);
|
|
787
853
|
// Extract results
|
|
788
854
|
const relayData = relayResult.status === 'fulfilled' ? relayResult.value : null;
|
|
789
855
|
const debridgeData = debridgeResult.status === 'fulfilled' ? debridgeResult.value : null;
|
|
@@ -807,48 +873,53 @@ forceProvider) {
|
|
|
807
873
|
}
|
|
808
874
|
throw new AggregateError(errors, 'All bridge providers failed');
|
|
809
875
|
}
|
|
876
|
+
// Helper to cache and return result
|
|
877
|
+
const cacheAndReturn = (result) => {
|
|
878
|
+
quoteCache.set(cacheKey, { result, timestamp: Date.now() });
|
|
879
|
+
return result;
|
|
880
|
+
};
|
|
810
881
|
// Only one succeeded
|
|
811
882
|
if (!relayData) {
|
|
812
883
|
console.info('Using deBridge (relay failed)');
|
|
813
|
-
return {
|
|
814
|
-
usdcAmountOut: debridgeData
|
|
815
|
-
actualAmountIn: debridgeData
|
|
884
|
+
return cacheAndReturn({
|
|
885
|
+
usdcAmountOut: debridgeData.usdcAmountOut,
|
|
886
|
+
actualAmountIn: debridgeData.actualAmountIn,
|
|
816
887
|
provider: 'debridge',
|
|
817
|
-
allowanceTarget: debridgeData
|
|
818
|
-
};
|
|
888
|
+
allowanceTarget: debridgeData.allowanceTarget,
|
|
889
|
+
});
|
|
819
890
|
}
|
|
820
891
|
if (!debridgeData) {
|
|
821
892
|
console.info('Using relay.link (deBridge failed)');
|
|
822
|
-
return {
|
|
823
|
-
usdcAmountOut: relayData
|
|
824
|
-
actualAmountIn: relayData
|
|
893
|
+
return cacheAndReturn({
|
|
894
|
+
usdcAmountOut: relayData.usdcAmountOut,
|
|
895
|
+
actualAmountIn: relayData.actualAmountIn,
|
|
825
896
|
provider: 'relay',
|
|
826
|
-
allowanceTarget: relayData
|
|
827
|
-
};
|
|
897
|
+
allowanceTarget: relayData.allowanceTarget,
|
|
898
|
+
});
|
|
828
899
|
}
|
|
829
900
|
// Compare rates (USDC out / amount in)
|
|
830
901
|
// Use BigNumber for precision (matching Svelte implementation)
|
|
831
902
|
// Svelte: yx_rate_relay = BigNumber(xg_uusdc_out_relay).div(xg_amount_in_relay)
|
|
832
|
-
const relayRate = BigNumber(relayData
|
|
833
|
-
const debridgeRate = BigNumber(debridgeData
|
|
903
|
+
const relayRate = BigNumber(relayData.usdcAmountOut.toString()).div(relayData.actualAmountIn.toString());
|
|
904
|
+
const debridgeRate = BigNumber(debridgeData.usdcAmountOut.toString()).div(debridgeData.actualAmountIn.toString());
|
|
834
905
|
// Relay performs better (matches Svelte: yx_rate_relay.gte(yx_rate_debridge))
|
|
835
906
|
if (relayRate.gte(debridgeRate)) {
|
|
836
|
-
console.info(`Using relay.link: ${relayRate.toString()} >= ${debridgeRate.toString()}`, [relayData
|
|
837
|
-
return {
|
|
838
|
-
usdcAmountOut: relayData
|
|
839
|
-
actualAmountIn: relayData
|
|
907
|
+
console.info(`Using relay.link: ${relayRate.toString()} >= ${debridgeRate.toString()}`, [relayData.usdcAmountOut, relayData.actualAmountIn], [debridgeData.usdcAmountOut, debridgeData.actualAmountIn]);
|
|
908
|
+
return cacheAndReturn({
|
|
909
|
+
usdcAmountOut: relayData.usdcAmountOut,
|
|
910
|
+
actualAmountIn: relayData.actualAmountIn,
|
|
840
911
|
provider: 'relay',
|
|
841
912
|
allowanceTarget: '',
|
|
842
|
-
};
|
|
913
|
+
});
|
|
843
914
|
}
|
|
844
915
|
else {
|
|
845
916
|
// DeBridge performs better
|
|
846
|
-
console.info(`Using deBridge: ${debridgeRate.toString()} >= ${relayRate.toString()}`, [debridgeData
|
|
847
|
-
return {
|
|
848
|
-
usdcAmountOut: debridgeData
|
|
849
|
-
actualAmountIn: debridgeData
|
|
917
|
+
console.info(`Using deBridge: ${debridgeRate.toString()} >= ${relayRate.toString()}`, [debridgeData.usdcAmountOut, debridgeData.actualAmountIn], [relayData.usdcAmountOut, relayData.actualAmountIn]);
|
|
918
|
+
return cacheAndReturn({
|
|
919
|
+
usdcAmountOut: debridgeData.usdcAmountOut,
|
|
920
|
+
actualAmountIn: debridgeData.actualAmountIn,
|
|
850
921
|
provider: 'debridge',
|
|
851
|
-
allowanceTarget: debridgeData
|
|
852
|
-
};
|
|
922
|
+
allowanceTarget: debridgeData.allowanceTarget,
|
|
923
|
+
});
|
|
853
924
|
}
|
|
854
925
|
}
|
package/dist/chain.js
CHANGED
|
@@ -31,12 +31,10 @@ export async function ensureChain(chainId, walletClient, connector, options) {
|
|
|
31
31
|
}
|
|
32
32
|
console.log('[ensureChain] currentChainId:', currentChainId, 'targetChainId:', chainId, 'needsSwitch:', currentChainId !== chainId);
|
|
33
33
|
if (currentChainId !== chainId) {
|
|
34
|
-
let switchSucceeded = false;
|
|
35
34
|
try {
|
|
36
35
|
// Try to switch chain
|
|
37
36
|
console.log('[ensureChain] attempting switchChain ...', { hasSwitchChain: !!connector.switchChain });
|
|
38
37
|
await connector.switchChain?.({ chainId });
|
|
39
|
-
switchSucceeded = true;
|
|
40
38
|
console.log('[ensureChain] switchChain succeeded');
|
|
41
39
|
}
|
|
42
40
|
catch (switchError) {
|
|
@@ -49,16 +47,17 @@ export async function ensureChain(chainId, walletClient, connector, options) {
|
|
|
49
47
|
}
|
|
50
48
|
// Non-required: chain switch failed (e.g. Trust Wallet via WalletConnect
|
|
51
49
|
// doesn't support programmatic chain switching). Still recreate the
|
|
52
|
-
// walletClient from the provider so the WalletConnect transport
|
|
53
|
-
// — TrustWallet silently drops signTypedData when the client's
|
|
54
|
-
// doesn't match its active session chain.
|
|
50
|
+
// walletClient from the provider below so the WalletConnect transport
|
|
51
|
+
// is fresh — TrustWallet silently drops signTypedData when the client's
|
|
52
|
+
// chain scope doesn't match its active session chain.
|
|
55
53
|
}
|
|
56
|
-
// Always
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// by
|
|
60
|
-
//
|
|
61
|
-
|
|
54
|
+
// Always rebind the walletClient if its `chain` config doesn't match the target.
|
|
55
|
+
// viem's signTypedData / sendTransaction asserts that walletClient.chain.id matches
|
|
56
|
+
// the wallet's reported eth_chainId — if the wallet was already switched to `chainId`
|
|
57
|
+
// (e.g. by an earlier ensureChain call) but the closure's walletClient was created
|
|
58
|
+
// by wagmi with a different chain, signing throws "Provided chainId X must match
|
|
59
|
+
// active chainId Y". Recreating the client here keeps the two in sync.
|
|
60
|
+
console.log('[ensureChain] rebinding walletClient to chain', chainId, '(was', walletClient.chain?.id, ')');
|
|
62
61
|
const provider = await connector.getProvider();
|
|
63
62
|
const chain = getChainById(chainId);
|
|
64
63
|
if (!chain) {
|
|
@@ -78,7 +77,7 @@ export async function ensureChain(chainId, walletClient, connector, options) {
|
|
|
78
77
|
});
|
|
79
78
|
return newClient;
|
|
80
79
|
}
|
|
81
|
-
console.log('[ensureChain] already on correct chain, returning existing walletClient');
|
|
80
|
+
console.log('[ensureChain] already on correct chain with matching client, returning existing walletClient');
|
|
82
81
|
return walletClient;
|
|
83
82
|
}
|
|
84
83
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
export type { SilentSwapClientConfig, SilentSwapClient, } from './client.js';
|
|
2
|
-
export type
|
|
2
|
+
export type { NonceResponse, AuthRequest, AuthResponse, QuoteRequest, QuoteResponse, OrderRequest, DepositParams, OrderResponse, } from './types/api.js';
|
|
3
3
|
export type { Caip19, SignInMessage } from './types/core.js';
|
|
4
4
|
export type { EvmSigner } from './types/sdk.js';
|
|
5
|
-
export
|
|
6
|
-
export
|
|
5
|
+
export type { FacilitatorPublicKey, Eip712Document, Eip3009TypedData, AuthorizationInstruction, AuthorizationReply, FacilitatorInstruction, FacilitatorReply, OrderOutputArg, OrderMetadata, Quote, Order, } from './order.js';
|
|
6
|
+
export { DeliveryMethod, PrivacySetting, FacilitatorKeyType, PublicKeyArgGroups, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION, EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, quoteResponseToEip712Document, } from './order.js';
|
|
7
|
+
export type { Caip19Parts, ParsedCaip19, ParsedEvmCaip19, ParsedSolanaCaip19, ParsedTronCaip19, } from './caip19.js';
|
|
8
|
+
export { CAIP19_REGEX, EVM_CAIP19_REGEX, SOLANA_CAIP19_REGEX, TRON_CAIP19_NATIVE_REGEX, TRON_CAIP19_TOKEN_REGEX, Caip19Namespace, parseCaip19, parseEvmCaip19, parseSolanaCaip19, parseTronCaip19, getChainNamespace, getChainId, getEvmChainId, getAssetNamespace, getAssetReference, getEvmTokenAddress, getCaip2FromCaip19, isNativeToken, isEvmAsset, isSolanaAsset, isTronAsset, BIP122_BITCOIN_MAINNET_CHAIN_ID, isBitcoinAsset, isBitcoinMainnetAsset, isEvmNativeToken, isErc20Token, isSolanaNativeToken, isSplToken, caip19FromParts, caip19FungibleEvmToken, caip19NativeEvmToken, caip19SplToken, caip19NativeSolanaToken, } from './caip19.js';
|
|
7
9
|
export { createSilentSwapClient, } from './client.js';
|
|
8
|
-
export
|
|
9
|
-
export
|
|
10
|
+
export type { CalculationDirection, } from './constants.js';
|
|
11
|
+
export { EVM_PHONY_ADDRESS, EVM_NATIVE_ADDRESS, DEAD_ADDRESS, S0X_ADDR_EVM_ZERO, UINT256_MAX, MAINNET_GATEWAY_ADDRESS, MAINNET_GATEWAY_PUBLIC_KEY, ENVIRONMENT, ENVIRONMENT_CONFIGS, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, XT_TTL_SESSION_CACHE, X_MINIMUM_INPUT_USD, X_MAX_IMPACT_PERCENT, COIN_TYPES, SB58_CHAIN_ID_SOLANA_MAINNET, SB58_ADDR_SOL_PROGRAM_SYSTEM, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, SB58_ADDR_SOL_DEAD, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, S0X_ADDR_TRON_NATIVE, SB58_ADDR_TRON_DEAD, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SUI, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, S0X_ADDR_EVM_RELAY_LINK_DEAD, P_URL_API_RPC_SOLANA, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from './constants.js';
|
|
12
|
+
export { GATEWAY_ABI, } from './gateway-abi.js';
|
|
10
13
|
export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, type HdFacilitatorGroup, } from './hd-facilitator-group.js';
|
|
11
14
|
export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
|
|
12
15
|
export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
|
|
13
|
-
export
|
|
14
|
-
export
|
|
15
|
-
export
|
|
16
|
-
export
|
|
17
|
-
export
|
|
18
|
-
export
|
|
19
|
-
export
|
|
20
|
-
export
|
|
21
|
-
export
|
|
22
|
-
export
|
|
23
|
-
export
|
|
16
|
+
export type { BridgeProvider, BridgeQuote, SolanaInstruction, BridgeTransaction, BridgeStatus, BridgeQuoteParams, RelayQuoteParams, RelayQuoteResponse, DeBridgeOrderParams, DeBridgeOrderResponse, SolveUsdcResult, } from './bridge.js';
|
|
17
|
+
export { getRelayOriginAsset, executeRelayBridge, executeDebridgeBridge, getRelayStatus, getDebridgeStatus, fetchRelayQuote, fetchDebridgeOrder, solveOptimalUsdcAmount, } from './bridge.js';
|
|
18
|
+
export type { EstimateSample, Estimate, QuoteMetrics, BridgeQuoteResult, ForceBridgeProvider, } from './quote-utils.js';
|
|
19
|
+
export { calculateRelayMetrics, calculateDebridgeMetrics, selectBestQuote, interpolateSamples, getBridgeQuote, convertQuoteResultToQuote, } from './quote-utils.js';
|
|
20
|
+
export type { SolanaTransactionExecutor, BitcoinTransactionExecutor, TronTransactionExecutor, UniversalTransactionExecutor, } from './transaction-utils.js';
|
|
21
|
+
export { createTransactionExecutor, createChainSwitcher, executeBridgeTransaction, getBridgeStatus, } from './transaction-utils.js';
|
|
22
|
+
export { queryDepositCount, createPhonyDepositCalldata, } from './wallet.js';
|
|
23
|
+
export { STORAGE_KEY_AUTH_PREFIX, STORAGE_KEY_WALLET_PREFIX, getAuthStorageKey, getWalletStorageKey, loadCachedAuth, saveAuth, clearAuth, saveWalletData, loadWalletData, clearWalletData, } from './storage.js';
|
|
24
|
+
export { ensureChain, pingWalletConnectSession, clearStaleWalletConnectSessions, createPublicClientWithRpc, waitForTransactionConfirmation, executeTransaction, } from './chain.js';
|
|
25
|
+
export { SOLANA_CHAIN_ID, BITCOIN_CHAIN_ID, TRON_CHAIN_ID, A_VIEM_CHAINS, getChainById, } from './chains.js';
|
|
26
|
+
export { H_RPCS, } from './rpc.js';
|
|
27
|
+
export type { AssetInfo, ChainInfo, AssetsData, } from './assets.js';
|
|
28
|
+
export { loadAssetsData, getAllAssets, getAllChains, getAllAssetsArray, getCommonAssets, COMMON_ASSETS, CHAIN_NAMES, getAssetByCaip19, getChainByCaip2, getAssetsByChain, getChainName, searchAssets, } from './assets.js';
|
|
29
|
+
export { hexToBytes, bytesToBase58, hexToBase58, base93ToBytes, bytesToBase93, } from './encoding.js';
|
|
30
|
+
export type { GatewayOrderStatus, RefundEligibility, } from './refund.js';
|
|
31
|
+
export { DepositStatus, orderIdToBytes32, queryOrderStatus, checkRefundEligibility, executeRefund, checkRecoveryEligibility, } from './refund.js';
|
|
24
32
|
export { trackOrderViaWebSocket, getOrderTrackingWebSocketUrl, type TrackOrderOptions, type OrderStatusUpdate, } from './order-tracking.js';
|
|
25
33
|
export type { NaiveBase58, NaiveBase93, NaiveHexLower, NaiveHexUpper } from './belt-utils.js';
|
|
26
34
|
export { bytes_to_base58, base58_to_bytes, bytes_to_base93, base93_to_bytes, bytes_to_hex, hex_to_bytes } from './belt-utils.js';
|
|
27
|
-
export
|
|
28
|
-
export
|
|
29
|
-
export
|
|
30
|
-
export
|
|
35
|
+
export type { ContactSource, Contact, Caip10, } from './address.js';
|
|
36
|
+
export { isValidEvmAddress, isValidSolanaAddress, isValidBitcoinAddress, isValidTronAddress, validateAddress, normalizeAddress, isValidEnsName, formatAddress, formatAddressByType, getAvatarColor, getAvatarInitials, createCaip10, parseCaip10, getAddressFromCaip10, evmAddressToCaip10, solanaAddressToCaip10, bitcoinAddressToCaip10, addressToCaip10, isContactCompatibleWithAsset, filterContacts, } from './address.js';
|
|
37
|
+
export { parseCaip19Legacy, getChainNamespaceFromAsset, getChainIdFromAsset, getAssetNamespaceFromAsset, getAssetId, getCaip2, getTokenAddress, isBitcoin, isEvm, isSolana, isCosmos, isSui, isTron, isNativeTokenFromAsset, isEvmNative, isEvmErc20, isSolanaNative, isSolanaToken, isCosmosNative, isCosmosIbc, getTokenChainId, getTokenChainIdString, extractChainIdsFromAssets, extractChainIdFromAsset, getTokenChainInfo, getTokenChainName, switchChainNamespace, } from './asset-utils.js';
|
|
38
|
+
export { getSolanaRpcUrl, } from './solana-utils.js';
|
|
39
|
+
export { SilentSwapError, ApiError, NetworkError, AuthenticationError, QuoteError, OrderError, ValidationError, ConfigurationError, WalletError, TransactionError, createErrorFromResponse, } from './errors.js';
|
|
31
40
|
export { executeSolanaSwap, type SwapEnvironment, type OutputStage, type OrderStatus, type SwapStatusUpdate, type SwapResult, type EvmAccount, type SolanaAccount, type SwapAccounts, type SolanaSwapConfig, } from './swap-executor.js';
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,37 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export { DeliveryMethod, PrivacySetting, FacilitatorKeyType, PublicKeyArgGroups, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION, EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, quoteResponseToEip712Document, } from './order.js';
|
|
2
|
+
export { CAIP19_REGEX, EVM_CAIP19_REGEX, SOLANA_CAIP19_REGEX, TRON_CAIP19_NATIVE_REGEX, TRON_CAIP19_TOKEN_REGEX, Caip19Namespace, parseCaip19, parseEvmCaip19, parseSolanaCaip19, parseTronCaip19, getChainNamespace, getChainId, getEvmChainId, getAssetNamespace, getAssetReference, getEvmTokenAddress, getCaip2FromCaip19, isNativeToken, isEvmAsset, isSolanaAsset, isTronAsset, BIP122_BITCOIN_MAINNET_CHAIN_ID, isBitcoinAsset, isBitcoinMainnetAsset, isEvmNativeToken, isErc20Token, isSolanaNativeToken, isSplToken, caip19FromParts, caip19FungibleEvmToken, caip19NativeEvmToken, caip19SplToken, caip19NativeSolanaToken, } from './caip19.js';
|
|
3
3
|
export { createSilentSwapClient, } from './client.js';
|
|
4
|
-
export
|
|
5
|
-
|
|
4
|
+
export { EVM_PHONY_ADDRESS, EVM_NATIVE_ADDRESS, DEAD_ADDRESS, S0X_ADDR_EVM_ZERO, UINT256_MAX, MAINNET_GATEWAY_ADDRESS, MAINNET_GATEWAY_PUBLIC_KEY, ENVIRONMENT, ENVIRONMENT_CONFIGS, S0X_ADDR_USDC_AVALANCHE, S_CAIP19_USDC_AVALANCHE, NI_CHAIN_ID_AVALANCHE, XT_TTL_SESSION_CACHE, X_MINIMUM_INPUT_USD, X_MAX_IMPACT_PERCENT, COIN_TYPES, SB58_CHAIN_ID_SOLANA_MAINNET, SB58_ADDR_SOL_PROGRAM_SYSTEM, SB58_ADDR_SOL_RELAY_LINK_RECIPIENT, SB58_ADDR_SOL_DEAD, SBTC_ADDR_BITCOIN_NATIVE, SBTC_ADDR_BTC_RELAY_LINK_RECIPIENT, S0X_ADDR_TRON_NATIVE, SB58_ADDR_TRON_DEAD, N_RELAY_CHAIN_ID_SOLANA, N_RELAY_CHAIN_ID_BITCOIN, N_RELAY_CHAIN_ID_TRON, N_RELAY_CHAIN_ID_SUI, N_DEBRIDGE_CHAIN_ID_SOLANA, N_DEBRIDGE_CHAIN_ID_TRON, S0X_ADDR_EVM_RELAY_LINK_DEAD, P_URL_API_RPC_SOLANA, CALCULATION_DIRECTION_INPUT_TO_OUTPUT, CALCULATION_DIRECTION_OUTPUT_TO_INPUT, } from './constants.js';
|
|
5
|
+
// gateway-abi
|
|
6
|
+
export { GATEWAY_ABI, } from './gateway-abi.js';
|
|
6
7
|
export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, } from './hd-facilitator-group.js';
|
|
7
8
|
export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
|
|
8
9
|
export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
export
|
|
10
|
+
export { getRelayOriginAsset, executeRelayBridge, executeDebridgeBridge, getRelayStatus, getDebridgeStatus, fetchRelayQuote, fetchDebridgeOrder, solveOptimalUsdcAmount, } from './bridge.js';
|
|
11
|
+
export { calculateRelayMetrics, calculateDebridgeMetrics, selectBestQuote, interpolateSamples, getBridgeQuote, convertQuoteResultToQuote, } from './quote-utils.js';
|
|
12
|
+
export { createTransactionExecutor, createChainSwitcher, executeBridgeTransaction, getBridgeStatus, } from './transaction-utils.js';
|
|
13
|
+
// wallet
|
|
14
|
+
export { queryDepositCount, createPhonyDepositCalldata, } from './wallet.js';
|
|
15
|
+
// storage
|
|
16
|
+
export { STORAGE_KEY_AUTH_PREFIX, STORAGE_KEY_WALLET_PREFIX, getAuthStorageKey, getWalletStorageKey, loadCachedAuth, saveAuth, clearAuth, saveWalletData, loadWalletData, clearWalletData, } from './storage.js';
|
|
17
|
+
// chain
|
|
18
|
+
export { ensureChain, pingWalletConnectSession, clearStaleWalletConnectSessions, createPublicClientWithRpc, waitForTransactionConfirmation, executeTransaction, } from './chain.js';
|
|
19
|
+
// chains
|
|
20
|
+
export { SOLANA_CHAIN_ID, BITCOIN_CHAIN_ID, TRON_CHAIN_ID, A_VIEM_CHAINS, getChainById, } from './chains.js';
|
|
21
|
+
// rpc
|
|
22
|
+
export { H_RPCS, } from './rpc.js';
|
|
23
|
+
export { loadAssetsData, getAllAssets, getAllChains, getAllAssetsArray, getCommonAssets, COMMON_ASSETS, CHAIN_NAMES, getAssetByCaip19, getChainByCaip2, getAssetsByChain, getChainName, searchAssets, } from './assets.js';
|
|
24
|
+
// encoding
|
|
25
|
+
export { hexToBytes, bytesToBase58, hexToBase58, base93ToBytes, bytesToBase93, } from './encoding.js';
|
|
26
|
+
export { DepositStatus, orderIdToBytes32, queryOrderStatus, checkRefundEligibility, executeRefund, checkRecoveryEligibility, } from './refund.js';
|
|
20
27
|
export { trackOrderViaWebSocket, getOrderTrackingWebSocketUrl, } from './order-tracking.js';
|
|
21
28
|
export { bytes_to_base58, base58_to_bytes, bytes_to_base93, base93_to_bytes, bytes_to_hex, hex_to_bytes } from './belt-utils.js';
|
|
22
|
-
export
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export
|
|
29
|
-
export * from './errors.js';
|
|
29
|
+
export { isValidEvmAddress, isValidSolanaAddress, isValidBitcoinAddress, isValidTronAddress, validateAddress, normalizeAddress, isValidEnsName, formatAddress, formatAddressByType, getAvatarColor, getAvatarInitials, createCaip10, parseCaip10, getAddressFromCaip10, evmAddressToCaip10, solanaAddressToCaip10, bitcoinAddressToCaip10, addressToCaip10, isContactCompatibleWithAsset, filterContacts, } from './address.js';
|
|
30
|
+
// asset-utils
|
|
31
|
+
export { parseCaip19Legacy, getChainNamespaceFromAsset, getChainIdFromAsset, getAssetNamespaceFromAsset, getAssetId, getCaip2, getTokenAddress, isBitcoin, isEvm, isSolana, isCosmos, isSui, isTron, isNativeTokenFromAsset, isEvmNative, isEvmErc20, isSolanaNative, isSolanaToken, isCosmosNative, isCosmosIbc, getTokenChainId, getTokenChainIdString, extractChainIdsFromAssets, extractChainIdFromAsset, getTokenChainInfo, getTokenChainName, switchChainNamespace, } from './asset-utils.js';
|
|
32
|
+
// solana-utils
|
|
33
|
+
export { getSolanaRpcUrl, } from './solana-utils.js';
|
|
34
|
+
// errors
|
|
35
|
+
export { SilentSwapError, ApiError, NetworkError, AuthenticationError, QuoteError, OrderError, ValidationError, ConfigurationError, WalletError, TransactionError, createErrorFromResponse, } from './errors.js';
|
|
30
36
|
// Swap executor for Node.js integrators
|
|
31
37
|
export { executeSolanaSwap, } from './swap-executor.js';
|
package/dist/order.d.ts
CHANGED
|
@@ -276,5 +276,10 @@ export declare const EIP712_DOMAIN_ORDER_DEFAULT: {
|
|
|
276
276
|
readonly version: "1";
|
|
277
277
|
readonly chainId: 1;
|
|
278
278
|
};
|
|
279
|
+
export declare const EIP712_DOMAIN_WALLET_GENERATION: {
|
|
280
|
+
readonly name: "SilentSwap v2";
|
|
281
|
+
readonly version: "1";
|
|
282
|
+
readonly chainId: 43114;
|
|
283
|
+
};
|
|
279
284
|
export declare function quoteResponseToEip712Document(quoteResponse: QuoteResponse): TypedDataDocument<typeof EIP712_DOMAIN_ORDER_DEFAULT>;
|
|
280
285
|
export {};
|
package/dist/order.js
CHANGED
|
@@ -94,11 +94,25 @@ export const EIP712_TYPES_WALLET_GENERATION = {
|
|
|
94
94
|
{ name: 'token', type: 'string' },
|
|
95
95
|
],
|
|
96
96
|
};
|
|
97
|
+
// Orders must be signed with chainId === 1 (Ethereum mainnet) — the backend
|
|
98
|
+
// rejects any other chainId with "eip712Domain value is invalid or not supported.
|
|
99
|
+
// expected mainnet chain ID 1". Wallet-generation typed data uses a different
|
|
100
|
+
// domain (EIP712_DOMAIN_WALLET_GENERATION below) and is not subject to that
|
|
101
|
+
// constraint.
|
|
97
102
|
export const EIP712_DOMAIN_ORDER_DEFAULT = {
|
|
98
103
|
name: 'SilentSwap v2',
|
|
99
104
|
version: '1',
|
|
100
105
|
chainId: 1,
|
|
101
106
|
};
|
|
107
|
+
// Wallet-generation typed data is signed locally to derive entropy — the chainId
|
|
108
|
+
// only matters for the wallet's cross-chain replay-protection check at sign time.
|
|
109
|
+
// Pinned to Avalanche (43114) so the user doesn't have to leave their working
|
|
110
|
+
// chain just to derive the wallet.
|
|
111
|
+
export const EIP712_DOMAIN_WALLET_GENERATION = {
|
|
112
|
+
name: 'SilentSwap v2',
|
|
113
|
+
version: '1',
|
|
114
|
+
chainId: 43114,
|
|
115
|
+
};
|
|
102
116
|
export function quoteResponseToEip712Document(quoteResponse) {
|
|
103
117
|
return {
|
|
104
118
|
domain: EIP712_DOMAIN_ORDER_DEFAULT,
|
package/dist/sdk.d.ts
CHANGED
|
@@ -156,7 +156,7 @@ export declare function createEip712DocForWalletGeneration(scope: string, token:
|
|
|
156
156
|
domain: {
|
|
157
157
|
readonly name: "SilentSwap v2";
|
|
158
158
|
readonly version: "1";
|
|
159
|
-
readonly chainId:
|
|
159
|
+
readonly chainId: 43114;
|
|
160
160
|
};
|
|
161
161
|
primaryType: "WalletGeneration";
|
|
162
162
|
message: {
|
package/dist/sdk.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSiweMessage } from 'viem/siwe';
|
|
2
|
-
import { EIP712_DOMAIN_ORDER_DEFAULT, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION } from './order.js';
|
|
2
|
+
import { EIP712_DOMAIN_ORDER_DEFAULT, EIP712_DOMAIN_WALLET_GENERATION, EIP712_TYPES_ORDER, EIP712_TYPES_WALLET_GENERATION } from './order.js';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a SIWE message for authentication with SilentSwap
|
|
5
5
|
* @param user - user's EVM address
|
|
@@ -49,7 +49,7 @@ export function createEip712DocForOrder(quote) {
|
|
|
49
49
|
export function createEip712DocForWalletGeneration(scope, token) {
|
|
50
50
|
return {
|
|
51
51
|
types: EIP712_TYPES_WALLET_GENERATION,
|
|
52
|
-
domain:
|
|
52
|
+
domain: EIP712_DOMAIN_WALLET_GENERATION,
|
|
53
53
|
primaryType: 'WalletGeneration',
|
|
54
54
|
message: {
|
|
55
55
|
description: 'Securely create a temporary, anonymous wallet for SilentSwap use only.',
|