@silentswap/sdk 0.0.21 → 0.0.22
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 +55 -0
- package/dist/assets.js +101 -0
- package/dist/bridge.d.ts +211 -0
- package/dist/bridge.js +615 -0
- package/dist/chain.d.ts +35 -0
- package/dist/chain.js +81 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +16 -0
- package/dist/data/filtered.json +2179 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +8 -0
- package/dist/quote-utils.d.ts +75 -0
- package/dist/quote-utils.js +185 -0
- package/dist/storage.d.ts +74 -0
- package/dist/storage.js +161 -0
- package/dist/transaction-utils.d.ts +19 -0
- package/dist/transaction-utils.js +85 -0
- package/dist/wallet.d.ts +18 -0
- package/dist/wallet.js +107 -0
- package/package.json +10 -4
- package/src/data/filtered.json +2179 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { SilentSwapClientConfig, SilentSwapClient, } from './client.js';
|
|
2
2
|
export type * from './types/api.js';
|
|
3
|
-
export type { Caip19 } from './types/core.js';
|
|
3
|
+
export type { Caip19, SignInMessage } from './types/core.js';
|
|
4
4
|
export type { EvmSigner } from './types/sdk.js';
|
|
5
5
|
export * from './order.js';
|
|
6
6
|
export * from './caip19.js';
|
|
@@ -10,3 +10,11 @@ export * from './gateway-abi.js';
|
|
|
10
10
|
export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, type HdFacilitatorGroup, } from './hd-facilitator-group.js';
|
|
11
11
|
export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
|
|
12
12
|
export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
|
|
13
|
+
export * from './bridge.js';
|
|
14
|
+
export * from './quote-utils.js';
|
|
15
|
+
export * from './transaction-utils.js';
|
|
16
|
+
export * from './wallet.js';
|
|
17
|
+
export * from './storage.js';
|
|
18
|
+
export * from './chain.js';
|
|
19
|
+
export * from './constants.js';
|
|
20
|
+
export * from './assets.js';
|
package/dist/index.js
CHANGED
|
@@ -6,3 +6,11 @@ export * from './gateway-abi.js';
|
|
|
6
6
|
export { createHdFacilitatorGroupFromEntropy, exportSecretMnemonicFromEntropy, } from './hd-facilitator-group.js';
|
|
7
7
|
export { createSignInMessage, createEip712DocForOrder, createEip712DocForWalletGeneration, } from './sdk.js';
|
|
8
8
|
export { createViemSigner, parseTransactionRequestForViem, } from './signer-adapters/viem.js';
|
|
9
|
+
export * from './bridge.js';
|
|
10
|
+
export * from './quote-utils.js';
|
|
11
|
+
export * from './transaction-utils.js';
|
|
12
|
+
export * from './wallet.js';
|
|
13
|
+
export * from './storage.js';
|
|
14
|
+
export * from './chain.js';
|
|
15
|
+
export * from './constants.js';
|
|
16
|
+
export * from './assets.js';
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { BridgeProvider, RelayQuoteResponse, DeBridgeOrderResponse } from './bridge.js';
|
|
2
|
+
/**
|
|
3
|
+
* Estimate sample for retention rate interpolation
|
|
4
|
+
*/
|
|
5
|
+
export interface EstimateSample {
|
|
6
|
+
/** USD baseline value for this sample */
|
|
7
|
+
baseline: number;
|
|
8
|
+
/** Retention rate (0-1) - how much value is retained after fees */
|
|
9
|
+
retention: number;
|
|
10
|
+
/** Bridge source that provided this sample */
|
|
11
|
+
source: BridgeProvider | 'none';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Estimate for a given direction (ingress or egress)
|
|
15
|
+
*/
|
|
16
|
+
export interface Estimate {
|
|
17
|
+
/** Gas fee in USD for this direction */
|
|
18
|
+
gasFee: number;
|
|
19
|
+
/** Array of samples for retention rate interpolation */
|
|
20
|
+
samples: EstimateSample[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Quote metrics calculated from provider responses
|
|
24
|
+
*/
|
|
25
|
+
export interface QuoteMetrics {
|
|
26
|
+
retention: number;
|
|
27
|
+
feeUsd: number;
|
|
28
|
+
slippage: number;
|
|
29
|
+
time: number;
|
|
30
|
+
txCount: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Quote result with all necessary information
|
|
34
|
+
*/
|
|
35
|
+
export interface BridgeQuoteResult {
|
|
36
|
+
/** Selected bridge provider */
|
|
37
|
+
provider: BridgeProvider;
|
|
38
|
+
/** Output amount in destination token units (as string) */
|
|
39
|
+
outputAmount: string;
|
|
40
|
+
/** Input amount required in source token units (as string) */
|
|
41
|
+
inputAmount: string;
|
|
42
|
+
/** Total fee in USD */
|
|
43
|
+
feeUsd: number;
|
|
44
|
+
/** Price slippage/impact percentage */
|
|
45
|
+
slippage: number;
|
|
46
|
+
/** Estimated time in seconds */
|
|
47
|
+
estimatedTime: number;
|
|
48
|
+
/** Retention rate (how much value is retained after fees, 0-1) */
|
|
49
|
+
retentionRate: number;
|
|
50
|
+
/** Number of transactions required */
|
|
51
|
+
txCount: number;
|
|
52
|
+
/** Raw response from the provider */
|
|
53
|
+
rawResponse: RelayQuoteResponse | DeBridgeOrderResponse;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Calculate metrics from a Relay.link quote response
|
|
57
|
+
*/
|
|
58
|
+
export declare function calculateRelayMetrics(relayQuote: RelayQuoteResponse): QuoteMetrics;
|
|
59
|
+
/**
|
|
60
|
+
* Calculate metrics from a deBridge quote response
|
|
61
|
+
*/
|
|
62
|
+
export declare function calculateDebridgeMetrics(debridgeQuote: DeBridgeOrderResponse): QuoteMetrics;
|
|
63
|
+
/**
|
|
64
|
+
* Select the best quote from multiple providers based on retention rate
|
|
65
|
+
*/
|
|
66
|
+
export declare function selectBestQuote(relayQuote: RelayQuoteResponse | null, debridgeQuote: DeBridgeOrderResponse | null, srcAmount: string): BridgeQuoteResult;
|
|
67
|
+
/**
|
|
68
|
+
* Interpolate retention rate from samples
|
|
69
|
+
*/
|
|
70
|
+
export declare function interpolateSamples(samples: EstimateSample[], usdValue: number, marginHi?: number): number;
|
|
71
|
+
/**
|
|
72
|
+
* Get quote for cross-chain swap from multiple providers
|
|
73
|
+
* This is the core logic shared between React and Vue
|
|
74
|
+
*/
|
|
75
|
+
export declare function getBridgeQuote(srcChainId: number, srcToken: string, srcAmount: string, dstChainId: number, dstToken: string, userAddress: `0x${string}`, signal?: AbortSignal): Promise<BridgeQuoteResult>;
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
import { fetchRelayQuote, fetchDebridgeOrder, } from './bridge.js';
|
|
3
|
+
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
4
|
+
/**
|
|
5
|
+
* Calculate metrics from a Relay.link quote response
|
|
6
|
+
*/
|
|
7
|
+
export function calculateRelayMetrics(relayQuote) {
|
|
8
|
+
const usdIn = relayQuote.details.currencyIn.amountUsd;
|
|
9
|
+
const usdOut = relayQuote.details.currencyOut.amountUsd;
|
|
10
|
+
return {
|
|
11
|
+
retention: BigNumber(usdOut).div(usdIn).toNumber(),
|
|
12
|
+
feeUsd: Number(relayQuote.fees.relayerGas?.amountUsd || relayQuote.fees.gas?.amountUsd || '0'),
|
|
13
|
+
slippage: Number(relayQuote.details.totalImpact?.percent || '0') * 100,
|
|
14
|
+
time: relayQuote.details.timeEstimate || 300,
|
|
15
|
+
txCount: relayQuote.steps?.length || 1,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculate metrics from a deBridge quote response
|
|
20
|
+
*/
|
|
21
|
+
export function calculateDebridgeMetrics(debridgeQuote) {
|
|
22
|
+
const usdIn = debridgeQuote.estimation.srcChainTokenIn.approximateUsdValue;
|
|
23
|
+
const usdOut = debridgeQuote.estimation.dstChainTokenOut.approximateUsdValue;
|
|
24
|
+
return {
|
|
25
|
+
retention: BigNumber(usdOut).div(usdIn).toNumber(),
|
|
26
|
+
feeUsd: debridgeQuote.estimation.costDetails
|
|
27
|
+
?.reduce((sum, detail) => sum + Number(detail.payload?.feeApproximateUsdValue || 0), 0) || 0,
|
|
28
|
+
slippage: 100 * (1 - usdOut / usdIn),
|
|
29
|
+
time: debridgeQuote.order?.approximateFulfillmentDelay || 600,
|
|
30
|
+
txCount: 2, // DeBridge typically requires 2 txs
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Select the best quote from multiple providers based on retention rate
|
|
35
|
+
*/
|
|
36
|
+
export function selectBestQuote(relayQuote, debridgeQuote, srcAmount) {
|
|
37
|
+
// Calculate metrics for each provider
|
|
38
|
+
const relayMetrics = relayQuote ? calculateRelayMetrics(relayQuote) : null;
|
|
39
|
+
const debridgeMetrics = debridgeQuote ? calculateDebridgeMetrics(debridgeQuote) : null;
|
|
40
|
+
// Both providers failed
|
|
41
|
+
if (!relayQuote && !debridgeQuote) {
|
|
42
|
+
throw new Error('All quote providers failed');
|
|
43
|
+
}
|
|
44
|
+
// Determine best provider based on retention rate
|
|
45
|
+
let bestProvider;
|
|
46
|
+
let bestQuote;
|
|
47
|
+
let bestMetrics;
|
|
48
|
+
if (!relayQuote || (debridgeMetrics && debridgeMetrics.retention > (relayMetrics?.retention || 0))) {
|
|
49
|
+
bestProvider = 'debridge';
|
|
50
|
+
bestQuote = debridgeQuote;
|
|
51
|
+
bestMetrics = debridgeMetrics;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
bestProvider = 'relay';
|
|
55
|
+
bestQuote = relayQuote;
|
|
56
|
+
bestMetrics = relayMetrics;
|
|
57
|
+
}
|
|
58
|
+
// Extract output amount
|
|
59
|
+
const outputAmount = bestProvider === 'relay'
|
|
60
|
+
? bestQuote.details.currencyOut.amount
|
|
61
|
+
: bestQuote.estimation.dstChainTokenOut.amount;
|
|
62
|
+
return {
|
|
63
|
+
provider: bestProvider,
|
|
64
|
+
outputAmount: outputAmount || '0',
|
|
65
|
+
inputAmount: srcAmount,
|
|
66
|
+
feeUsd: bestMetrics.feeUsd,
|
|
67
|
+
slippage: bestMetrics.slippage,
|
|
68
|
+
estimatedTime: bestMetrics.time,
|
|
69
|
+
retentionRate: bestMetrics.retention,
|
|
70
|
+
txCount: bestMetrics.txCount,
|
|
71
|
+
rawResponse: bestQuote,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Interpolate retention rate from samples
|
|
76
|
+
*/
|
|
77
|
+
export function interpolateSamples(samples, usdValue, marginHi = Infinity) {
|
|
78
|
+
if (samples.length === 0) {
|
|
79
|
+
throw new Error('No samples provided');
|
|
80
|
+
}
|
|
81
|
+
let lo = samples[0];
|
|
82
|
+
let hi = samples[samples.length - 1];
|
|
83
|
+
// Less than or equal to lo
|
|
84
|
+
if (usdValue <= lo.baseline) {
|
|
85
|
+
return lo.retention;
|
|
86
|
+
}
|
|
87
|
+
// Greater than or equal to hi
|
|
88
|
+
if (usdValue >= hi.baseline) {
|
|
89
|
+
// Exclusive hi with margin check
|
|
90
|
+
if (usdValue > hi.baseline + marginHi) {
|
|
91
|
+
throw new Error(`Value ${usdValue} exceeds maximum ${hi.baseline} by more than margin ${marginHi}`);
|
|
92
|
+
}
|
|
93
|
+
return hi.retention;
|
|
94
|
+
}
|
|
95
|
+
// In range - find bracketing samples
|
|
96
|
+
for (let i = 0; i < samples.length; i++) {
|
|
97
|
+
const sample = samples[i];
|
|
98
|
+
// Exact match
|
|
99
|
+
if (sample.baseline === usdValue) {
|
|
100
|
+
return sample.retention;
|
|
101
|
+
}
|
|
102
|
+
// Target is greater than sample
|
|
103
|
+
if (usdValue > sample.baseline) {
|
|
104
|
+
lo = sample;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// Target is lower than sample
|
|
108
|
+
hi = sample;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Linear interpolation
|
|
113
|
+
const deltaY = hi.retention - lo.retention;
|
|
114
|
+
const deltaX = hi.baseline - lo.baseline;
|
|
115
|
+
return ((usdValue - lo.baseline) / deltaX) * deltaY + lo.retention;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get quote for cross-chain swap from multiple providers
|
|
119
|
+
* This is the core logic shared between React and Vue
|
|
120
|
+
*/
|
|
121
|
+
export async function getBridgeQuote(srcChainId, srcToken, srcAmount, dstChainId, dstToken, userAddress, signal) {
|
|
122
|
+
// Normalize addresses
|
|
123
|
+
const srcTokenNorm = srcToken === '0x0' || srcToken === '0x0000000000000000000000000000000000000000'
|
|
124
|
+
? ZERO_ADDRESS
|
|
125
|
+
: srcToken;
|
|
126
|
+
const dstTokenNorm = dstToken === '0x0' || dstToken === '0x0000000000000000000000000000000000000000'
|
|
127
|
+
? ZERO_ADDRESS
|
|
128
|
+
: dstToken;
|
|
129
|
+
// Fetch quotes from both providers in parallel
|
|
130
|
+
const [relayResult, debridgeResult] = await Promise.allSettled([
|
|
131
|
+
// Relay.link quote
|
|
132
|
+
(async () => {
|
|
133
|
+
try {
|
|
134
|
+
const quote = await fetchRelayQuote({
|
|
135
|
+
user: userAddress,
|
|
136
|
+
referrer: 'silentswap',
|
|
137
|
+
originChainId: srcChainId,
|
|
138
|
+
destinationChainId: dstChainId,
|
|
139
|
+
originCurrency: srcTokenNorm,
|
|
140
|
+
destinationCurrency: dstTokenNorm,
|
|
141
|
+
amount: srcAmount,
|
|
142
|
+
tradeType: 'EXACT_INPUT',
|
|
143
|
+
}, signal);
|
|
144
|
+
return quote;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (err instanceof Error && err.name !== 'AbortError') {
|
|
148
|
+
console.warn('Relay quote failed:', err);
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
})(),
|
|
153
|
+
// deBridge quote
|
|
154
|
+
(async () => {
|
|
155
|
+
try {
|
|
156
|
+
const quote = await fetchDebridgeOrder({
|
|
157
|
+
srcChainId,
|
|
158
|
+
srcChainTokenIn: srcTokenNorm,
|
|
159
|
+
srcChainTokenInAmount: srcAmount,
|
|
160
|
+
dstChainId,
|
|
161
|
+
dstChainTokenOut: dstTokenNorm,
|
|
162
|
+
dstChainTokenOutAmount: 'auto',
|
|
163
|
+
prependOperatingExpenses: true,
|
|
164
|
+
}, signal);
|
|
165
|
+
return quote;
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
if (err instanceof Error && err.name !== 'AbortError') {
|
|
169
|
+
console.warn('DeBridge quote failed:', err);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
})(),
|
|
174
|
+
]);
|
|
175
|
+
const relayQuote = relayResult.status === 'fulfilled' ? relayResult.value : null;
|
|
176
|
+
const debridgeQuote = debridgeResult.status === 'fulfilled' ? debridgeResult.value : null;
|
|
177
|
+
// Select best quote
|
|
178
|
+
const result = selectBestQuote(relayQuote, debridgeQuote, srcAmount);
|
|
179
|
+
console.info(`Selected ${result.provider} for quote:`, {
|
|
180
|
+
retention: result.retentionRate,
|
|
181
|
+
feeUsd: result.feeUsd,
|
|
182
|
+
time: result.estimatedTime,
|
|
183
|
+
});
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { AuthResponse } from './types/api.js';
|
|
2
|
+
/**
|
|
3
|
+
* Storage key prefix for authentication data
|
|
4
|
+
*/
|
|
5
|
+
export declare const STORAGE_KEY_AUTH_PREFIX = "silentswap:auth:";
|
|
6
|
+
/**
|
|
7
|
+
* Storage key prefix for wallet data
|
|
8
|
+
*/
|
|
9
|
+
export declare const STORAGE_KEY_WALLET_PREFIX = "silentswap:signer:";
|
|
10
|
+
/**
|
|
11
|
+
* Get storage key for authentication data
|
|
12
|
+
*
|
|
13
|
+
* @param address - The user's EVM address
|
|
14
|
+
* @returns The storage key for the auth data
|
|
15
|
+
*/
|
|
16
|
+
export declare function getAuthStorageKey(address: `0x${string}`): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get storage key for wallet data
|
|
19
|
+
*
|
|
20
|
+
* @param address - The user's EVM address
|
|
21
|
+
* @returns The storage key for the wallet data
|
|
22
|
+
*/
|
|
23
|
+
export declare function getWalletStorageKey(address: `0x${string}`): string;
|
|
24
|
+
/**
|
|
25
|
+
* Load cached authentication data
|
|
26
|
+
*
|
|
27
|
+
* @param address - The user's EVM address
|
|
28
|
+
* @returns The cached auth response or null if not found/expired
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadCachedAuth(address: `0x${string}`): AuthResponse | null;
|
|
31
|
+
/**
|
|
32
|
+
* Save authentication data to cache
|
|
33
|
+
*
|
|
34
|
+
* @param address - The user's EVM address
|
|
35
|
+
* @param authData - The authentication response to cache
|
|
36
|
+
*/
|
|
37
|
+
export declare function saveAuth(address: `0x${string}`, authData: AuthResponse): void;
|
|
38
|
+
/**
|
|
39
|
+
* Clear cached authentication data
|
|
40
|
+
*
|
|
41
|
+
* @param address - The user's EVM address
|
|
42
|
+
*/
|
|
43
|
+
export declare function clearAuth(address: `0x${string}`): void;
|
|
44
|
+
/**
|
|
45
|
+
* Save wallet data to sessionStorage
|
|
46
|
+
*
|
|
47
|
+
* @param address - The user's EVM address
|
|
48
|
+
* @param walletData - The wallet data to cache
|
|
49
|
+
* @param expirationMs - Expiration time in milliseconds from now
|
|
50
|
+
*/
|
|
51
|
+
export declare function saveWalletData(address: `0x${string}`, walletData: {
|
|
52
|
+
entropy: string;
|
|
53
|
+
accounts: {
|
|
54
|
+
nonce: number;
|
|
55
|
+
}[];
|
|
56
|
+
}, expirationMs?: number): void;
|
|
57
|
+
/**
|
|
58
|
+
* Load cached wallet data from sessionStorage
|
|
59
|
+
*
|
|
60
|
+
* @param address - The user's EVM address
|
|
61
|
+
* @returns The cached wallet data or null if not found/expired
|
|
62
|
+
*/
|
|
63
|
+
export declare function loadWalletData(address: `0x${string}`): {
|
|
64
|
+
entropy: string;
|
|
65
|
+
accounts: {
|
|
66
|
+
nonce: number;
|
|
67
|
+
}[];
|
|
68
|
+
} | null;
|
|
69
|
+
/**
|
|
70
|
+
* Clear cached wallet data
|
|
71
|
+
*
|
|
72
|
+
* @param address - The user's EVM address
|
|
73
|
+
*/
|
|
74
|
+
export declare function clearWalletData(address: `0x${string}`): void;
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { getAddress } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Storage key prefix for authentication data
|
|
4
|
+
*/
|
|
5
|
+
export const STORAGE_KEY_AUTH_PREFIX = 'silentswap:auth:';
|
|
6
|
+
/**
|
|
7
|
+
* Storage key prefix for wallet data
|
|
8
|
+
*/
|
|
9
|
+
export const STORAGE_KEY_WALLET_PREFIX = 'silentswap:signer:';
|
|
10
|
+
/**
|
|
11
|
+
* Get storage key for authentication data
|
|
12
|
+
*
|
|
13
|
+
* @param address - The user's EVM address
|
|
14
|
+
* @returns The storage key for the auth data
|
|
15
|
+
*/
|
|
16
|
+
export function getAuthStorageKey(address) {
|
|
17
|
+
return `${STORAGE_KEY_AUTH_PREFIX}${getAddress(address)}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get storage key for wallet data
|
|
21
|
+
*
|
|
22
|
+
* @param address - The user's EVM address
|
|
23
|
+
* @returns The storage key for the wallet data
|
|
24
|
+
*/
|
|
25
|
+
export function getWalletStorageKey(address) {
|
|
26
|
+
return `${STORAGE_KEY_WALLET_PREFIX}${getAddress(address)}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Load cached authentication data
|
|
30
|
+
*
|
|
31
|
+
* @param address - The user's EVM address
|
|
32
|
+
* @returns The cached auth response or null if not found/expired
|
|
33
|
+
*/
|
|
34
|
+
export function loadCachedAuth(address) {
|
|
35
|
+
const normalizedAddress = getAddress(address);
|
|
36
|
+
try {
|
|
37
|
+
const storageKey = getAuthStorageKey(normalizedAddress);
|
|
38
|
+
const cachedData = typeof localStorage !== 'undefined' ? localStorage.getItem(storageKey) : null;
|
|
39
|
+
if (!cachedData)
|
|
40
|
+
return null;
|
|
41
|
+
const cachedAuth = JSON.parse(cachedData);
|
|
42
|
+
// Check if auth is still valid
|
|
43
|
+
if (cachedAuth.authExpires && cachedAuth.authExpires > Date.now()) {
|
|
44
|
+
return cachedAuth;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Remove expired auth
|
|
48
|
+
if (typeof localStorage !== 'undefined') {
|
|
49
|
+
localStorage.removeItem(storageKey);
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
console.warn('Failed to load cached auth:', err);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Save authentication data to cache
|
|
61
|
+
*
|
|
62
|
+
* @param address - The user's EVM address
|
|
63
|
+
* @param authData - The authentication response to cache
|
|
64
|
+
*/
|
|
65
|
+
export function saveAuth(address, authData) {
|
|
66
|
+
const normalizedAddress = getAddress(address);
|
|
67
|
+
try {
|
|
68
|
+
const storageKey = getAuthStorageKey(normalizedAddress);
|
|
69
|
+
if (typeof localStorage !== 'undefined') {
|
|
70
|
+
localStorage.setItem(storageKey, JSON.stringify(authData));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.warn('Failed to save auth:', err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clear cached authentication data
|
|
79
|
+
*
|
|
80
|
+
* @param address - The user's EVM address
|
|
81
|
+
*/
|
|
82
|
+
export function clearAuth(address) {
|
|
83
|
+
const normalizedAddress = getAddress(address);
|
|
84
|
+
const storageKey = getAuthStorageKey(normalizedAddress);
|
|
85
|
+
if (typeof localStorage !== 'undefined') {
|
|
86
|
+
localStorage.removeItem(storageKey);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Save wallet data to sessionStorage
|
|
91
|
+
*
|
|
92
|
+
* @param address - The user's EVM address
|
|
93
|
+
* @param walletData - The wallet data to cache
|
|
94
|
+
* @param expirationMs - Expiration time in milliseconds from now
|
|
95
|
+
*/
|
|
96
|
+
export function saveWalletData(address, walletData, expirationMs = 24 * 60 * 60 * 1000 // 24 hours
|
|
97
|
+
) {
|
|
98
|
+
const normalizedAddress = getAddress(address);
|
|
99
|
+
try {
|
|
100
|
+
const storageKey = getWalletStorageKey(normalizedAddress);
|
|
101
|
+
const data = {
|
|
102
|
+
...walletData,
|
|
103
|
+
expiration: Date.now() + expirationMs,
|
|
104
|
+
};
|
|
105
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
106
|
+
sessionStorage.setItem(storageKey, JSON.stringify(data));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
console.warn('Failed to save wallet data:', err);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Load cached wallet data from sessionStorage
|
|
115
|
+
*
|
|
116
|
+
* @param address - The user's EVM address
|
|
117
|
+
* @returns The cached wallet data or null if not found/expired
|
|
118
|
+
*/
|
|
119
|
+
export function loadWalletData(address) {
|
|
120
|
+
const normalizedAddress = getAddress(address);
|
|
121
|
+
try {
|
|
122
|
+
const storageKey = getWalletStorageKey(normalizedAddress);
|
|
123
|
+
const sessionData = typeof sessionStorage !== 'undefined'
|
|
124
|
+
? sessionStorage.getItem(storageKey)
|
|
125
|
+
: null;
|
|
126
|
+
if (!sessionData)
|
|
127
|
+
return null;
|
|
128
|
+
const cached = JSON.parse(sessionData);
|
|
129
|
+
// Check expiration
|
|
130
|
+
if (cached.expiration <= Date.now()) {
|
|
131
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
132
|
+
sessionStorage.removeItem(storageKey);
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
entropy: cached.entropy,
|
|
138
|
+
accounts: cached.accounts,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
console.warn('Failed to load wallet data:', err);
|
|
143
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
144
|
+
const storageKey = getWalletStorageKey(normalizedAddress);
|
|
145
|
+
sessionStorage.removeItem(storageKey);
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear cached wallet data
|
|
152
|
+
*
|
|
153
|
+
* @param address - The user's EVM address
|
|
154
|
+
*/
|
|
155
|
+
export function clearWalletData(address) {
|
|
156
|
+
const normalizedAddress = getAddress(address);
|
|
157
|
+
const storageKey = getWalletStorageKey(normalizedAddress);
|
|
158
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
159
|
+
sessionStorage.removeItem(storageKey);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Hex, WalletClient } from 'viem';
|
|
2
|
+
import type { Connector } from 'wagmi';
|
|
3
|
+
import type { BridgeProvider, BridgeQuote, BridgeTransaction, BridgeStatus } from './bridge.js';
|
|
4
|
+
/**
|
|
5
|
+
* Create transaction execution wrapper for framework-agnostic bridge execution
|
|
6
|
+
*/
|
|
7
|
+
export declare function createTransactionExecutor(walletClient: WalletClient, connector: Connector): (tx: BridgeTransaction) => Promise<Hex>;
|
|
8
|
+
/**
|
|
9
|
+
* Create chain switching wrapper
|
|
10
|
+
*/
|
|
11
|
+
export declare function createChainSwitcher(walletClient: WalletClient, connector: Connector): (chainId: number) => Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Execute a bridge transaction (framework-agnostic)
|
|
14
|
+
*/
|
|
15
|
+
export declare function executeBridgeTransaction(quote: BridgeQuote, walletClient: WalletClient, connector: Connector, setStep: (step: string) => void): Promise<BridgeStatus>;
|
|
16
|
+
/**
|
|
17
|
+
* Get bridge status (framework-agnostic)
|
|
18
|
+
*/
|
|
19
|
+
export declare function getBridgeStatus(requestId: string, provider: BridgeProvider): Promise<BridgeStatus>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { executeRelayBridge, executeDebridgeBridge, getRelayStatus, getDebridgeStatus, } from './bridge.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create transaction execution wrapper for framework-agnostic bridge execution
|
|
4
|
+
*/
|
|
5
|
+
export function createTransactionExecutor(walletClient, connector) {
|
|
6
|
+
return async (tx) => {
|
|
7
|
+
// Switch to the correct chain if needed
|
|
8
|
+
let currentChainId;
|
|
9
|
+
try {
|
|
10
|
+
currentChainId = await walletClient.getChainId();
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
currentChainId = -1;
|
|
14
|
+
}
|
|
15
|
+
if (currentChainId !== tx.chainId) {
|
|
16
|
+
try {
|
|
17
|
+
await connector.switchChain?.({ chainId: tx.chainId });
|
|
18
|
+
}
|
|
19
|
+
catch (switchError) {
|
|
20
|
+
throw new Error(`Failed to switch to chain ${tx.chainId}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Send transaction
|
|
24
|
+
const hash = await walletClient.sendTransaction({
|
|
25
|
+
account: walletClient.account,
|
|
26
|
+
chain: null,
|
|
27
|
+
to: tx.to,
|
|
28
|
+
value: BigInt(tx.value),
|
|
29
|
+
data: tx.data,
|
|
30
|
+
gas: tx.gasLimit ? BigInt(tx.gasLimit) : undefined,
|
|
31
|
+
});
|
|
32
|
+
return hash;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Create chain switching wrapper
|
|
37
|
+
*/
|
|
38
|
+
export function createChainSwitcher(walletClient, connector) {
|
|
39
|
+
return async (chainId) => {
|
|
40
|
+
// Check current chain
|
|
41
|
+
let currentChainId;
|
|
42
|
+
try {
|
|
43
|
+
currentChainId = await walletClient?.getChainId() || -1;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
currentChainId = -1;
|
|
47
|
+
}
|
|
48
|
+
if (currentChainId !== chainId) {
|
|
49
|
+
try {
|
|
50
|
+
await connector.switchChain?.({ chainId });
|
|
51
|
+
}
|
|
52
|
+
catch (switchError) {
|
|
53
|
+
throw new Error(`Failed to switch to chain ${chainId}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Execute a bridge transaction (framework-agnostic)
|
|
60
|
+
*/
|
|
61
|
+
export async function executeBridgeTransaction(quote, walletClient, connector, setStep) {
|
|
62
|
+
const executeTransaction = createTransactionExecutor(walletClient, connector);
|
|
63
|
+
const switchChain = createChainSwitcher(walletClient, connector);
|
|
64
|
+
switch (quote.provider) {
|
|
65
|
+
case 'relay':
|
|
66
|
+
return await executeRelayBridge(quote, executeTransaction, switchChain, setStep);
|
|
67
|
+
case 'debridge':
|
|
68
|
+
return await executeDebridgeBridge(quote, executeTransaction, switchChain, setStep);
|
|
69
|
+
default:
|
|
70
|
+
throw new Error(`Unsupported bridge provider: ${quote.provider}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get bridge status (framework-agnostic)
|
|
75
|
+
*/
|
|
76
|
+
export async function getBridgeStatus(requestId, provider) {
|
|
77
|
+
switch (provider) {
|
|
78
|
+
case 'relay':
|
|
79
|
+
return await getRelayStatus(requestId);
|
|
80
|
+
case 'debridge':
|
|
81
|
+
return await getDebridgeStatus(requestId);
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Unsupported bridge provider: ${provider}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
package/dist/wallet.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Hex } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Query the number of deposits made by a user to the Gateway contract
|
|
4
|
+
*
|
|
5
|
+
* @param userAddress - The user's EVM address
|
|
6
|
+
* @returns The number of deposits made by the user
|
|
7
|
+
*/
|
|
8
|
+
export declare function queryDepositCount(userAddress: `0x${string}`): Promise<bigint>;
|
|
9
|
+
/**
|
|
10
|
+
* Generate phony deposit proxy calldata for testing/estimation purposes
|
|
11
|
+
* This creates a valid calldata structure without actual signature data
|
|
12
|
+
*
|
|
13
|
+
* @param signerAddress - The signer's EVM address (or zero address for anonymous)
|
|
14
|
+
* @param approvalExpiration - Timestamp when approval expires (default: 12 hours from now)
|
|
15
|
+
* @param duration - Duration of the deposit in seconds (default: 7 days)
|
|
16
|
+
* @returns Encoded calldata for depositProxy2 function
|
|
17
|
+
*/
|
|
18
|
+
export declare function createPhonyDepositCalldata(signerAddress?: `0x${string}`, approvalExpiration?: bigint, duration?: bigint): Hex;
|