@shapeshiftoss/swap-widget 0.7.0 → 0.9.0
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 +172 -2
- package/dist/index.css +19 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.js +428 -209
- package/package.json +11 -6
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { useCallback as useCallback11, useEffect as useEffect10, useMemo as useM
|
|
|
4
4
|
|
|
5
5
|
// src/api/client.ts
|
|
6
6
|
var DEFAULT_API_BASE_URL = "https://api.shapeshift.com";
|
|
7
|
+
var getTradeAmount = (params) => params.buyAmountCryptoBaseUnit !== void 0 ? { buyAmountCryptoBaseUnit: params.buyAmountCryptoBaseUnit } : { sellAmountCryptoBaseUnit: params.sellAmountCryptoBaseUnit };
|
|
7
8
|
var createApiClient = (config = {}) => {
|
|
8
9
|
const baseUrl = config.baseUrl ?? DEFAULT_API_BASE_URL;
|
|
9
10
|
const fetchWithConfig = async (endpoint, params, method = "GET", timeoutMs = 3e4) => {
|
|
@@ -41,7 +42,7 @@ var createApiClient = (config = {}) => {
|
|
|
41
42
|
getRates: (params) => fetchWithConfig("/v1/swap/rates", {
|
|
42
43
|
sellAssetId: params.sellAssetId,
|
|
43
44
|
buyAssetId: params.buyAssetId,
|
|
44
|
-
|
|
45
|
+
...getTradeAmount(params)
|
|
45
46
|
}),
|
|
46
47
|
getSwapStatus: (params) => fetchWithConfig("/v1/swap/status", {
|
|
47
48
|
quoteId: params.quoteId,
|
|
@@ -52,7 +53,7 @@ var createApiClient = (config = {}) => {
|
|
|
52
53
|
{
|
|
53
54
|
sellAssetId: params.sellAssetId,
|
|
54
55
|
buyAssetId: params.buyAssetId,
|
|
55
|
-
|
|
56
|
+
...getTradeAmount(params),
|
|
56
57
|
sendAddress: params.sendAddress,
|
|
57
58
|
receiveAddress: params.receiveAddress,
|
|
58
59
|
swapperName: params.swapperName,
|
|
@@ -680,6 +681,7 @@ var formatAmount = (amount, decimals, maxDecimals) => {
|
|
|
680
681
|
minimumFractionDigits: 0
|
|
681
682
|
});
|
|
682
683
|
};
|
|
684
|
+
var formatAmountForInput = (amount, decimals) => BigAmount.fromBaseUnit({ value: amount, precision: decimals }).toPrecision();
|
|
683
685
|
var parseAmount = (amount, decimals) => {
|
|
684
686
|
return BigAmount.fromPrecision({ value: amount, precision: decimals }).toBaseUnit();
|
|
685
687
|
};
|
|
@@ -689,8 +691,11 @@ var truncateAddress = (address, chars = 4) => {
|
|
|
689
691
|
};
|
|
690
692
|
|
|
691
693
|
// src/machines/guards.ts
|
|
694
|
+
var isExactOutput = (context) => !!context.buyAmountBaseUnit;
|
|
692
695
|
var hasValidInput = (context) => {
|
|
693
|
-
|
|
696
|
+
if (!context.sellAsset || !context.buyAsset) return false;
|
|
697
|
+
const amountBaseUnit = isExactOutput(context) ? context.buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
698
|
+
return !!amountBaseUnit && amountBaseUnit !== "0";
|
|
694
699
|
};
|
|
695
700
|
var hasQuote = (context) => context.quote !== null;
|
|
696
701
|
var canRetry = (context) => context.retryCount < 3;
|
|
@@ -711,6 +716,8 @@ var createInitialContext = (input) => {
|
|
|
711
716
|
buyAsset,
|
|
712
717
|
sellAmount: "",
|
|
713
718
|
sellAmountBaseUnit: void 0,
|
|
719
|
+
buyAmount: input?.buyAmount ?? "",
|
|
720
|
+
buyAmountBaseUnit: input?.buyAmountBaseUnit,
|
|
714
721
|
isSellAmountFiat: false,
|
|
715
722
|
sellAmountFiat: "",
|
|
716
723
|
selectedRate: null,
|
|
@@ -773,12 +780,14 @@ var swapMachine = setup({
|
|
|
773
780
|
quote: null
|
|
774
781
|
};
|
|
775
782
|
}),
|
|
776
|
-
assignBuyAsset: assign(({ event }) => {
|
|
783
|
+
assignBuyAsset: assign(({ context, event }) => {
|
|
777
784
|
const { asset } = event;
|
|
778
785
|
const buyChainType = getChainType(asset.chainId);
|
|
779
786
|
return {
|
|
780
787
|
buyAsset: asset,
|
|
781
788
|
isBuyAssetEvm: buyChainType === "evm",
|
|
789
|
+
buyAmount: context.buyAmount,
|
|
790
|
+
buyAmountBaseUnit: context.buyAmount ? parseAmount(context.buyAmount, asset.precision) : void 0,
|
|
782
791
|
selectedRate: null,
|
|
783
792
|
quote: null
|
|
784
793
|
};
|
|
@@ -788,7 +797,11 @@ var swapMachine = setup({
|
|
|
788
797
|
return {
|
|
789
798
|
sellAmount: amount,
|
|
790
799
|
sellAmountBaseUnit: amountBaseUnit,
|
|
791
|
-
sellAmountFiat: fiatValue
|
|
800
|
+
sellAmountFiat: fiatValue,
|
|
801
|
+
buyAmount: "",
|
|
802
|
+
buyAmountBaseUnit: void 0,
|
|
803
|
+
selectedRate: null,
|
|
804
|
+
quote: null
|
|
792
805
|
};
|
|
793
806
|
}),
|
|
794
807
|
assignSellFiatMode: assign(({ event }) => {
|
|
@@ -832,6 +845,19 @@ var swapMachine = setup({
|
|
|
832
845
|
assignReceiveAddress: assign(({ event }) => ({
|
|
833
846
|
receiveAddress: event.address
|
|
834
847
|
})),
|
|
848
|
+
assignBuyAmount: assign(({ event }) => {
|
|
849
|
+
const { amount, amountBaseUnit } = event;
|
|
850
|
+
return {
|
|
851
|
+
buyAmount: amount,
|
|
852
|
+
buyAmountBaseUnit: amountBaseUnit,
|
|
853
|
+
sellAmount: "",
|
|
854
|
+
sellAmountBaseUnit: void 0,
|
|
855
|
+
sellAmountFiat: "",
|
|
856
|
+
isSellAmountFiat: false,
|
|
857
|
+
selectedRate: null,
|
|
858
|
+
quote: null
|
|
859
|
+
};
|
|
860
|
+
}),
|
|
835
861
|
assignChainInfo: assign(({ event }) => {
|
|
836
862
|
const e = event;
|
|
837
863
|
return {
|
|
@@ -859,6 +885,8 @@ var swapMachine = setup({
|
|
|
859
885
|
buyAsset: context.buyAsset,
|
|
860
886
|
sellAmount: context.sellAmount,
|
|
861
887
|
sellAmountBaseUnit: context.sellAmountBaseUnit,
|
|
888
|
+
buyAmount: context.buyAmount,
|
|
889
|
+
buyAmountBaseUnit: context.buyAmountBaseUnit,
|
|
862
890
|
slippage: context.slippage,
|
|
863
891
|
sendAddress: context.sendAddress,
|
|
864
892
|
receiveAddress: context.receiveAddress
|
|
@@ -877,6 +905,7 @@ var swapMachine = setup({
|
|
|
877
905
|
SET_SELL_ASSET: { actions: "assignSellAsset" },
|
|
878
906
|
SET_BUY_ASSET: { actions: "assignBuyAsset" },
|
|
879
907
|
SET_SELL_AMOUNT: { actions: "assignSellAmount" },
|
|
908
|
+
SET_BUY_AMOUNT: { actions: "assignBuyAmount" },
|
|
880
909
|
SET_SELL_FIAT_MODE: { actions: "assignSellFiatMode" },
|
|
881
910
|
SET_SLIPPAGE: { actions: "assignSlippage" },
|
|
882
911
|
SELECT_RATE: { actions: "assignSelectedRate" },
|
|
@@ -1350,11 +1379,17 @@ import {
|
|
|
1350
1379
|
mayachain,
|
|
1351
1380
|
megaeth as megaeth2,
|
|
1352
1381
|
monad as monad2,
|
|
1382
|
+
near,
|
|
1353
1383
|
optimism as optimism2,
|
|
1354
1384
|
plasma as plasma2,
|
|
1355
1385
|
polygon as polygon2,
|
|
1356
1386
|
solana,
|
|
1357
|
-
|
|
1387
|
+
starknet,
|
|
1388
|
+
sui,
|
|
1389
|
+
thorchain,
|
|
1390
|
+
ton,
|
|
1391
|
+
tron,
|
|
1392
|
+
zcash
|
|
1358
1393
|
} from "@shapeshiftoss/utils";
|
|
1359
1394
|
var BASE_ASSETS_BY_CHAIN_ID = {
|
|
1360
1395
|
[ethereum2.chainId]: ethereum2,
|
|
@@ -1374,10 +1409,16 @@ var BASE_ASSETS_BY_CHAIN_ID = {
|
|
|
1374
1409
|
[bitcoincash.chainId]: bitcoincash,
|
|
1375
1410
|
[dogecoin.chainId]: dogecoin,
|
|
1376
1411
|
[litecoin.chainId]: litecoin,
|
|
1412
|
+
[zcash.chainId]: zcash,
|
|
1377
1413
|
[atom.chainId]: atom,
|
|
1378
1414
|
[thorchain.chainId]: thorchain,
|
|
1379
1415
|
[mayachain.chainId]: mayachain,
|
|
1380
|
-
[solana.chainId]: solana
|
|
1416
|
+
[solana.chainId]: solana,
|
|
1417
|
+
[tron.chainId]: tron,
|
|
1418
|
+
[sui.chainId]: sui,
|
|
1419
|
+
[ton.chainId]: ton,
|
|
1420
|
+
[near.chainId]: near,
|
|
1421
|
+
[starknet.chainId]: starknet
|
|
1381
1422
|
};
|
|
1382
1423
|
var SUPPORTED_CHAIN_IDS_SET = new Set(
|
|
1383
1424
|
Object.keys(BASE_ASSETS_BY_CHAIN_ID)
|
|
@@ -2237,28 +2278,55 @@ var formatUsdValue = (cryptoAmount, precision, usdPrice) => {
|
|
|
2237
2278
|
};
|
|
2238
2279
|
|
|
2239
2280
|
// src/hooks/useSwapRates.ts
|
|
2240
|
-
import { bnOrZero } from "@shapeshiftoss/utils";
|
|
2241
2281
|
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
2282
|
+
|
|
2283
|
+
// src/utils/rateDisplay.ts
|
|
2284
|
+
import { bnOrZero } from "@shapeshiftoss/utils";
|
|
2285
|
+
var getRateAmountBaseUnit = (rate, isExactOutput2) => (isExactOutput2 ? rate.sellAmountCryptoBaseUnit : rate.buyAmountCryptoBaseUnit) ?? "0";
|
|
2286
|
+
var sortRatesByValue = (rates, isExactOutput2) => [...rates].filter((rate) => !rate.error && getRateAmountBaseUnit(rate, isExactOutput2) !== "0").sort((a, b) => {
|
|
2287
|
+
const aAmount = bnOrZero(getRateAmountBaseUnit(a, isExactOutput2));
|
|
2288
|
+
const bAmount = bnOrZero(getRateAmountBaseUnit(b, isExactOutput2));
|
|
2289
|
+
return isExactOutput2 ? aAmount.minus(bAmount).toNumber() : bAmount.minus(aAmount).toNumber();
|
|
2290
|
+
});
|
|
2291
|
+
var getRateDiffPercent = (bestAmountBaseUnit, amountBaseUnit, isExactOutput2) => {
|
|
2292
|
+
const best = bnOrZero(bestAmountBaseUnit);
|
|
2293
|
+
const current = bnOrZero(amountBaseUnit);
|
|
2294
|
+
if (best.isZero()) return null;
|
|
2295
|
+
const diff = isExactOutput2 ? current.minus(best).div(best).times(100) : best.minus(current).div(best).times(100);
|
|
2296
|
+
return diff.gte("0.01") ? diff.toFixed(2) : null;
|
|
2297
|
+
};
|
|
2298
|
+
|
|
2299
|
+
// src/hooks/useSwapRates.ts
|
|
2242
2300
|
var ENABLED_SWAPPER_NAMES = new Set(Object.values(SwapperName));
|
|
2243
2301
|
var useSwapRates = (apiClient, params) => {
|
|
2244
2302
|
const {
|
|
2245
2303
|
sellAssetId,
|
|
2246
2304
|
buyAssetId,
|
|
2247
2305
|
sellAmountCryptoBaseUnit,
|
|
2306
|
+
buyAmountCryptoBaseUnit,
|
|
2248
2307
|
enabled = true,
|
|
2249
2308
|
allowedSwapperNames,
|
|
2250
2309
|
refetchInterval = 15e3
|
|
2251
2310
|
} = params;
|
|
2311
|
+
const isExactOutput2 = buyAmountCryptoBaseUnit !== void 0;
|
|
2312
|
+
const amountCryptoBaseUnit = isExactOutput2 ? buyAmountCryptoBaseUnit : sellAmountCryptoBaseUnit;
|
|
2252
2313
|
return useQuery3({
|
|
2253
|
-
queryKey: [
|
|
2314
|
+
queryKey: [
|
|
2315
|
+
"swapRates",
|
|
2316
|
+
sellAssetId,
|
|
2317
|
+
buyAssetId,
|
|
2318
|
+
amountCryptoBaseUnit,
|
|
2319
|
+
isExactOutput2,
|
|
2320
|
+
allowedSwapperNames
|
|
2321
|
+
],
|
|
2254
2322
|
queryFn: async () => {
|
|
2255
|
-
if (!sellAssetId || !buyAssetId || !
|
|
2323
|
+
if (!sellAssetId || !buyAssetId || !amountCryptoBaseUnit) {
|
|
2256
2324
|
return [];
|
|
2257
2325
|
}
|
|
2258
2326
|
const response = await apiClient.getRates({
|
|
2259
2327
|
sellAssetId,
|
|
2260
2328
|
buyAssetId,
|
|
2261
|
-
sellAmountCryptoBaseUnit
|
|
2329
|
+
...isExactOutput2 ? { buyAmountCryptoBaseUnit: amountCryptoBaseUnit } : { sellAmountCryptoBaseUnit: amountCryptoBaseUnit }
|
|
2262
2330
|
});
|
|
2263
2331
|
let filteredRates = response.rates.filter(
|
|
2264
2332
|
(rate) => !rate.error && rate.buyAmountCryptoBaseUnit !== "0" && ENABLED_SWAPPER_NAMES.has(rate.swapperName)
|
|
@@ -2266,16 +2334,15 @@ var useSwapRates = (apiClient, params) => {
|
|
|
2266
2334
|
if (allowedSwapperNames?.length) {
|
|
2267
2335
|
filteredRates = filteredRates.filter((rate) => allowedSwapperNames.includes(rate.swapperName));
|
|
2268
2336
|
}
|
|
2269
|
-
return
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
});
|
|
2337
|
+
return sortRatesByValue(
|
|
2338
|
+
filteredRates.map((rate, index) => ({
|
|
2339
|
+
...rate,
|
|
2340
|
+
id: rate.id ?? `${rate.swapperName}-${index}`
|
|
2341
|
+
})),
|
|
2342
|
+
isExactOutput2
|
|
2343
|
+
);
|
|
2277
2344
|
},
|
|
2278
|
-
enabled: enabled && !!sellAssetId && !!buyAssetId && !!
|
|
2345
|
+
enabled: enabled && !!sellAssetId && !!buyAssetId && !!amountCryptoBaseUnit,
|
|
2279
2346
|
staleTime: 1e4,
|
|
2280
2347
|
refetchInterval
|
|
2281
2348
|
});
|
|
@@ -2287,18 +2354,23 @@ var useSwapDisplayValues = ({
|
|
|
2287
2354
|
allowedSwapperNames,
|
|
2288
2355
|
ratesRefetchInterval
|
|
2289
2356
|
}) => {
|
|
2290
|
-
const
|
|
2291
|
-
const
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2357
|
+
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
2358
|
+
const {
|
|
2359
|
+
sellAsset,
|
|
2360
|
+
buyAsset,
|
|
2361
|
+
buyAmountBaseUnit,
|
|
2362
|
+
isSellAssetEvm,
|
|
2363
|
+
isSellAssetUtxo,
|
|
2364
|
+
isSellAssetSolana,
|
|
2365
|
+
selectedRate
|
|
2366
|
+
} = context;
|
|
2367
|
+
const { receiveAddress, isReceiveAddressBlocked, evm, bitcoin: bitcoin3, solana: solana3 } = useSwapWallet();
|
|
2298
2368
|
const evmAddress = evm.address;
|
|
2299
2369
|
const bitcoinAddress = bitcoin3.address;
|
|
2300
2370
|
const solanaAddress = solana3.address;
|
|
2301
2371
|
const buyChainType = getChainType(buyAsset.chainId);
|
|
2372
|
+
const isExactOutput2 = !!buyAmountBaseUnit;
|
|
2373
|
+
const amountBaseUnit = isExactOutput2 ? buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
2302
2374
|
const {
|
|
2303
2375
|
data: rates,
|
|
2304
2376
|
isLoading: isLoadingRates,
|
|
@@ -2306,10 +2378,12 @@ var useSwapDisplayValues = ({
|
|
|
2306
2378
|
} = useSwapRates(apiClient, {
|
|
2307
2379
|
sellAssetId: sellAsset.assetId,
|
|
2308
2380
|
buyAssetId: buyAsset.assetId,
|
|
2309
|
-
sellAmountCryptoBaseUnit: sellAmountBaseUnit,
|
|
2381
|
+
sellAmountCryptoBaseUnit: context.sellAmountBaseUnit,
|
|
2382
|
+
buyAmountCryptoBaseUnit: buyAmountBaseUnit,
|
|
2310
2383
|
allowedSwapperNames,
|
|
2311
2384
|
refetchInterval: ratesRefetchInterval,
|
|
2312
|
-
|
|
2385
|
+
// Rates need no destination, but a locked one the buy chain rejects can never be quoted
|
|
2386
|
+
enabled: !!amountBaseUnit && amountBaseUnit !== "0" && !isReceiveAddressBlocked && (isSellAssetEvm || isSellAssetUtxo || isSellAssetSolana)
|
|
2313
2387
|
});
|
|
2314
2388
|
const {
|
|
2315
2389
|
data: sellAssetBalance,
|
|
@@ -2343,6 +2417,7 @@ var useSwapDisplayValues = ({
|
|
|
2343
2417
|
const { data: buyChainInfo } = useChainInfo(buyAsset.chainId);
|
|
2344
2418
|
const displayRate = useMemo5(() => selectedRate ?? rates?.[0], [selectedRate, rates]);
|
|
2345
2419
|
const buyAmount = displayRate?.buyAmountCryptoBaseUnit;
|
|
2420
|
+
const sellAmountBaseUnit = isExactOutput2 ? displayRate?.sellAmountCryptoBaseUnit : context.sellAmountBaseUnit;
|
|
2346
2421
|
const sellChainNativeAsset = useMemo5(() => getBaseAsset(sellAsset.chainId), [sellAsset.chainId]);
|
|
2347
2422
|
const assetIdsForPrices = useMemo5(() => {
|
|
2348
2423
|
const ids = [sellAsset.assetId, buyAsset.assetId];
|
|
@@ -2400,6 +2475,8 @@ var useSwapDisplayValues = ({
|
|
|
2400
2475
|
buyChainInfo,
|
|
2401
2476
|
displayRate,
|
|
2402
2477
|
buyAmount,
|
|
2478
|
+
isExactOutput: isExactOutput2,
|
|
2479
|
+
sellAmountBaseUnit,
|
|
2403
2480
|
sellChainNativeAsset,
|
|
2404
2481
|
networkFeeDisplay,
|
|
2405
2482
|
sellUsdValue,
|
|
@@ -2423,6 +2500,8 @@ var useSwapDisplayValues = ({
|
|
|
2423
2500
|
buyChainInfo,
|
|
2424
2501
|
displayRate,
|
|
2425
2502
|
buyAmount,
|
|
2503
|
+
isExactOutput2,
|
|
2504
|
+
sellAmountBaseUnit,
|
|
2426
2505
|
sellChainNativeAsset,
|
|
2427
2506
|
networkFeeDisplay,
|
|
2428
2507
|
sellUsdValue,
|
|
@@ -2553,6 +2632,10 @@ var useSwapExecution = () => {
|
|
|
2553
2632
|
});
|
|
2554
2633
|
return;
|
|
2555
2634
|
}
|
|
2635
|
+
if (Date.now() >= quote.expiresAt) {
|
|
2636
|
+
actorRef.send({ type: "EXECUTE_ERROR", error: "Quote expired \u2014 please try again" });
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2556
2639
|
const txData = quote.steps[0]?.transactionData;
|
|
2557
2640
|
if (!txData) {
|
|
2558
2641
|
console.error("Quote missing transactionData in steps[0]", quote);
|
|
@@ -2662,15 +2745,27 @@ var useSwapHandlers = ({
|
|
|
2662
2745
|
},
|
|
2663
2746
|
[actorRef]
|
|
2664
2747
|
);
|
|
2748
|
+
const handleBuyAmountChange = useCallback4(
|
|
2749
|
+
(value) => {
|
|
2750
|
+
const { buyAsset } = actorRef.getSnapshot().context;
|
|
2751
|
+
const amountBaseUnit = value ? parseAmount(value, buyAsset.precision) : void 0;
|
|
2752
|
+
actorRef.send({ type: "SET_BUY_AMOUNT", amount: value, amountBaseUnit });
|
|
2753
|
+
},
|
|
2754
|
+
[actorRef]
|
|
2755
|
+
);
|
|
2665
2756
|
const handleToggleSellFiat = useCallback4(
|
|
2666
2757
|
(sellAssetUsdPrice) => {
|
|
2667
2758
|
if (!sellAssetUsdPrice) return;
|
|
2668
2759
|
const snap = actorRef.getSnapshot();
|
|
2669
|
-
const { sellAmount, sellAmountBaseUnit, sellAsset, isSellAmountFiat } = snap.context;
|
|
2760
|
+
const { sellAmount, sellAmountBaseUnit, sellAsset, isSellAmountFiat, buyAmountBaseUnit } = snap.context;
|
|
2670
2761
|
if (isSellAmountFiat) {
|
|
2671
2762
|
actorRef.send({ type: "SET_SELL_FIAT_MODE", isFiat: false });
|
|
2672
2763
|
return;
|
|
2673
2764
|
}
|
|
2765
|
+
if (buyAmountBaseUnit) {
|
|
2766
|
+
actorRef.send({ type: "SET_SELL_FIAT_MODE", isFiat: true });
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2674
2769
|
const fiatValue = cryptoToFiat(sellAmountBaseUnit, sellAssetUsdPrice, sellAsset.precision);
|
|
2675
2770
|
actorRef.send({
|
|
2676
2771
|
type: "SET_SELL_AMOUNT",
|
|
@@ -2746,6 +2841,7 @@ var useSwapHandlers = ({
|
|
|
2746
2841
|
handleSellAssetSelect,
|
|
2747
2842
|
handleBuyAssetSelect,
|
|
2748
2843
|
handleSellAmountChange,
|
|
2844
|
+
handleBuyAmountChange,
|
|
2749
2845
|
handleToggleSellFiat,
|
|
2750
2846
|
handleSelectRate,
|
|
2751
2847
|
handleSlippageChange,
|
|
@@ -2768,9 +2864,12 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2768
2864
|
quotingRef.current = true;
|
|
2769
2865
|
const fetchQuote = async () => {
|
|
2770
2866
|
try {
|
|
2771
|
-
|
|
2867
|
+
const isExactOutput2 = !!context.buyAmountBaseUnit;
|
|
2868
|
+
const rateToUse = context.selectedRate ?? rates?.[0];
|
|
2869
|
+
const sellAmountBaseUnit = isExactOutput2 ? rateToUse?.sellAmountCryptoBaseUnit : context.sellAmountBaseUnit;
|
|
2870
|
+
if (sellAssetBalance?.balance && sellAmountBaseUnit) {
|
|
2772
2871
|
const balanceBigInt = BigInt(sellAssetBalance.balance);
|
|
2773
|
-
const amountBigInt = BigInt(
|
|
2872
|
+
const amountBigInt = BigInt(sellAmountBaseUnit);
|
|
2774
2873
|
if (amountBigInt > balanceBigInt) {
|
|
2775
2874
|
actorRef.send({ type: "QUOTE_ERROR", error: "Insufficient balance" });
|
|
2776
2875
|
return;
|
|
@@ -2782,8 +2881,8 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2782
2881
|
return;
|
|
2783
2882
|
}
|
|
2784
2883
|
const slippageDecimal = (parsedSlippage / 100).toString();
|
|
2785
|
-
const
|
|
2786
|
-
if (!rateToUse || !
|
|
2884
|
+
const amountBaseUnit = isExactOutput2 ? context.buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
2885
|
+
if (!rateToUse || !amountBaseUnit) {
|
|
2787
2886
|
actorRef.send({ type: "QUOTE_ERROR", error: "No rate or amount available" });
|
|
2788
2887
|
return;
|
|
2789
2888
|
}
|
|
@@ -2799,7 +2898,7 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2799
2898
|
const response = await apiClient.getQuote({
|
|
2800
2899
|
sellAssetId: context.sellAsset.assetId,
|
|
2801
2900
|
buyAssetId: context.buyAsset.assetId,
|
|
2802
|
-
sellAmountCryptoBaseUnit:
|
|
2901
|
+
...isExactOutput2 ? { buyAmountCryptoBaseUnit: amountBaseUnit } : { sellAmountCryptoBaseUnit: amountBaseUnit },
|
|
2803
2902
|
sendAddress,
|
|
2804
2903
|
receiveAddress: resolvedReceiveAddress,
|
|
2805
2904
|
swapperName: rateToUse.swapperName,
|
|
@@ -2956,6 +3055,19 @@ var getAddressFormatHint = (chainId) => {
|
|
|
2956
3055
|
}
|
|
2957
3056
|
};
|
|
2958
3057
|
|
|
3058
|
+
// src/utils/receiveAddress.ts
|
|
3059
|
+
var resolveReceiveAddress = ({
|
|
3060
|
+
isLocked,
|
|
3061
|
+
defaultAddress,
|
|
3062
|
+
customAddress,
|
|
3063
|
+
walletAddress,
|
|
3064
|
+
buyChainId
|
|
3065
|
+
}) => {
|
|
3066
|
+
const isValidForBuyChain = (address) => !!address && validateAddress(address, buyChainId).valid;
|
|
3067
|
+
if (isLocked) return isValidForBuyChain(defaultAddress) ? defaultAddress : void 0;
|
|
3068
|
+
return isValidForBuyChain(customAddress) ? customAddress : walletAddress;
|
|
3069
|
+
};
|
|
3070
|
+
|
|
2959
3071
|
// src/components/ApprovalStep.tsx
|
|
2960
3072
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2961
3073
|
var ApprovalStep = () => {
|
|
@@ -3117,9 +3229,8 @@ var getSwapperColor = (swapperName) => {
|
|
|
3117
3229
|
};
|
|
3118
3230
|
|
|
3119
3231
|
// src/components/QuotesModal.tsx
|
|
3120
|
-
import { bnOrZero as bnOrZero2 } from "@shapeshiftoss/utils";
|
|
3121
3232
|
import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo6 } from "react";
|
|
3122
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3233
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3123
3234
|
var useLockBodyScroll = (isLocked) => {
|
|
3124
3235
|
useEffect6(() => {
|
|
3125
3236
|
if (!isLocked) return;
|
|
@@ -3130,13 +3241,6 @@ var useLockBodyScroll = (isLocked) => {
|
|
|
3130
3241
|
};
|
|
3131
3242
|
}, [isLocked]);
|
|
3132
3243
|
};
|
|
3133
|
-
var calculateSavingsPercent = (bestAmount, currentAmount) => {
|
|
3134
|
-
const best = bnOrZero2(bestAmount);
|
|
3135
|
-
const current = bnOrZero2(currentAmount);
|
|
3136
|
-
if (best.isZero()) return null;
|
|
3137
|
-
const diff = best.minus(current).div(best).times(100);
|
|
3138
|
-
return diff.gt(0.1) ? diff.toFixed(2) : null;
|
|
3139
|
-
};
|
|
3140
3244
|
var QuotesModal = ({
|
|
3141
3245
|
isOpen,
|
|
3142
3246
|
onClose,
|
|
@@ -3146,6 +3250,9 @@ var QuotesModal = ({
|
|
|
3146
3250
|
buyAsset,
|
|
3147
3251
|
sellAsset,
|
|
3148
3252
|
sellAmountBaseUnit,
|
|
3253
|
+
buyAmountBaseUnit,
|
|
3254
|
+
isExactOutput: isExactOutput2,
|
|
3255
|
+
sellAssetUsdPrice,
|
|
3149
3256
|
buyAssetUsdPrice
|
|
3150
3257
|
}) => {
|
|
3151
3258
|
useLockBodyScroll(isOpen);
|
|
@@ -3164,15 +3271,11 @@ var QuotesModal = ({
|
|
|
3164
3271
|
},
|
|
3165
3272
|
[onSelectRate, onClose]
|
|
3166
3273
|
);
|
|
3167
|
-
const sortedRates = useMemo6(() =>
|
|
3168
|
-
return [...rates].filter((r) => !r.error && r.buyAmountCryptoBaseUnit !== "0").sort((a, b) => {
|
|
3169
|
-
const aAmount = bnOrZero2(a.buyAmountCryptoBaseUnit);
|
|
3170
|
-
const bAmount = bnOrZero2(b.buyAmountCryptoBaseUnit);
|
|
3171
|
-
return bAmount.minus(aAmount).toNumber();
|
|
3172
|
-
});
|
|
3173
|
-
}, [rates]);
|
|
3274
|
+
const sortedRates = useMemo6(() => sortRatesByValue(rates, isExactOutput2), [rates, isExactOutput2]);
|
|
3174
3275
|
const bestRate = useMemo6(() => sortedRates[0], [sortedRates]);
|
|
3175
|
-
const
|
|
3276
|
+
const bestAmountBaseUnit = bestRate ? getRateAmountBaseUnit(bestRate, isExactOutput2) : "0";
|
|
3277
|
+
const asset = isExactOutput2 ? sellAsset : buyAsset;
|
|
3278
|
+
const usdPrice = isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice;
|
|
3176
3279
|
if (!isOpen) return null;
|
|
3177
3280
|
return (
|
|
3178
3281
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
@@ -3189,14 +3292,20 @@ var QuotesModal = ({
|
|
|
3189
3292
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-modal-header", children: [
|
|
3190
3293
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-header-content", children: [
|
|
3191
3294
|
/* @__PURE__ */ jsx3("h2", { id: "quotes-modal-title", className: "ssw-quotes-modal-title", children: "Select Route" }),
|
|
3192
|
-
/* @__PURE__ */
|
|
3295
|
+
/* @__PURE__ */ jsx3("span", { className: "ssw-quotes-modal-subtitle", children: isExactOutput2 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3296
|
+
sellAsset.symbol,
|
|
3297
|
+
" \u2192 ",
|
|
3298
|
+
formatAmount(buyAmountBaseUnit, buyAsset.precision),
|
|
3299
|
+
" ",
|
|
3300
|
+
buyAsset.symbol
|
|
3301
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3193
3302
|
formatAmount(sellAmountBaseUnit, sellAsset.precision),
|
|
3194
3303
|
" ",
|
|
3195
3304
|
sellAsset.symbol,
|
|
3196
3305
|
" \u2192",
|
|
3197
3306
|
" ",
|
|
3198
3307
|
buyAsset.symbol
|
|
3199
|
-
] })
|
|
3308
|
+
] }) })
|
|
3200
3309
|
] }),
|
|
3201
3310
|
/* @__PURE__ */ jsx3("button", { className: "ssw-quotes-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx3(
|
|
3202
3311
|
"svg",
|
|
@@ -3212,15 +3321,15 @@ var QuotesModal = ({
|
|
|
3212
3321
|
) })
|
|
3213
3322
|
] }),
|
|
3214
3323
|
/* @__PURE__ */ jsx3("div", { className: "ssw-quotes-modal-list", children: sortedRates.map((rate, index) => {
|
|
3215
|
-
const
|
|
3324
|
+
const amountBaseUnit = getRateAmountBaseUnit(rate, isExactOutput2);
|
|
3216
3325
|
const estimatedTime = rate.estimatedExecutionTimeMs;
|
|
3217
3326
|
const isBest = index === 0;
|
|
3218
3327
|
const isSelected = selectedRate?.id === rate.id;
|
|
3219
3328
|
const swapperIcon = getSwapperIcon(rate.swapperName);
|
|
3220
3329
|
const swapperColor = getSwapperColor(rate.swapperName);
|
|
3221
|
-
const
|
|
3222
|
-
const usdValue = formatUsdValue(
|
|
3223
|
-
const
|
|
3330
|
+
const formattedAmount = formatAmount(amountBaseUnit, asset.precision);
|
|
3331
|
+
const usdValue = formatUsdValue(amountBaseUnit, asset.precision, usdPrice);
|
|
3332
|
+
const diffPercent = isBest ? null : getRateDiffPercent(bestAmountBaseUnit, amountBaseUnit, isExactOutput2);
|
|
3224
3333
|
const estimatedSeconds = estimatedTime ? Math.round(estimatedTime / 1e3) : 0;
|
|
3225
3334
|
const hasTime = estimatedSeconds > 0;
|
|
3226
3335
|
return /* @__PURE__ */ jsxs3(
|
|
@@ -3243,9 +3352,9 @@ var QuotesModal = ({
|
|
|
3243
3352
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-name-row", children: [
|
|
3244
3353
|
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-name", children: rate.swapperName }),
|
|
3245
3354
|
isBest && /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-best", children: "Best" }),
|
|
3246
|
-
|
|
3247
|
-
"-",
|
|
3248
|
-
|
|
3355
|
+
diffPercent && /* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-diff", children: [
|
|
3356
|
+
isExactOutput2 ? "+" : "-",
|
|
3357
|
+
diffPercent,
|
|
3249
3358
|
"%"
|
|
3250
3359
|
] })
|
|
3251
3360
|
] }),
|
|
@@ -3258,9 +3367,9 @@ var QuotesModal = ({
|
|
|
3258
3367
|
] }),
|
|
3259
3368
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-right", children: [
|
|
3260
3369
|
/* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-amount", children: [
|
|
3261
|
-
|
|
3370
|
+
formattedAmount,
|
|
3262
3371
|
" ",
|
|
3263
|
-
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-symbol", children:
|
|
3372
|
+
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-symbol", children: asset.symbol })
|
|
3264
3373
|
] }),
|
|
3265
3374
|
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-usd", children: usdValue })
|
|
3266
3375
|
] })
|
|
@@ -3276,7 +3385,7 @@ var QuotesModal = ({
|
|
|
3276
3385
|
};
|
|
3277
3386
|
|
|
3278
3387
|
// src/components/QuoteSelector.tsx
|
|
3279
|
-
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3388
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3280
3389
|
var QuoteSelector = ({
|
|
3281
3390
|
rates,
|
|
3282
3391
|
selectedRate,
|
|
@@ -3284,7 +3393,10 @@ var QuoteSelector = ({
|
|
|
3284
3393
|
buyAsset,
|
|
3285
3394
|
sellAsset,
|
|
3286
3395
|
sellAmountBaseUnit,
|
|
3396
|
+
buyAmountBaseUnit,
|
|
3397
|
+
isExactOutput: isExactOutput2,
|
|
3287
3398
|
isLoading,
|
|
3399
|
+
sellAssetUsdPrice,
|
|
3288
3400
|
buyAssetUsdPrice
|
|
3289
3401
|
}) => {
|
|
3290
3402
|
const [isModalOpen, setIsModalOpen] = useState3(false);
|
|
@@ -3314,12 +3426,17 @@ var QuoteSelector = ({
|
|
|
3314
3426
|
return null;
|
|
3315
3427
|
}
|
|
3316
3428
|
const displayRate = selectedRate ?? bestRate;
|
|
3317
|
-
const buyAmount = displayRate.buyAmountCryptoBaseUnit ?? "0";
|
|
3318
3429
|
const swapperIcon = getSwapperIcon(displayRate.swapperName);
|
|
3319
3430
|
const swapperColor = getSwapperColor(displayRate.swapperName);
|
|
3320
|
-
const
|
|
3321
|
-
const
|
|
3322
|
-
|
|
3431
|
+
const asset = isExactOutput2 ? sellAsset : buyAsset;
|
|
3432
|
+
const amountBaseUnit = getRateAmountBaseUnit(displayRate, isExactOutput2);
|
|
3433
|
+
const formattedAmount = formatAmount(amountBaseUnit, asset.precision);
|
|
3434
|
+
const usdValue = formatUsdValue(
|
|
3435
|
+
amountBaseUnit,
|
|
3436
|
+
asset.precision,
|
|
3437
|
+
isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice
|
|
3438
|
+
);
|
|
3439
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3323
3440
|
/* @__PURE__ */ jsxs4("button", { className: "ssw-quote-selector", onClick: handleOpenModal, type: "button", children: [
|
|
3324
3441
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-left", children: [
|
|
3325
3442
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-provider", children: [
|
|
@@ -3345,8 +3462,8 @@ var QuoteSelector = ({
|
|
|
3345
3462
|
] }),
|
|
3346
3463
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-right", children: [
|
|
3347
3464
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-amount-row", children: [
|
|
3348
|
-
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-amount", children:
|
|
3349
|
-
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-symbol", children:
|
|
3465
|
+
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-amount", children: formattedAmount }),
|
|
3466
|
+
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-symbol", children: asset.symbol })
|
|
3350
3467
|
] }),
|
|
3351
3468
|
alternativeRatesCount > 0 && /* @__PURE__ */ jsxs4("span", { className: "ssw-quote-more", children: [
|
|
3352
3469
|
"+",
|
|
@@ -3378,6 +3495,9 @@ var QuoteSelector = ({
|
|
|
3378
3495
|
buyAsset,
|
|
3379
3496
|
sellAsset,
|
|
3380
3497
|
sellAmountBaseUnit,
|
|
3498
|
+
buyAmountBaseUnit,
|
|
3499
|
+
isExactOutput: isExactOutput2,
|
|
3500
|
+
sellAssetUsdPrice,
|
|
3381
3501
|
buyAssetUsdPrice
|
|
3382
3502
|
}
|
|
3383
3503
|
)
|
|
@@ -3386,11 +3506,12 @@ var QuoteSelector = ({
|
|
|
3386
3506
|
|
|
3387
3507
|
// src/components/ReceiveAddressRow.tsx
|
|
3388
3508
|
import { useCallback as useCallback7, useLayoutEffect, useMemo as useMemo8, useRef as useRef5, useState as useState4 } from "react";
|
|
3389
|
-
import { Fragment as
|
|
3509
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3390
3510
|
var ReceiveAddressRow = ({
|
|
3391
3511
|
receiveAddress,
|
|
3392
3512
|
isResolving,
|
|
3393
3513
|
buyChainId,
|
|
3514
|
+
isLocked,
|
|
3394
3515
|
onSetCustomReceiveAddress
|
|
3395
3516
|
}) => {
|
|
3396
3517
|
const [isEditing, setIsEditing] = useState4(false);
|
|
@@ -3398,7 +3519,7 @@ var ReceiveAddressRow = ({
|
|
|
3398
3519
|
const [hasInteracted, setHasInteracted] = useState4(false);
|
|
3399
3520
|
const inputRef = useRef5(null);
|
|
3400
3521
|
const needsAddress = !receiveAddress;
|
|
3401
|
-
const showInput = needsAddress && !isResolving || isEditing;
|
|
3522
|
+
const showInput = !isLocked && (needsAddress && !isResolving || isEditing);
|
|
3402
3523
|
const showAttention = needsAddress && !isResolving;
|
|
3403
3524
|
useLayoutEffect(() => {
|
|
3404
3525
|
if (isEditing) inputRef.current?.focus();
|
|
@@ -3418,6 +3539,7 @@ var ReceiveAddressRow = ({
|
|
|
3418
3539
|
[trimmedDraft, buyChainId]
|
|
3419
3540
|
);
|
|
3420
3541
|
const formatHint = useMemo8(() => getAddressFormatHint(buyChainId), [buyChainId]);
|
|
3542
|
+
const chainName = useMemo8(() => getChainName(buyChainId), [buyChainId]);
|
|
3421
3543
|
const startEditing = useCallback7(() => {
|
|
3422
3544
|
setDraft(receiveAddress ?? "");
|
|
3423
3545
|
setHasInteracted(false);
|
|
@@ -3441,36 +3563,48 @@ var ReceiveAddressRow = ({
|
|
|
3441
3563
|
}, [onSetCustomReceiveAddress]);
|
|
3442
3564
|
const showReset = !!draft || isEditing;
|
|
3443
3565
|
if (!showInput) {
|
|
3444
|
-
return /* @__PURE__ */ jsxs5(
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
"
|
|
3450
|
-
{
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3566
|
+
return /* @__PURE__ */ jsxs5(
|
|
3567
|
+
"div",
|
|
3568
|
+
{
|
|
3569
|
+
className: `ssw-receive-row ssw-receive-row-resolved${showAttention ? " ssw-receive-row-invalid" : ""}`,
|
|
3570
|
+
children: [
|
|
3571
|
+
/* @__PURE__ */ jsx5("span", { className: "ssw-receive-label", children: "Receive address" }),
|
|
3572
|
+
/* @__PURE__ */ jsx5("div", { className: "ssw-receive-resolved-value", children: isResolving ? /* @__PURE__ */ jsx5("span", { className: "ssw-balance-skeleton" }) : showAttention ? (
|
|
3573
|
+
// Locked only - an unlocked row with no address shows the input instead
|
|
3574
|
+
/* @__PURE__ */ jsxs5("span", { className: "ssw-receive-error", children: [
|
|
3575
|
+
"Not valid for ",
|
|
3576
|
+
chainName
|
|
3577
|
+
] })
|
|
3578
|
+
) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3579
|
+
/* @__PURE__ */ jsx5("span", { className: "ssw-receive-address", children: truncateAddress(receiveAddress ?? "", 6) }),
|
|
3580
|
+
!isLocked && /* @__PURE__ */ jsx5(
|
|
3581
|
+
"button",
|
|
3457
3582
|
{
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3583
|
+
className: "ssw-receive-edit-btn",
|
|
3584
|
+
onClick: startEditing,
|
|
3585
|
+
type: "button",
|
|
3586
|
+
"aria-label": "Edit receive address",
|
|
3587
|
+
children: /* @__PURE__ */ jsxs5(
|
|
3588
|
+
"svg",
|
|
3589
|
+
{
|
|
3590
|
+
width: "14",
|
|
3591
|
+
height: "14",
|
|
3592
|
+
viewBox: "0 0 24 24",
|
|
3593
|
+
fill: "none",
|
|
3594
|
+
stroke: "currentColor",
|
|
3595
|
+
strokeWidth: "2",
|
|
3596
|
+
children: [
|
|
3597
|
+
/* @__PURE__ */ jsx5("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
|
|
3598
|
+
/* @__PURE__ */ jsx5("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
3599
|
+
]
|
|
3600
|
+
}
|
|
3601
|
+
)
|
|
3468
3602
|
}
|
|
3469
3603
|
)
|
|
3470
|
-
}
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3604
|
+
] }) })
|
|
3605
|
+
]
|
|
3606
|
+
}
|
|
3607
|
+
);
|
|
3474
3608
|
}
|
|
3475
3609
|
return /* @__PURE__ */ jsxs5(
|
|
3476
3610
|
"div",
|
|
@@ -3554,39 +3688,23 @@ var ReceiveAddressRow = ({
|
|
|
3554
3688
|
};
|
|
3555
3689
|
|
|
3556
3690
|
// src/components/InputStep.tsx
|
|
3557
|
-
import { Fragment as
|
|
3691
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3558
3692
|
var InputStep = ({
|
|
3559
3693
|
displayValues,
|
|
3560
3694
|
onOpenTokenModal,
|
|
3561
3695
|
onSellAmountChange,
|
|
3696
|
+
onBuyAmountChange,
|
|
3562
3697
|
onToggleSellFiat,
|
|
3563
3698
|
onSwapTokens,
|
|
3564
3699
|
onSelectRate,
|
|
3565
3700
|
onButtonClick,
|
|
3566
3701
|
isBuyAssetLocked,
|
|
3702
|
+
isBuyAmountLocked,
|
|
3703
|
+
isReceiveAddressLocked,
|
|
3567
3704
|
allowShapeshiftRedirect
|
|
3568
3705
|
}) => {
|
|
3569
3706
|
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
3570
3707
|
const isQuoting = SwapMachineCtx.useSelector((s) => s.matches("quoting"));
|
|
3571
|
-
const {
|
|
3572
|
-
rates,
|
|
3573
|
-
isLoadingRates,
|
|
3574
|
-
ratesError,
|
|
3575
|
-
sellAssetBalance,
|
|
3576
|
-
buyAssetBalance,
|
|
3577
|
-
isSellBalanceLoading,
|
|
3578
|
-
isBuyBalanceLoading,
|
|
3579
|
-
sellUsdValue,
|
|
3580
|
-
sellAssetUsdPrice,
|
|
3581
|
-
buyUsdValue,
|
|
3582
|
-
sellChainInfo,
|
|
3583
|
-
buyChainInfo,
|
|
3584
|
-
buyAmount,
|
|
3585
|
-
buyAssetUsdPrice,
|
|
3586
|
-
networkFeeDisplay,
|
|
3587
|
-
sellBalanceFiatValue,
|
|
3588
|
-
buyBalanceFiatValue
|
|
3589
|
-
} = displayValues;
|
|
3590
3708
|
const {
|
|
3591
3709
|
sendAddress,
|
|
3592
3710
|
receiveAddress,
|
|
@@ -3596,22 +3714,48 @@ var InputStep = ({
|
|
|
3596
3714
|
bitcoin: bitcoin3,
|
|
3597
3715
|
solana: solana3
|
|
3598
3716
|
} = useSwapWallet();
|
|
3599
|
-
const
|
|
3600
|
-
sellAsset,
|
|
3601
|
-
buyAsset,
|
|
3602
|
-
selectedRate,
|
|
3603
|
-
sellAmount,
|
|
3604
|
-
sellAmountBaseUnit,
|
|
3605
|
-
isSellAmountFiat,
|
|
3606
|
-
sellAmountFiat,
|
|
3607
|
-
isSellAssetEvm,
|
|
3608
|
-
isSellAssetUtxo,
|
|
3609
|
-
isSellAssetSolana
|
|
3610
|
-
} = context;
|
|
3611
|
-
const buyChainId = buyAsset.chainId;
|
|
3717
|
+
const buyChainId = context.buyAsset.chainId;
|
|
3612
3718
|
const hasAnyWalletAddress = !!evm.address || !!bitcoin3.address || !!solana3.address;
|
|
3613
3719
|
const hasActiveWallet = !!receiveAddress || hasAnyWalletAddress || isReceiveAddressResolving;
|
|
3614
|
-
const isUnsupportedChain = !isSellAssetEvm && !isSellAssetUtxo && !isSellAssetSolana;
|
|
3720
|
+
const isUnsupportedChain = !context.isSellAssetEvm && !context.isSellAssetUtxo && !context.isSellAssetSolana;
|
|
3721
|
+
const amountBaseUnit = displayValues.isExactOutput ? context.buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
3722
|
+
const isSellAmountReadOnly = displayValues.isExactOutput && isBuyAmountLocked;
|
|
3723
|
+
const isSellAmountPending = displayValues.isExactOutput && displayValues.isLoadingRates;
|
|
3724
|
+
const isBuyAmountPending = !displayValues.isExactOutput && displayValues.isLoadingRates;
|
|
3725
|
+
const sellAmountCrypto = useMemo9(
|
|
3726
|
+
() => displayValues.sellAmountBaseUnit ? formatAmount(displayValues.sellAmountBaseUnit, context.sellAsset.precision, 6) : "",
|
|
3727
|
+
[displayValues.sellAmountBaseUnit, context.sellAsset.precision]
|
|
3728
|
+
);
|
|
3729
|
+
const buyAmountValue = useMemo9(() => {
|
|
3730
|
+
if (displayValues.isExactOutput) return context.buyAmount;
|
|
3731
|
+
if (!displayValues.buyAmount) return "";
|
|
3732
|
+
return formatAmount(displayValues.buyAmount, context.buyAsset.precision);
|
|
3733
|
+
}, [
|
|
3734
|
+
displayValues.isExactOutput,
|
|
3735
|
+
displayValues.buyAmount,
|
|
3736
|
+
context.buyAmount,
|
|
3737
|
+
context.buyAsset.precision
|
|
3738
|
+
]);
|
|
3739
|
+
const sellAmountValue = useMemo9(() => {
|
|
3740
|
+
if (!displayValues.isExactOutput) {
|
|
3741
|
+
return context.isSellAmountFiat ? context.sellAmountFiat : context.sellAmount;
|
|
3742
|
+
}
|
|
3743
|
+
if (!context.isSellAmountFiat) return sellAmountCrypto;
|
|
3744
|
+
return cryptoToFiat(
|
|
3745
|
+
displayValues.sellAmountBaseUnit,
|
|
3746
|
+
displayValues.sellAssetUsdPrice ?? "",
|
|
3747
|
+
context.sellAsset.precision
|
|
3748
|
+
);
|
|
3749
|
+
}, [
|
|
3750
|
+
displayValues.isExactOutput,
|
|
3751
|
+
displayValues.sellAmountBaseUnit,
|
|
3752
|
+
displayValues.sellAssetUsdPrice,
|
|
3753
|
+
context.isSellAmountFiat,
|
|
3754
|
+
context.sellAmountFiat,
|
|
3755
|
+
context.sellAmount,
|
|
3756
|
+
context.sellAsset.precision,
|
|
3757
|
+
sellAmountCrypto
|
|
3758
|
+
]);
|
|
3615
3759
|
const { text: buttonText, disabled: isButtonDisabled } = useMemo9(() => {
|
|
3616
3760
|
if (isUnsupportedChain) {
|
|
3617
3761
|
if (!allowShapeshiftRedirect) return { text: "Route not supported", disabled: true };
|
|
@@ -3619,39 +3763,43 @@ var InputStep = ({
|
|
|
3619
3763
|
}
|
|
3620
3764
|
if (!sendAddress) return { text: "Connect Wallet", disabled: false };
|
|
3621
3765
|
if (!receiveAddress) return { text: "Enter receive address", disabled: true };
|
|
3622
|
-
|
|
3623
|
-
if (
|
|
3624
|
-
if (
|
|
3625
|
-
if (
|
|
3766
|
+
const drivingAmount = displayValues.isExactOutput ? context.buyAmountBaseUnit : context.sellAmount;
|
|
3767
|
+
if (!drivingAmount || drivingAmount === "0") return { text: "Enter an amount", disabled: true };
|
|
3768
|
+
if (displayValues.isLoadingRates) return { text: "Finding rates...", disabled: true };
|
|
3769
|
+
if (displayValues.ratesError) return { text: "No routes available", disabled: true };
|
|
3770
|
+
if (!displayValues.rates?.length) return { text: "No routes found", disabled: true };
|
|
3626
3771
|
return { text: "Swap", disabled: false };
|
|
3627
3772
|
}, [
|
|
3628
3773
|
isUnsupportedChain,
|
|
3629
3774
|
allowShapeshiftRedirect,
|
|
3630
3775
|
sendAddress,
|
|
3631
3776
|
receiveAddress,
|
|
3632
|
-
sellAmount,
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3777
|
+
context.sellAmount,
|
|
3778
|
+
displayValues.isExactOutput,
|
|
3779
|
+
context.buyAmountBaseUnit,
|
|
3780
|
+
displayValues.isLoadingRates,
|
|
3781
|
+
displayValues.ratesError,
|
|
3782
|
+
displayValues.rates
|
|
3636
3783
|
]);
|
|
3637
|
-
return /* @__PURE__ */ jsxs6(
|
|
3784
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3638
3785
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-swap-container", children: [
|
|
3639
3786
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-section ssw-sell", children: [
|
|
3640
3787
|
/* @__PURE__ */ jsx6("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx6("span", { className: "ssw-section-label", children: "Sell" }) }),
|
|
3641
3788
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-input-row", children: [
|
|
3642
|
-
isSellAmountFiat && /* @__PURE__ */ jsx6("span", { className: "ssw-fiat-prefix", children: "$" }),
|
|
3789
|
+
context.isSellAmountFiat && /* @__PURE__ */ jsx6("span", { className: "ssw-fiat-prefix", children: "$" }),
|
|
3643
3790
|
/* @__PURE__ */ jsx6(
|
|
3644
3791
|
"input",
|
|
3645
3792
|
{
|
|
3646
3793
|
type: "text",
|
|
3647
|
-
className: "ssw-amount-input"
|
|
3648
|
-
placeholder: "0",
|
|
3649
|
-
value:
|
|
3794
|
+
className: `ssw-amount-input${isSellAmountReadOnly ? " ssw-amount-input-locked" : ""}${isSellAmountPending ? " ssw-amount-input-pending" : ""}`,
|
|
3795
|
+
placeholder: isSellAmountPending ? "..." : "0",
|
|
3796
|
+
value: sellAmountValue,
|
|
3797
|
+
readOnly: isSellAmountReadOnly,
|
|
3650
3798
|
onChange: (e) => {
|
|
3651
3799
|
const raw = e.target.value.replace(/[^0-9.]/g, "");
|
|
3652
3800
|
const parts = raw.split(".");
|
|
3653
3801
|
const sanitized = parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : raw;
|
|
3654
|
-
onSellAmountChange(sanitized, sellAssetUsdPrice);
|
|
3802
|
+
onSellAmountChange(sanitized, displayValues.sellAssetUsdPrice);
|
|
3655
3803
|
}
|
|
3656
3804
|
}
|
|
3657
3805
|
),
|
|
@@ -3662,10 +3810,17 @@ var InputStep = ({
|
|
|
3662
3810
|
onClick: () => onOpenTokenModal("sell"),
|
|
3663
3811
|
type: "button",
|
|
3664
3812
|
children: [
|
|
3665
|
-
sellAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3813
|
+
context.sellAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3814
|
+
"img",
|
|
3815
|
+
{
|
|
3816
|
+
src: context.sellAsset.icon,
|
|
3817
|
+
alt: context.sellAsset.symbol,
|
|
3818
|
+
className: "ssw-token-icon"
|
|
3819
|
+
}
|
|
3820
|
+
) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.sellAsset.symbol.charAt(0) }),
|
|
3666
3821
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
|
|
3667
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: sellAsset.symbol }),
|
|
3668
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: sellChainInfo?.name ?? sellAsset.networkName ?? sellAsset.name })
|
|
3822
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.sellAsset.symbol }),
|
|
3823
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.sellChainInfo?.name ?? context.sellAsset.networkName ?? context.sellAsset.name })
|
|
3669
3824
|
] }),
|
|
3670
3825
|
/* @__PURE__ */ jsx6(
|
|
3671
3826
|
"svg",
|
|
@@ -3684,14 +3839,14 @@ var InputStep = ({
|
|
|
3684
3839
|
)
|
|
3685
3840
|
] }),
|
|
3686
3841
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
|
|
3687
|
-
sellAssetUsdPrice ? /* @__PURE__ */ jsxs6(
|
|
3842
|
+
!displayValues.sellAssetUsdPrice ? /* @__PURE__ */ jsx6("span", { className: "ssw-usd-value" }) : /* @__PURE__ */ jsxs6(
|
|
3688
3843
|
"button",
|
|
3689
3844
|
{
|
|
3690
3845
|
type: "button",
|
|
3691
3846
|
className: "ssw-usd-value ssw-usd-value-toggle",
|
|
3692
|
-
onClick: () => onToggleSellFiat(sellAssetUsdPrice),
|
|
3847
|
+
onClick: () => onToggleSellFiat(displayValues.sellAssetUsdPrice),
|
|
3693
3848
|
children: [
|
|
3694
|
-
/* @__PURE__ */ jsx6("span", { children: isSellAmountFiat ? `\u2248 ${
|
|
3849
|
+
/* @__PURE__ */ jsx6("span", { children: context.isSellAmountFiat ? `\u2248 ${sellAmountCrypto || "0"} ${context.sellAsset.symbol}` : displayValues.sellUsdValue }),
|
|
3695
3850
|
/* @__PURE__ */ jsx6(
|
|
3696
3851
|
"svg",
|
|
3697
3852
|
{
|
|
@@ -3707,13 +3862,14 @@ var InputStep = ({
|
|
|
3707
3862
|
)
|
|
3708
3863
|
]
|
|
3709
3864
|
}
|
|
3710
|
-
)
|
|
3711
|
-
hasAnyWalletAddress && (isSellBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : sellAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3865
|
+
),
|
|
3866
|
+
hasAnyWalletAddress && (displayValues.isSellBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.sellAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3712
3867
|
"Balance: ",
|
|
3713
|
-
sellAssetBalance.balanceFormatted,
|
|
3714
|
-
sellBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3715
|
-
"
|
|
3716
|
-
|
|
3868
|
+
displayValues.sellAssetBalance.balanceFormatted,
|
|
3869
|
+
displayValues.sellBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3870
|
+
" ",
|
|
3871
|
+
"(",
|
|
3872
|
+
displayValues.sellBalanceFiatValue,
|
|
3717
3873
|
")"
|
|
3718
3874
|
] })
|
|
3719
3875
|
] }) : null)
|
|
@@ -3747,10 +3903,15 @@ var InputStep = ({
|
|
|
3747
3903
|
"input",
|
|
3748
3904
|
{
|
|
3749
3905
|
type: "text",
|
|
3750
|
-
className: "ssw-amount-input"
|
|
3751
|
-
placeholder: "0",
|
|
3752
|
-
value:
|
|
3753
|
-
readOnly:
|
|
3906
|
+
className: `ssw-amount-input${isBuyAmountLocked ? " ssw-amount-input-locked" : ""}${isBuyAmountPending ? " ssw-amount-input-pending" : ""}`,
|
|
3907
|
+
placeholder: isBuyAmountPending ? "..." : "0",
|
|
3908
|
+
value: buyAmountValue,
|
|
3909
|
+
readOnly: isBuyAmountLocked,
|
|
3910
|
+
onChange: (e) => {
|
|
3911
|
+
const raw = e.target.value.replace(/[^0-9.]/g, "");
|
|
3912
|
+
const parts = raw.split(".");
|
|
3913
|
+
onBuyAmountChange(parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : raw);
|
|
3914
|
+
}
|
|
3754
3915
|
}
|
|
3755
3916
|
),
|
|
3756
3917
|
/* @__PURE__ */ jsxs6(
|
|
@@ -3761,10 +3922,17 @@ var InputStep = ({
|
|
|
3761
3922
|
disabled: isBuyAssetLocked,
|
|
3762
3923
|
type: "button",
|
|
3763
3924
|
children: [
|
|
3764
|
-
buyAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3925
|
+
context.buyAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3926
|
+
"img",
|
|
3927
|
+
{
|
|
3928
|
+
src: context.buyAsset.icon,
|
|
3929
|
+
alt: context.buyAsset.symbol,
|
|
3930
|
+
className: "ssw-token-icon"
|
|
3931
|
+
}
|
|
3932
|
+
) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.buyAsset.symbol.charAt(0) }),
|
|
3765
3933
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
|
|
3766
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: buyAsset.symbol }),
|
|
3767
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: buyChainInfo?.name ?? buyAsset.networkName ?? buyAsset.name })
|
|
3934
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.buyAsset.symbol }),
|
|
3935
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.buyChainInfo?.name ?? context.buyAsset.networkName ?? context.buyAsset.name })
|
|
3768
3936
|
] }),
|
|
3769
3937
|
!isBuyAssetLocked && /* @__PURE__ */ jsx6(
|
|
3770
3938
|
"svg",
|
|
@@ -3783,13 +3951,13 @@ var InputStep = ({
|
|
|
3783
3951
|
)
|
|
3784
3952
|
] }),
|
|
3785
3953
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
|
|
3786
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-usd-value", children: buyUsdValue }),
|
|
3787
|
-
hasAnyWalletAddress && (isBuyBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : buyAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3954
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-usd-value", children: displayValues.buyUsdValue }),
|
|
3955
|
+
hasAnyWalletAddress && (displayValues.isBuyBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.buyAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3788
3956
|
"Balance: ",
|
|
3789
|
-
buyAssetBalance.balanceFormatted,
|
|
3790
|
-
buyBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3957
|
+
displayValues.buyAssetBalance.balanceFormatted,
|
|
3958
|
+
displayValues.buyBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3791
3959
|
" (",
|
|
3792
|
-
buyBalanceFiatValue,
|
|
3960
|
+
displayValues.buyBalanceFiatValue,
|
|
3793
3961
|
")"
|
|
3794
3962
|
] })
|
|
3795
3963
|
] }) : null)
|
|
@@ -3801,26 +3969,30 @@ var InputStep = ({
|
|
|
3801
3969
|
receiveAddress,
|
|
3802
3970
|
isResolving: isReceiveAddressResolving,
|
|
3803
3971
|
buyChainId,
|
|
3972
|
+
isLocked: isReceiveAddressLocked,
|
|
3804
3973
|
onSetCustomReceiveAddress: setCustomReceiveAddress
|
|
3805
3974
|
}
|
|
3806
3975
|
)
|
|
3807
3976
|
] }),
|
|
3808
|
-
|
|
3977
|
+
amountBaseUnit && amountBaseUnit !== "0" && (displayValues.rates?.length || displayValues.isLoadingRates) && /* @__PURE__ */ jsx6("div", { className: "ssw-quotes", children: /* @__PURE__ */ jsx6(
|
|
3809
3978
|
QuoteSelector,
|
|
3810
3979
|
{
|
|
3811
|
-
rates: rates ?? [],
|
|
3812
|
-
selectedRate,
|
|
3980
|
+
rates: displayValues.rates ?? [],
|
|
3981
|
+
selectedRate: context.selectedRate,
|
|
3813
3982
|
onSelectRate,
|
|
3814
|
-
buyAsset,
|
|
3815
|
-
sellAsset,
|
|
3816
|
-
sellAmountBaseUnit,
|
|
3817
|
-
|
|
3818
|
-
|
|
3983
|
+
buyAsset: context.buyAsset,
|
|
3984
|
+
sellAsset: context.sellAsset,
|
|
3985
|
+
sellAmountBaseUnit: displayValues.sellAmountBaseUnit ?? "0",
|
|
3986
|
+
buyAmountBaseUnit: context.buyAmountBaseUnit ?? "0",
|
|
3987
|
+
isExactOutput: displayValues.isExactOutput,
|
|
3988
|
+
isLoading: displayValues.isLoadingRates,
|
|
3989
|
+
sellAssetUsdPrice: displayValues.sellAssetUsdPrice,
|
|
3990
|
+
buyAssetUsdPrice: displayValues.buyAssetUsdPrice
|
|
3819
3991
|
}
|
|
3820
3992
|
) }),
|
|
3821
|
-
networkFeeDisplay && /* @__PURE__ */ jsxs6("div", { className: "ssw-network-fee", children: [
|
|
3993
|
+
displayValues.networkFeeDisplay && /* @__PURE__ */ jsxs6("div", { className: "ssw-network-fee", children: [
|
|
3822
3994
|
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-label", children: "Est. network fee" }),
|
|
3823
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-value", children: networkFeeDisplay })
|
|
3995
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-value", children: displayValues.networkFeeDisplay })
|
|
3824
3996
|
] }),
|
|
3825
3997
|
/* @__PURE__ */ jsx6(
|
|
3826
3998
|
"button",
|
|
@@ -3830,7 +4002,7 @@ var InputStep = ({
|
|
|
3830
4002
|
onClick: onButtonClick,
|
|
3831
4003
|
type: "button",
|
|
3832
4004
|
style: isQuoting ? { opacity: 0.7 } : void 0,
|
|
3833
|
-
children: isQuoting ? /* @__PURE__ */ jsxs6(
|
|
4005
|
+
children: isQuoting ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3834
4006
|
/* @__PURE__ */ jsxs6(
|
|
3835
4007
|
"svg",
|
|
3836
4008
|
{
|
|
@@ -4017,7 +4189,7 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
|
|
|
4017
4189
|
|
|
4018
4190
|
// src/components/StatusStep.tsx
|
|
4019
4191
|
import { useMemo as useMemo10 } from "react";
|
|
4020
|
-
import { Fragment as
|
|
4192
|
+
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4021
4193
|
var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "ssw-step-explorer-link", children: [
|
|
4022
4194
|
"View on Explorer",
|
|
4023
4195
|
/* @__PURE__ */ jsx8(
|
|
@@ -4033,7 +4205,7 @@ var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target:
|
|
|
4033
4205
|
}
|
|
4034
4206
|
)
|
|
4035
4207
|
] });
|
|
4036
|
-
var StatusStep = () => {
|
|
4208
|
+
var StatusStep = ({ isPayment }) => {
|
|
4037
4209
|
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
4038
4210
|
const isPolling = SwapMachineCtx.useSelector((s) => s.matches("polling_status"));
|
|
4039
4211
|
const isComplete = SwapMachineCtx.useSelector((s) => s.matches("complete"));
|
|
@@ -4051,7 +4223,7 @@ var StatusStep = () => {
|
|
|
4051
4223
|
[error]
|
|
4052
4224
|
);
|
|
4053
4225
|
return /* @__PURE__ */ jsxs8("div", { className: "ssw-step-screen", children: [
|
|
4054
|
-
isPolling && /* @__PURE__ */ jsxs8(
|
|
4226
|
+
isPolling && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4055
4227
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs8(
|
|
4056
4228
|
"svg",
|
|
4057
4229
|
{
|
|
@@ -4072,7 +4244,7 @@ var StatusStep = () => {
|
|
|
4072
4244
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-subtitle", children: "Your swap is being processed\u2026" }),
|
|
4073
4245
|
explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl })
|
|
4074
4246
|
] }),
|
|
4075
|
-
isComplete && /* @__PURE__ */ jsxs8(
|
|
4247
|
+
isComplete && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4076
4248
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-success", children: /* @__PURE__ */ jsx8(
|
|
4077
4249
|
"svg",
|
|
4078
4250
|
{
|
|
@@ -4093,7 +4265,7 @@ var StatusStep = () => {
|
|
|
4093
4265
|
buyAsset.symbol
|
|
4094
4266
|
] }),
|
|
4095
4267
|
explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl }),
|
|
4096
|
-
/* @__PURE__ */ jsx8("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx8(
|
|
4268
|
+
!isPayment && /* @__PURE__ */ jsx8("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx8(
|
|
4097
4269
|
"button",
|
|
4098
4270
|
{
|
|
4099
4271
|
className: "ssw-action-btn",
|
|
@@ -4103,7 +4275,7 @@ var StatusStep = () => {
|
|
|
4103
4275
|
}
|
|
4104
4276
|
) })
|
|
4105
4277
|
] }),
|
|
4106
|
-
isError && /* @__PURE__ */ jsxs8(
|
|
4278
|
+
isError && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4107
4279
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-error", children: /* @__PURE__ */ jsxs8(
|
|
4108
4280
|
"svg",
|
|
4109
4281
|
{
|
|
@@ -4146,10 +4318,10 @@ var StatusStep = () => {
|
|
|
4146
4318
|
};
|
|
4147
4319
|
|
|
4148
4320
|
// src/components/TokenSelectModal.tsx
|
|
4149
|
-
import { bnOrZero as
|
|
4321
|
+
import { bnOrZero as bnOrZero2 } from "@shapeshiftoss/utils";
|
|
4150
4322
|
import { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo11, useRef as useRef6, useState as useState6 } from "react";
|
|
4151
4323
|
import { Virtuoso } from "react-virtuoso";
|
|
4152
|
-
import { Fragment as
|
|
4324
|
+
import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4153
4325
|
var VISIBLE_BUFFER = 10;
|
|
4154
4326
|
var useLockBodyScroll3 = (isLocked) => {
|
|
4155
4327
|
useEffect8(() => {
|
|
@@ -4330,7 +4502,7 @@ var TokenSelectModal = ({
|
|
|
4330
4502
|
const balance = balances[asset.assetId];
|
|
4331
4503
|
if (balance && balance.balance !== "0") {
|
|
4332
4504
|
const price = marketData?.[asset.assetId]?.price;
|
|
4333
|
-
const fiatValue = price ?
|
|
4505
|
+
const fiatValue = price ? bnOrZero2(balance.balance).div(bnOrZero2(10).pow(asset.precision)).times(bnOrZero2(price)).toNumber() : 0;
|
|
4334
4506
|
withBalance.push({ asset, fiatValue });
|
|
4335
4507
|
} else {
|
|
4336
4508
|
withoutBalance.push(asset);
|
|
@@ -4534,10 +4706,10 @@ var TokenSelectModal = ({
|
|
|
4534
4706
|
/* @__PURE__ */ jsx9("span", { className: "ssw-token-symbol", children: asset.symbol }),
|
|
4535
4707
|
/* @__PURE__ */ jsx9("span", { className: "ssw-token-name", children: chainInfo?.name ?? asset.networkName ?? asset.name })
|
|
4536
4708
|
] }),
|
|
4537
|
-
/* @__PURE__ */ jsx9("div", { className: "ssw-token-right", children: (evmAddress || bitcoinAddress || solanaAddress) && (loadingAssetIds.has(asset.assetId) ? /* @__PURE__ */ jsx9("span", { className: "ssw-token-balance-skeleton" }) : balance && balance.balance !== "0" ? /* @__PURE__ */ jsxs9(
|
|
4709
|
+
/* @__PURE__ */ jsx9("div", { className: "ssw-token-right", children: (evmAddress || bitcoinAddress || solanaAddress) && (loadingAssetIds.has(asset.assetId) ? /* @__PURE__ */ jsx9("span", { className: "ssw-token-balance-skeleton" }) : balance && balance.balance !== "0" ? /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
4538
4710
|
marketData?.[asset.assetId]?.price && /* @__PURE__ */ jsxs9("span", { className: "ssw-token-fiat-value", children: [
|
|
4539
4711
|
"$",
|
|
4540
|
-
|
|
4712
|
+
bnOrZero2(balance.balance).div(bnOrZero2(10).pow(asset.precision)).times(bnOrZero2(marketData[asset.assetId].price)).toNumber().toLocaleString(void 0, {
|
|
4541
4713
|
minimumFractionDigits: 2,
|
|
4542
4714
|
maximumFractionDigits: 2
|
|
4543
4715
|
})
|
|
@@ -4586,7 +4758,8 @@ import { createAppKit, modal } from "@reown/appkit/react";
|
|
|
4586
4758
|
import { BitcoinAdapter } from "@reown/appkit-adapter-bitcoin";
|
|
4587
4759
|
import { SolanaAdapter } from "@reown/appkit-adapter-solana/react";
|
|
4588
4760
|
import { WagmiAdapter } from "@reown/appkit-adapter-wagmi";
|
|
4589
|
-
import { PhantomWalletAdapter
|
|
4761
|
+
import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom";
|
|
4762
|
+
import { SolflareWalletAdapter } from "@solana/wallet-adapter-solflare";
|
|
4590
4763
|
var EVM_NETWORKS = [
|
|
4591
4764
|
mainnet3,
|
|
4592
4765
|
polygon3,
|
|
@@ -4679,8 +4852,11 @@ var SwapWidgetContent = ({
|
|
|
4679
4852
|
showPoweredBy,
|
|
4680
4853
|
showConnectButton,
|
|
4681
4854
|
isBuyAssetLocked,
|
|
4855
|
+
isBuyAmountLocked,
|
|
4856
|
+
isReceiveAddressLocked,
|
|
4857
|
+
isPayment,
|
|
4682
4858
|
partnerCode,
|
|
4683
|
-
|
|
4859
|
+
canRedirectToShapeshift,
|
|
4684
4860
|
onSwapSuccess,
|
|
4685
4861
|
onSwapError,
|
|
4686
4862
|
sellFilters,
|
|
@@ -4704,11 +4880,12 @@ var SwapWidgetContent = ({
|
|
|
4704
4880
|
handleSellAssetSelect,
|
|
4705
4881
|
handleBuyAssetSelect,
|
|
4706
4882
|
handleSellAmountChange,
|
|
4883
|
+
handleBuyAmountChange,
|
|
4707
4884
|
handleToggleSellFiat,
|
|
4708
4885
|
handleSelectRate,
|
|
4709
4886
|
handleSlippageChange,
|
|
4710
4887
|
handleButtonClick
|
|
4711
|
-
} = useSwapHandlers({ partnerCode, allowShapeshiftRedirect });
|
|
4888
|
+
} = useSwapHandlers({ partnerCode, allowShapeshiftRedirect: canRedirectToShapeshift });
|
|
4712
4889
|
useSwapQuoting({ apiClient, rates, sellAssetBalance });
|
|
4713
4890
|
useSwapApproval();
|
|
4714
4891
|
useSwapExecution();
|
|
@@ -4804,17 +4981,20 @@ var SwapWidgetContent = ({
|
|
|
4804
4981
|
displayValues,
|
|
4805
4982
|
onOpenTokenModal: setTokenModalType,
|
|
4806
4983
|
onSellAmountChange: handleSellAmountChange,
|
|
4984
|
+
onBuyAmountChange: handleBuyAmountChange,
|
|
4807
4985
|
onToggleSellFiat: handleToggleSellFiat,
|
|
4808
4986
|
onSwapTokens: handleSwapTokens,
|
|
4809
4987
|
onSelectRate: handleSelectRate,
|
|
4810
4988
|
onButtonClick: handleButtonClick,
|
|
4811
4989
|
isBuyAssetLocked,
|
|
4812
|
-
|
|
4990
|
+
isBuyAmountLocked,
|
|
4991
|
+
isReceiveAddressLocked,
|
|
4992
|
+
allowShapeshiftRedirect: canRedirectToShapeshift
|
|
4813
4993
|
}
|
|
4814
4994
|
),
|
|
4815
4995
|
(state.matches("approval_needed") || state.matches("approving")) && /* @__PURE__ */ jsx11(ApprovalStep, {}),
|
|
4816
4996
|
state.matches("executing") && /* @__PURE__ */ jsx11(ExecutionStep, {}),
|
|
4817
|
-
(state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx11(StatusStep, {})
|
|
4997
|
+
(state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx11(StatusStep, { isPayment })
|
|
4818
4998
|
] }),
|
|
4819
4999
|
showPoweredBy && /* @__PURE__ */ jsxs11("div", { className: "ssw-powered-by", children: [
|
|
4820
5000
|
"Powered by",
|
|
@@ -4843,7 +5023,7 @@ var SwapWidgetContent = ({
|
|
|
4843
5023
|
disabledChainIds: (tokenModalType === "buy" ? buyFilters : sellFilters).disabledChainIds ?? [],
|
|
4844
5024
|
allowedChainIds: (tokenModalType === "buy" ? buyFilters : sellFilters).allowedChainIds,
|
|
4845
5025
|
allowedAssetIds: (tokenModalType === "buy" ? buyFilters : sellFilters).allowedAssetIds,
|
|
4846
|
-
allowShapeshiftRedirect
|
|
5026
|
+
allowShapeshiftRedirect: canRedirectToShapeshift
|
|
4847
5027
|
}
|
|
4848
5028
|
),
|
|
4849
5029
|
/* @__PURE__ */ jsx11(
|
|
@@ -4867,6 +5047,10 @@ var SwapWidgetCore = ({
|
|
|
4867
5047
|
showPoweredBy,
|
|
4868
5048
|
showConnectButton,
|
|
4869
5049
|
isBuyAssetLocked,
|
|
5050
|
+
defaultReceiveAddress,
|
|
5051
|
+
isReceiveAddressLocked,
|
|
5052
|
+
defaultBuyAmountCryptoBaseUnit,
|
|
5053
|
+
isBuyAmountLocked,
|
|
4870
5054
|
partnerCode,
|
|
4871
5055
|
allowShapeshiftRedirect,
|
|
4872
5056
|
onSwapSuccess,
|
|
@@ -4880,7 +5064,9 @@ var SwapWidgetCore = ({
|
|
|
4880
5064
|
const evm = useEvmSigning();
|
|
4881
5065
|
const bitcoin3 = useBitcoinSigning();
|
|
4882
5066
|
const solana3 = useSolanaSigning();
|
|
4883
|
-
const [customReceiveAddress, setCustomReceiveAddress] = useState8(
|
|
5067
|
+
const [customReceiveAddress, setCustomReceiveAddress] = useState8(
|
|
5068
|
+
defaultReceiveAddress ?? ""
|
|
5069
|
+
);
|
|
4884
5070
|
const sellChainId = SwapMachineCtx.useSelector((s) => s.context.sellAsset.chainId);
|
|
4885
5071
|
const buyChainId = SwapMachineCtx.useSelector((s) => s.context.buyAsset.chainId);
|
|
4886
5072
|
const sellChainType = getChainType(sellChainId);
|
|
@@ -4913,14 +5099,30 @@ var SwapWidgetCore = ({
|
|
|
4913
5099
|
() => addressForChain(buyChainType),
|
|
4914
5100
|
[addressForChain, buyChainType]
|
|
4915
5101
|
);
|
|
4916
|
-
const isCustomReceiveAddressValid = useMemo12(
|
|
4917
|
-
() => !!customReceiveAddress && validateAddress(customReceiveAddress, buyChainId).valid,
|
|
4918
|
-
[customReceiveAddress, buyChainId]
|
|
4919
|
-
);
|
|
4920
5102
|
const receiveAddress = useMemo12(
|
|
4921
|
-
() =>
|
|
4922
|
-
|
|
5103
|
+
() => resolveReceiveAddress({
|
|
5104
|
+
isLocked: isReceiveAddressLocked,
|
|
5105
|
+
defaultAddress: defaultReceiveAddress,
|
|
5106
|
+
customAddress: customReceiveAddress,
|
|
5107
|
+
walletAddress: walletReceiveAddress,
|
|
5108
|
+
buyChainId
|
|
5109
|
+
}),
|
|
5110
|
+
[
|
|
5111
|
+
isReceiveAddressLocked,
|
|
5112
|
+
defaultReceiveAddress,
|
|
5113
|
+
customReceiveAddress,
|
|
5114
|
+
walletReceiveAddress,
|
|
5115
|
+
buyChainId
|
|
5116
|
+
]
|
|
4923
5117
|
);
|
|
5118
|
+
useEffect10(() => {
|
|
5119
|
+
if (!isBuyAmountLocked) return;
|
|
5120
|
+
actorRef.send({
|
|
5121
|
+
type: "SET_BUY_AMOUNT",
|
|
5122
|
+
amount: defaultBuyAmountCryptoBaseUnit ? formatAmountForInput(defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision) : "",
|
|
5123
|
+
amountBaseUnit: defaultBuyAmountCryptoBaseUnit
|
|
5124
|
+
});
|
|
5125
|
+
}, [isBuyAmountLocked, defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision, actorRef]);
|
|
4924
5126
|
const initialSyncRef = useRef7(false);
|
|
4925
5127
|
useEffect10(() => {
|
|
4926
5128
|
if (initialSyncRef.current) return;
|
|
@@ -4928,6 +5130,11 @@ var SwapWidgetCore = ({
|
|
|
4928
5130
|
actorRef.send({ type: "SET_SELL_ASSET", asset: defaultSellAsset });
|
|
4929
5131
|
actorRef.send({ type: "SET_BUY_ASSET", asset: defaultBuyAsset });
|
|
4930
5132
|
actorRef.send({ type: "SET_SLIPPAGE", slippage: defaultSlippage });
|
|
5133
|
+
actorRef.send({
|
|
5134
|
+
type: "SET_BUY_AMOUNT",
|
|
5135
|
+
amount: defaultBuyAmountCryptoBaseUnit ? formatAmountForInput(defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision) : "",
|
|
5136
|
+
amountBaseUnit: defaultBuyAmountCryptoBaseUnit
|
|
5137
|
+
});
|
|
4931
5138
|
}, [actorRef]);
|
|
4932
5139
|
useEffect10(() => {
|
|
4933
5140
|
actorRef.send({ type: "SET_SEND_ADDRESS", address: sendAddress });
|
|
@@ -4944,6 +5151,7 @@ var SwapWidgetCore = ({
|
|
|
4944
5151
|
sendAddress,
|
|
4945
5152
|
receiveAddress,
|
|
4946
5153
|
isReceiveAddressResolving,
|
|
5154
|
+
isReceiveAddressBlocked: isReceiveAddressLocked && !receiveAddress,
|
|
4947
5155
|
customReceiveAddress,
|
|
4948
5156
|
setCustomReceiveAddress,
|
|
4949
5157
|
evm,
|
|
@@ -4954,12 +5162,16 @@ var SwapWidgetCore = ({
|
|
|
4954
5162
|
sendAddress,
|
|
4955
5163
|
receiveAddress,
|
|
4956
5164
|
isReceiveAddressResolving,
|
|
5165
|
+
isReceiveAddressLocked,
|
|
4957
5166
|
customReceiveAddress,
|
|
4958
5167
|
evm,
|
|
4959
5168
|
bitcoin3,
|
|
4960
5169
|
solana3
|
|
4961
5170
|
]
|
|
4962
5171
|
);
|
|
5172
|
+
const hasLockedBuyAmount = isBuyAmountLocked && !!defaultBuyAmountCryptoBaseUnit;
|
|
5173
|
+
const isPayment = hasLockedBuyAmount && isReceiveAddressLocked && !!defaultReceiveAddress;
|
|
5174
|
+
const canRedirectToShapeshift = allowShapeshiftRedirect && !hasLockedBuyAmount && !isReceiveAddressLocked;
|
|
4963
5175
|
return /* @__PURE__ */ jsx11(SwapWalletProvider, { value: walletValue, children: /* @__PURE__ */ jsx11(
|
|
4964
5176
|
SwapWidgetContent,
|
|
4965
5177
|
{
|
|
@@ -4967,9 +5179,12 @@ var SwapWidgetCore = ({
|
|
|
4967
5179
|
theme,
|
|
4968
5180
|
showPoweredBy,
|
|
4969
5181
|
showConnectButton,
|
|
4970
|
-
isBuyAssetLocked,
|
|
5182
|
+
isBuyAssetLocked: isBuyAssetLocked || hasLockedBuyAmount,
|
|
5183
|
+
isBuyAmountLocked,
|
|
5184
|
+
isReceiveAddressLocked,
|
|
5185
|
+
isPayment,
|
|
4971
5186
|
partnerCode,
|
|
4972
|
-
|
|
5187
|
+
canRedirectToShapeshift,
|
|
4973
5188
|
onSwapSuccess,
|
|
4974
5189
|
onSwapError,
|
|
4975
5190
|
sellFilters,
|
|
@@ -4998,6 +5213,10 @@ var SwapWidget = (props) => {
|
|
|
4998
5213
|
showPoweredBy: props.showPoweredBy ?? true,
|
|
4999
5214
|
showConnectButton: props.showConnectButton ?? true,
|
|
5000
5215
|
isBuyAssetLocked: props.isBuyAssetLocked ?? false,
|
|
5216
|
+
defaultReceiveAddress: props.defaultReceiveAddress,
|
|
5217
|
+
isReceiveAddressLocked: props.isReceiveAddressLocked ?? false,
|
|
5218
|
+
defaultBuyAmountCryptoBaseUnit: props.defaultBuyAmountCryptoBaseUnit,
|
|
5219
|
+
isBuyAmountLocked: props.isBuyAmountLocked ?? false,
|
|
5001
5220
|
partnerCode: props.partnerCode,
|
|
5002
5221
|
allowShapeshiftRedirect: props.allowShapeshiftRedirect ?? true,
|
|
5003
5222
|
onSwapSuccess: props.onSwapSuccess,
|