@shapeshiftoss/swap-widget 0.6.0 → 0.8.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 +171 -1
- package/dist/index.css +19 -0
- package/dist/index.d.ts +16 -2
- package/dist/index.js +439 -228
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,8 @@ import { useAppKitAccount as useAppKitAccount3 } from "@reown/appkit/react";
|
|
|
3
3
|
import { useCallback as useCallback11, useEffect as useEffect10, useMemo as useMemo12, useRef as useRef7, useState as useState8 } from "react";
|
|
4
4
|
|
|
5
5
|
// src/api/client.ts
|
|
6
|
-
var DEFAULT_API_BASE_URL =
|
|
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" },
|
|
@@ -1330,7 +1359,7 @@ var useStatusPolling = ({
|
|
|
1330
1359
|
|
|
1331
1360
|
// src/hooks/useSwapApproval.ts
|
|
1332
1361
|
import { useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
1333
|
-
import { createPublicClient as createPublicClient2,
|
|
1362
|
+
import { createPublicClient as createPublicClient2, http as http2 } from "viem";
|
|
1334
1363
|
|
|
1335
1364
|
// src/constants/chains.ts
|
|
1336
1365
|
import {
|
|
@@ -1443,6 +1472,15 @@ var useSwapApproval = () => {
|
|
|
1443
1472
|
});
|
|
1444
1473
|
return;
|
|
1445
1474
|
}
|
|
1475
|
+
if (!sellAmountBaseUnit || sellAmountBaseUnit === "0") {
|
|
1476
|
+
actorRef.send({ type: "APPROVAL_ERROR", error: "No sell amount specified" });
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1479
|
+
const approvalTxs = quote.approval.approvalTxs;
|
|
1480
|
+
if (!approvalTxs?.length) {
|
|
1481
|
+
actorRef.send({ type: "APPROVAL_ERROR", error: "No approval transactions in quote" });
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1446
1484
|
const requiredChainId = getEvmNetworkId(sellAsset.chainId);
|
|
1447
1485
|
const client = walletClient;
|
|
1448
1486
|
const currentChainId = await client.getChainId();
|
|
@@ -1458,28 +1496,24 @@ var useSwapApproval = () => {
|
|
|
1458
1496
|
nativeCurrency,
|
|
1459
1497
|
rpcUrls: { default: { http: [] } }
|
|
1460
1498
|
};
|
|
1461
|
-
if (!sellAmountBaseUnit || sellAmountBaseUnit === "0") {
|
|
1462
|
-
actorRef.send({ type: "APPROVAL_ERROR", error: "No sell amount specified" });
|
|
1463
|
-
return;
|
|
1464
|
-
}
|
|
1465
|
-
const approvalData = encodeFunctionData({
|
|
1466
|
-
abi: erc20Abi2,
|
|
1467
|
-
functionName: "approve",
|
|
1468
|
-
args: [quote.approval.spender, BigInt(sellAmountBaseUnit)]
|
|
1469
|
-
});
|
|
1470
|
-
const approvalHash = await client.sendTransaction({
|
|
1471
|
-
to: sellAssetAddress,
|
|
1472
|
-
data: approvalData,
|
|
1473
|
-
value: BigInt(0),
|
|
1474
|
-
chain,
|
|
1475
|
-
account: walletAddress
|
|
1476
|
-
});
|
|
1477
1499
|
const rpcUrl = chain.rpcUrls?.default?.http?.[0];
|
|
1478
1500
|
const publicClient = createPublicClient2({
|
|
1479
1501
|
chain,
|
|
1480
1502
|
transport: rpcUrl ? http2(rpcUrl) : http2()
|
|
1481
1503
|
});
|
|
1482
|
-
|
|
1504
|
+
let approvalHash;
|
|
1505
|
+
for (const approvalTx of approvalTxs) {
|
|
1506
|
+
approvalHash = await client.sendTransaction({
|
|
1507
|
+
to: approvalTx.to,
|
|
1508
|
+
data: approvalTx.data,
|
|
1509
|
+
value: BigInt(approvalTx.value),
|
|
1510
|
+
chain,
|
|
1511
|
+
account: walletAddress
|
|
1512
|
+
});
|
|
1513
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: approvalHash });
|
|
1514
|
+
if (receipt.status !== "success") throw new Error("Approval transaction reverted");
|
|
1515
|
+
}
|
|
1516
|
+
if (!approvalHash) throw new Error("Expected at least one approval transaction");
|
|
1483
1517
|
actorRef.send({ type: "APPROVAL_SUCCESS", txHash: approvalHash });
|
|
1484
1518
|
} catch (error) {
|
|
1485
1519
|
actorRef.send({
|
|
@@ -1623,7 +1657,7 @@ import { useQueries, useQueryClient } from "@tanstack/react-query";
|
|
|
1623
1657
|
import { getBalance, readContract } from "@wagmi/core";
|
|
1624
1658
|
import PQueue from "p-queue";
|
|
1625
1659
|
import { useCallback as useCallback3, useMemo as useMemo4 } from "react";
|
|
1626
|
-
import { erc20Abi as
|
|
1660
|
+
import { erc20Abi as erc20Abi2 } from "viem";
|
|
1627
1661
|
import { useConfig } from "wagmi";
|
|
1628
1662
|
var CONCURRENCY_LIMIT = 5;
|
|
1629
1663
|
var DELAY_BETWEEN_BATCHES_MS = 50;
|
|
@@ -1823,7 +1857,7 @@ var useMultiChainBalance = (evmAddress, utxoAddress, solanaAddress, assetId, pre
|
|
|
1823
1857
|
if (isErc20 && evmParsed.tokenAddress) {
|
|
1824
1858
|
const result2 = await readContract(config, {
|
|
1825
1859
|
address: evmParsed.tokenAddress,
|
|
1826
|
-
abi:
|
|
1860
|
+
abi: erc20Abi2,
|
|
1827
1861
|
functionName: "balanceOf",
|
|
1828
1862
|
args: [evmAddress],
|
|
1829
1863
|
chainId: evmParsed.evmChainId
|
|
@@ -1936,7 +1970,7 @@ var useMultiChainBalances = (evmAddress, utxoAddress, solanaAddress, assetIds, a
|
|
|
1936
1970
|
if (asset.tokenAddress) {
|
|
1937
1971
|
const result2 = await readContract(config, {
|
|
1938
1972
|
address: asset.tokenAddress,
|
|
1939
|
-
abi:
|
|
1973
|
+
abi: erc20Abi2,
|
|
1940
1974
|
functionName: "balanceOf",
|
|
1941
1975
|
args: [evmAddress],
|
|
1942
1976
|
// @ts-ignore - swap-widget supports more chains than main app's wagmi type registration
|
|
@@ -2232,28 +2266,55 @@ var formatUsdValue = (cryptoAmount, precision, usdPrice) => {
|
|
|
2232
2266
|
};
|
|
2233
2267
|
|
|
2234
2268
|
// src/hooks/useSwapRates.ts
|
|
2235
|
-
import { bnOrZero } from "@shapeshiftoss/utils";
|
|
2236
2269
|
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
2270
|
+
|
|
2271
|
+
// src/utils/rateDisplay.ts
|
|
2272
|
+
import { bnOrZero } from "@shapeshiftoss/utils";
|
|
2273
|
+
var getRateAmountBaseUnit = (rate, isExactOutput2) => (isExactOutput2 ? rate.sellAmountCryptoBaseUnit : rate.buyAmountCryptoBaseUnit) ?? "0";
|
|
2274
|
+
var sortRatesByValue = (rates, isExactOutput2) => [...rates].filter((rate) => !rate.error && getRateAmountBaseUnit(rate, isExactOutput2) !== "0").sort((a, b) => {
|
|
2275
|
+
const aAmount = bnOrZero(getRateAmountBaseUnit(a, isExactOutput2));
|
|
2276
|
+
const bAmount = bnOrZero(getRateAmountBaseUnit(b, isExactOutput2));
|
|
2277
|
+
return isExactOutput2 ? aAmount.minus(bAmount).toNumber() : bAmount.minus(aAmount).toNumber();
|
|
2278
|
+
});
|
|
2279
|
+
var getRateDiffPercent = (bestAmountBaseUnit, amountBaseUnit, isExactOutput2) => {
|
|
2280
|
+
const best = bnOrZero(bestAmountBaseUnit);
|
|
2281
|
+
const current = bnOrZero(amountBaseUnit);
|
|
2282
|
+
if (best.isZero()) return null;
|
|
2283
|
+
const diff = isExactOutput2 ? current.minus(best).div(best).times(100) : best.minus(current).div(best).times(100);
|
|
2284
|
+
return diff.gte("0.01") ? diff.toFixed(2) : null;
|
|
2285
|
+
};
|
|
2286
|
+
|
|
2287
|
+
// src/hooks/useSwapRates.ts
|
|
2237
2288
|
var ENABLED_SWAPPER_NAMES = new Set(Object.values(SwapperName));
|
|
2238
2289
|
var useSwapRates = (apiClient, params) => {
|
|
2239
2290
|
const {
|
|
2240
2291
|
sellAssetId,
|
|
2241
2292
|
buyAssetId,
|
|
2242
2293
|
sellAmountCryptoBaseUnit,
|
|
2294
|
+
buyAmountCryptoBaseUnit,
|
|
2243
2295
|
enabled = true,
|
|
2244
2296
|
allowedSwapperNames,
|
|
2245
2297
|
refetchInterval = 15e3
|
|
2246
2298
|
} = params;
|
|
2299
|
+
const isExactOutput2 = buyAmountCryptoBaseUnit !== void 0;
|
|
2300
|
+
const amountCryptoBaseUnit = isExactOutput2 ? buyAmountCryptoBaseUnit : sellAmountCryptoBaseUnit;
|
|
2247
2301
|
return useQuery3({
|
|
2248
|
-
queryKey: [
|
|
2302
|
+
queryKey: [
|
|
2303
|
+
"swapRates",
|
|
2304
|
+
sellAssetId,
|
|
2305
|
+
buyAssetId,
|
|
2306
|
+
amountCryptoBaseUnit,
|
|
2307
|
+
isExactOutput2,
|
|
2308
|
+
allowedSwapperNames
|
|
2309
|
+
],
|
|
2249
2310
|
queryFn: async () => {
|
|
2250
|
-
if (!sellAssetId || !buyAssetId || !
|
|
2311
|
+
if (!sellAssetId || !buyAssetId || !amountCryptoBaseUnit) {
|
|
2251
2312
|
return [];
|
|
2252
2313
|
}
|
|
2253
2314
|
const response = await apiClient.getRates({
|
|
2254
2315
|
sellAssetId,
|
|
2255
2316
|
buyAssetId,
|
|
2256
|
-
sellAmountCryptoBaseUnit
|
|
2317
|
+
...isExactOutput2 ? { buyAmountCryptoBaseUnit: amountCryptoBaseUnit } : { sellAmountCryptoBaseUnit: amountCryptoBaseUnit }
|
|
2257
2318
|
});
|
|
2258
2319
|
let filteredRates = response.rates.filter(
|
|
2259
2320
|
(rate) => !rate.error && rate.buyAmountCryptoBaseUnit !== "0" && ENABLED_SWAPPER_NAMES.has(rate.swapperName)
|
|
@@ -2261,16 +2322,15 @@ var useSwapRates = (apiClient, params) => {
|
|
|
2261
2322
|
if (allowedSwapperNames?.length) {
|
|
2262
2323
|
filteredRates = filteredRates.filter((rate) => allowedSwapperNames.includes(rate.swapperName));
|
|
2263
2324
|
}
|
|
2264
|
-
return
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
});
|
|
2325
|
+
return sortRatesByValue(
|
|
2326
|
+
filteredRates.map((rate, index) => ({
|
|
2327
|
+
...rate,
|
|
2328
|
+
id: rate.id ?? `${rate.swapperName}-${index}`
|
|
2329
|
+
})),
|
|
2330
|
+
isExactOutput2
|
|
2331
|
+
);
|
|
2272
2332
|
},
|
|
2273
|
-
enabled: enabled && !!sellAssetId && !!buyAssetId && !!
|
|
2333
|
+
enabled: enabled && !!sellAssetId && !!buyAssetId && !!amountCryptoBaseUnit,
|
|
2274
2334
|
staleTime: 1e4,
|
|
2275
2335
|
refetchInterval
|
|
2276
2336
|
});
|
|
@@ -2282,18 +2342,23 @@ var useSwapDisplayValues = ({
|
|
|
2282
2342
|
allowedSwapperNames,
|
|
2283
2343
|
ratesRefetchInterval
|
|
2284
2344
|
}) => {
|
|
2285
|
-
const
|
|
2286
|
-
const
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2345
|
+
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
2346
|
+
const {
|
|
2347
|
+
sellAsset,
|
|
2348
|
+
buyAsset,
|
|
2349
|
+
buyAmountBaseUnit,
|
|
2350
|
+
isSellAssetEvm,
|
|
2351
|
+
isSellAssetUtxo,
|
|
2352
|
+
isSellAssetSolana,
|
|
2353
|
+
selectedRate
|
|
2354
|
+
} = context;
|
|
2355
|
+
const { receiveAddress, isReceiveAddressBlocked, evm, bitcoin: bitcoin3, solana: solana3 } = useSwapWallet();
|
|
2293
2356
|
const evmAddress = evm.address;
|
|
2294
2357
|
const bitcoinAddress = bitcoin3.address;
|
|
2295
2358
|
const solanaAddress = solana3.address;
|
|
2296
2359
|
const buyChainType = getChainType(buyAsset.chainId);
|
|
2360
|
+
const isExactOutput2 = !!buyAmountBaseUnit;
|
|
2361
|
+
const amountBaseUnit = isExactOutput2 ? buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
2297
2362
|
const {
|
|
2298
2363
|
data: rates,
|
|
2299
2364
|
isLoading: isLoadingRates,
|
|
@@ -2301,10 +2366,12 @@ var useSwapDisplayValues = ({
|
|
|
2301
2366
|
} = useSwapRates(apiClient, {
|
|
2302
2367
|
sellAssetId: sellAsset.assetId,
|
|
2303
2368
|
buyAssetId: buyAsset.assetId,
|
|
2304
|
-
sellAmountCryptoBaseUnit: sellAmountBaseUnit,
|
|
2369
|
+
sellAmountCryptoBaseUnit: context.sellAmountBaseUnit,
|
|
2370
|
+
buyAmountCryptoBaseUnit: buyAmountBaseUnit,
|
|
2305
2371
|
allowedSwapperNames,
|
|
2306
2372
|
refetchInterval: ratesRefetchInterval,
|
|
2307
|
-
|
|
2373
|
+
// Rates need no destination, but a locked one the buy chain rejects can never be quoted
|
|
2374
|
+
enabled: !!amountBaseUnit && amountBaseUnit !== "0" && !isReceiveAddressBlocked && (isSellAssetEvm || isSellAssetUtxo || isSellAssetSolana)
|
|
2308
2375
|
});
|
|
2309
2376
|
const {
|
|
2310
2377
|
data: sellAssetBalance,
|
|
@@ -2338,6 +2405,7 @@ var useSwapDisplayValues = ({
|
|
|
2338
2405
|
const { data: buyChainInfo } = useChainInfo(buyAsset.chainId);
|
|
2339
2406
|
const displayRate = useMemo5(() => selectedRate ?? rates?.[0], [selectedRate, rates]);
|
|
2340
2407
|
const buyAmount = displayRate?.buyAmountCryptoBaseUnit;
|
|
2408
|
+
const sellAmountBaseUnit = isExactOutput2 ? displayRate?.sellAmountCryptoBaseUnit : context.sellAmountBaseUnit;
|
|
2341
2409
|
const sellChainNativeAsset = useMemo5(() => getBaseAsset(sellAsset.chainId), [sellAsset.chainId]);
|
|
2342
2410
|
const assetIdsForPrices = useMemo5(() => {
|
|
2343
2411
|
const ids = [sellAsset.assetId, buyAsset.assetId];
|
|
@@ -2395,6 +2463,8 @@ var useSwapDisplayValues = ({
|
|
|
2395
2463
|
buyChainInfo,
|
|
2396
2464
|
displayRate,
|
|
2397
2465
|
buyAmount,
|
|
2466
|
+
isExactOutput: isExactOutput2,
|
|
2467
|
+
sellAmountBaseUnit,
|
|
2398
2468
|
sellChainNativeAsset,
|
|
2399
2469
|
networkFeeDisplay,
|
|
2400
2470
|
sellUsdValue,
|
|
@@ -2418,6 +2488,8 @@ var useSwapDisplayValues = ({
|
|
|
2418
2488
|
buyChainInfo,
|
|
2419
2489
|
displayRate,
|
|
2420
2490
|
buyAmount,
|
|
2491
|
+
isExactOutput2,
|
|
2492
|
+
sellAmountBaseUnit,
|
|
2421
2493
|
sellChainNativeAsset,
|
|
2422
2494
|
networkFeeDisplay,
|
|
2423
2495
|
sellUsdValue,
|
|
@@ -2548,6 +2620,10 @@ var useSwapExecution = () => {
|
|
|
2548
2620
|
});
|
|
2549
2621
|
return;
|
|
2550
2622
|
}
|
|
2623
|
+
if (Date.now() >= quote.expiresAt) {
|
|
2624
|
+
actorRef.send({ type: "EXECUTE_ERROR", error: "Quote expired \u2014 please try again" });
|
|
2625
|
+
return;
|
|
2626
|
+
}
|
|
2551
2627
|
const txData = quote.steps[0]?.transactionData;
|
|
2552
2628
|
if (!txData) {
|
|
2553
2629
|
console.error("Quote missing transactionData in steps[0]", quote);
|
|
@@ -2657,15 +2733,27 @@ var useSwapHandlers = ({
|
|
|
2657
2733
|
},
|
|
2658
2734
|
[actorRef]
|
|
2659
2735
|
);
|
|
2736
|
+
const handleBuyAmountChange = useCallback4(
|
|
2737
|
+
(value) => {
|
|
2738
|
+
const { buyAsset } = actorRef.getSnapshot().context;
|
|
2739
|
+
const amountBaseUnit = value ? parseAmount(value, buyAsset.precision) : void 0;
|
|
2740
|
+
actorRef.send({ type: "SET_BUY_AMOUNT", amount: value, amountBaseUnit });
|
|
2741
|
+
},
|
|
2742
|
+
[actorRef]
|
|
2743
|
+
);
|
|
2660
2744
|
const handleToggleSellFiat = useCallback4(
|
|
2661
2745
|
(sellAssetUsdPrice) => {
|
|
2662
2746
|
if (!sellAssetUsdPrice) return;
|
|
2663
2747
|
const snap = actorRef.getSnapshot();
|
|
2664
|
-
const { sellAmount, sellAmountBaseUnit, sellAsset, isSellAmountFiat } = snap.context;
|
|
2748
|
+
const { sellAmount, sellAmountBaseUnit, sellAsset, isSellAmountFiat, buyAmountBaseUnit } = snap.context;
|
|
2665
2749
|
if (isSellAmountFiat) {
|
|
2666
2750
|
actorRef.send({ type: "SET_SELL_FIAT_MODE", isFiat: false });
|
|
2667
2751
|
return;
|
|
2668
2752
|
}
|
|
2753
|
+
if (buyAmountBaseUnit) {
|
|
2754
|
+
actorRef.send({ type: "SET_SELL_FIAT_MODE", isFiat: true });
|
|
2755
|
+
return;
|
|
2756
|
+
}
|
|
2669
2757
|
const fiatValue = cryptoToFiat(sellAmountBaseUnit, sellAssetUsdPrice, sellAsset.precision);
|
|
2670
2758
|
actorRef.send({
|
|
2671
2759
|
type: "SET_SELL_AMOUNT",
|
|
@@ -2741,6 +2829,7 @@ var useSwapHandlers = ({
|
|
|
2741
2829
|
handleSellAssetSelect,
|
|
2742
2830
|
handleBuyAssetSelect,
|
|
2743
2831
|
handleSellAmountChange,
|
|
2832
|
+
handleBuyAmountChange,
|
|
2744
2833
|
handleToggleSellFiat,
|
|
2745
2834
|
handleSelectRate,
|
|
2746
2835
|
handleSlippageChange,
|
|
@@ -2763,9 +2852,12 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2763
2852
|
quotingRef.current = true;
|
|
2764
2853
|
const fetchQuote = async () => {
|
|
2765
2854
|
try {
|
|
2766
|
-
|
|
2855
|
+
const isExactOutput2 = !!context.buyAmountBaseUnit;
|
|
2856
|
+
const rateToUse = context.selectedRate ?? rates?.[0];
|
|
2857
|
+
const sellAmountBaseUnit = isExactOutput2 ? rateToUse?.sellAmountCryptoBaseUnit : context.sellAmountBaseUnit;
|
|
2858
|
+
if (sellAssetBalance?.balance && sellAmountBaseUnit) {
|
|
2767
2859
|
const balanceBigInt = BigInt(sellAssetBalance.balance);
|
|
2768
|
-
const amountBigInt = BigInt(
|
|
2860
|
+
const amountBigInt = BigInt(sellAmountBaseUnit);
|
|
2769
2861
|
if (amountBigInt > balanceBigInt) {
|
|
2770
2862
|
actorRef.send({ type: "QUOTE_ERROR", error: "Insufficient balance" });
|
|
2771
2863
|
return;
|
|
@@ -2777,8 +2869,8 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2777
2869
|
return;
|
|
2778
2870
|
}
|
|
2779
2871
|
const slippageDecimal = (parsedSlippage / 100).toString();
|
|
2780
|
-
const
|
|
2781
|
-
if (!rateToUse || !
|
|
2872
|
+
const amountBaseUnit = isExactOutput2 ? context.buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
2873
|
+
if (!rateToUse || !amountBaseUnit) {
|
|
2782
2874
|
actorRef.send({ type: "QUOTE_ERROR", error: "No rate or amount available" });
|
|
2783
2875
|
return;
|
|
2784
2876
|
}
|
|
@@ -2794,7 +2886,7 @@ var useSwapQuoting = ({ apiClient, rates, sellAssetBalance }) => {
|
|
|
2794
2886
|
const response = await apiClient.getQuote({
|
|
2795
2887
|
sellAssetId: context.sellAsset.assetId,
|
|
2796
2888
|
buyAssetId: context.buyAsset.assetId,
|
|
2797
|
-
sellAmountCryptoBaseUnit:
|
|
2889
|
+
...isExactOutput2 ? { buyAmountCryptoBaseUnit: amountBaseUnit } : { sellAmountCryptoBaseUnit: amountBaseUnit },
|
|
2798
2890
|
sendAddress,
|
|
2799
2891
|
receiveAddress: resolvedReceiveAddress,
|
|
2800
2892
|
swapperName: rateToUse.swapperName,
|
|
@@ -2951,6 +3043,19 @@ var getAddressFormatHint = (chainId) => {
|
|
|
2951
3043
|
}
|
|
2952
3044
|
};
|
|
2953
3045
|
|
|
3046
|
+
// src/utils/receiveAddress.ts
|
|
3047
|
+
var resolveReceiveAddress = ({
|
|
3048
|
+
isLocked,
|
|
3049
|
+
defaultAddress,
|
|
3050
|
+
customAddress,
|
|
3051
|
+
walletAddress,
|
|
3052
|
+
buyChainId
|
|
3053
|
+
}) => {
|
|
3054
|
+
const isValidForBuyChain = (address) => !!address && validateAddress(address, buyChainId).valid;
|
|
3055
|
+
if (isLocked) return isValidForBuyChain(defaultAddress) ? defaultAddress : void 0;
|
|
3056
|
+
return isValidForBuyChain(customAddress) ? customAddress : walletAddress;
|
|
3057
|
+
};
|
|
3058
|
+
|
|
2954
3059
|
// src/components/ApprovalStep.tsx
|
|
2955
3060
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2956
3061
|
var ApprovalStep = () => {
|
|
@@ -3112,9 +3217,8 @@ var getSwapperColor = (swapperName) => {
|
|
|
3112
3217
|
};
|
|
3113
3218
|
|
|
3114
3219
|
// src/components/QuotesModal.tsx
|
|
3115
|
-
import { bnOrZero as bnOrZero2 } from "@shapeshiftoss/utils";
|
|
3116
3220
|
import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo6 } from "react";
|
|
3117
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3221
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
3118
3222
|
var useLockBodyScroll = (isLocked) => {
|
|
3119
3223
|
useEffect6(() => {
|
|
3120
3224
|
if (!isLocked) return;
|
|
@@ -3125,13 +3229,6 @@ var useLockBodyScroll = (isLocked) => {
|
|
|
3125
3229
|
};
|
|
3126
3230
|
}, [isLocked]);
|
|
3127
3231
|
};
|
|
3128
|
-
var calculateSavingsPercent = (bestAmount, currentAmount) => {
|
|
3129
|
-
const best = bnOrZero2(bestAmount);
|
|
3130
|
-
const current = bnOrZero2(currentAmount);
|
|
3131
|
-
if (best.isZero()) return null;
|
|
3132
|
-
const diff = best.minus(current).div(best).times(100);
|
|
3133
|
-
return diff.gt(0.1) ? diff.toFixed(2) : null;
|
|
3134
|
-
};
|
|
3135
3232
|
var QuotesModal = ({
|
|
3136
3233
|
isOpen,
|
|
3137
3234
|
onClose,
|
|
@@ -3141,6 +3238,9 @@ var QuotesModal = ({
|
|
|
3141
3238
|
buyAsset,
|
|
3142
3239
|
sellAsset,
|
|
3143
3240
|
sellAmountBaseUnit,
|
|
3241
|
+
buyAmountBaseUnit,
|
|
3242
|
+
isExactOutput: isExactOutput2,
|
|
3243
|
+
sellAssetUsdPrice,
|
|
3144
3244
|
buyAssetUsdPrice
|
|
3145
3245
|
}) => {
|
|
3146
3246
|
useLockBodyScroll(isOpen);
|
|
@@ -3159,15 +3259,11 @@ var QuotesModal = ({
|
|
|
3159
3259
|
},
|
|
3160
3260
|
[onSelectRate, onClose]
|
|
3161
3261
|
);
|
|
3162
|
-
const sortedRates = useMemo6(() =>
|
|
3163
|
-
return [...rates].filter((r) => !r.error && r.buyAmountCryptoBaseUnit !== "0").sort((a, b) => {
|
|
3164
|
-
const aAmount = bnOrZero2(a.buyAmountCryptoBaseUnit);
|
|
3165
|
-
const bAmount = bnOrZero2(b.buyAmountCryptoBaseUnit);
|
|
3166
|
-
return bAmount.minus(aAmount).toNumber();
|
|
3167
|
-
});
|
|
3168
|
-
}, [rates]);
|
|
3262
|
+
const sortedRates = useMemo6(() => sortRatesByValue(rates, isExactOutput2), [rates, isExactOutput2]);
|
|
3169
3263
|
const bestRate = useMemo6(() => sortedRates[0], [sortedRates]);
|
|
3170
|
-
const
|
|
3264
|
+
const bestAmountBaseUnit = bestRate ? getRateAmountBaseUnit(bestRate, isExactOutput2) : "0";
|
|
3265
|
+
const asset = isExactOutput2 ? sellAsset : buyAsset;
|
|
3266
|
+
const usdPrice = isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice;
|
|
3171
3267
|
if (!isOpen) return null;
|
|
3172
3268
|
return (
|
|
3173
3269
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
@@ -3184,14 +3280,20 @@ var QuotesModal = ({
|
|
|
3184
3280
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-modal-header", children: [
|
|
3185
3281
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quotes-header-content", children: [
|
|
3186
3282
|
/* @__PURE__ */ jsx3("h2", { id: "quotes-modal-title", className: "ssw-quotes-modal-title", children: "Select Route" }),
|
|
3187
|
-
/* @__PURE__ */
|
|
3283
|
+
/* @__PURE__ */ jsx3("span", { className: "ssw-quotes-modal-subtitle", children: isExactOutput2 ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3284
|
+
sellAsset.symbol,
|
|
3285
|
+
" \u2192 ",
|
|
3286
|
+
formatAmount(buyAmountBaseUnit, buyAsset.precision),
|
|
3287
|
+
" ",
|
|
3288
|
+
buyAsset.symbol
|
|
3289
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
3188
3290
|
formatAmount(sellAmountBaseUnit, sellAsset.precision),
|
|
3189
3291
|
" ",
|
|
3190
3292
|
sellAsset.symbol,
|
|
3191
3293
|
" \u2192",
|
|
3192
3294
|
" ",
|
|
3193
3295
|
buyAsset.symbol
|
|
3194
|
-
] })
|
|
3296
|
+
] }) })
|
|
3195
3297
|
] }),
|
|
3196
3298
|
/* @__PURE__ */ jsx3("button", { className: "ssw-quotes-modal-close", onClick: onClose, type: "button", children: /* @__PURE__ */ jsx3(
|
|
3197
3299
|
"svg",
|
|
@@ -3207,15 +3309,15 @@ var QuotesModal = ({
|
|
|
3207
3309
|
) })
|
|
3208
3310
|
] }),
|
|
3209
3311
|
/* @__PURE__ */ jsx3("div", { className: "ssw-quotes-modal-list", children: sortedRates.map((rate, index) => {
|
|
3210
|
-
const
|
|
3312
|
+
const amountBaseUnit = getRateAmountBaseUnit(rate, isExactOutput2);
|
|
3211
3313
|
const estimatedTime = rate.estimatedExecutionTimeMs;
|
|
3212
3314
|
const isBest = index === 0;
|
|
3213
3315
|
const isSelected = selectedRate?.id === rate.id;
|
|
3214
3316
|
const swapperIcon = getSwapperIcon(rate.swapperName);
|
|
3215
3317
|
const swapperColor = getSwapperColor(rate.swapperName);
|
|
3216
|
-
const
|
|
3217
|
-
const usdValue = formatUsdValue(
|
|
3218
|
-
const
|
|
3318
|
+
const formattedAmount = formatAmount(amountBaseUnit, asset.precision);
|
|
3319
|
+
const usdValue = formatUsdValue(amountBaseUnit, asset.precision, usdPrice);
|
|
3320
|
+
const diffPercent = isBest ? null : getRateDiffPercent(bestAmountBaseUnit, amountBaseUnit, isExactOutput2);
|
|
3219
3321
|
const estimatedSeconds = estimatedTime ? Math.round(estimatedTime / 1e3) : 0;
|
|
3220
3322
|
const hasTime = estimatedSeconds > 0;
|
|
3221
3323
|
return /* @__PURE__ */ jsxs3(
|
|
@@ -3238,9 +3340,9 @@ var QuotesModal = ({
|
|
|
3238
3340
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-name-row", children: [
|
|
3239
3341
|
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-name", children: rate.swapperName }),
|
|
3240
3342
|
isBest && /* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-best", children: "Best" }),
|
|
3241
|
-
|
|
3242
|
-
"-",
|
|
3243
|
-
|
|
3343
|
+
diffPercent && /* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-diff", children: [
|
|
3344
|
+
isExactOutput2 ? "+" : "-",
|
|
3345
|
+
diffPercent,
|
|
3244
3346
|
"%"
|
|
3245
3347
|
] })
|
|
3246
3348
|
] }),
|
|
@@ -3253,9 +3355,9 @@ var QuotesModal = ({
|
|
|
3253
3355
|
] }),
|
|
3254
3356
|
/* @__PURE__ */ jsxs3("div", { className: "ssw-quote-row-right", children: [
|
|
3255
3357
|
/* @__PURE__ */ jsxs3("span", { className: "ssw-quote-row-amount", children: [
|
|
3256
|
-
|
|
3358
|
+
formattedAmount,
|
|
3257
3359
|
" ",
|
|
3258
|
-
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-symbol", children:
|
|
3360
|
+
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-symbol", children: asset.symbol })
|
|
3259
3361
|
] }),
|
|
3260
3362
|
/* @__PURE__ */ jsx3("span", { className: "ssw-quote-row-usd", children: usdValue })
|
|
3261
3363
|
] })
|
|
@@ -3271,7 +3373,7 @@ var QuotesModal = ({
|
|
|
3271
3373
|
};
|
|
3272
3374
|
|
|
3273
3375
|
// src/components/QuoteSelector.tsx
|
|
3274
|
-
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3376
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3275
3377
|
var QuoteSelector = ({
|
|
3276
3378
|
rates,
|
|
3277
3379
|
selectedRate,
|
|
@@ -3279,7 +3381,10 @@ var QuoteSelector = ({
|
|
|
3279
3381
|
buyAsset,
|
|
3280
3382
|
sellAsset,
|
|
3281
3383
|
sellAmountBaseUnit,
|
|
3384
|
+
buyAmountBaseUnit,
|
|
3385
|
+
isExactOutput: isExactOutput2,
|
|
3282
3386
|
isLoading,
|
|
3387
|
+
sellAssetUsdPrice,
|
|
3283
3388
|
buyAssetUsdPrice
|
|
3284
3389
|
}) => {
|
|
3285
3390
|
const [isModalOpen, setIsModalOpen] = useState3(false);
|
|
@@ -3309,12 +3414,17 @@ var QuoteSelector = ({
|
|
|
3309
3414
|
return null;
|
|
3310
3415
|
}
|
|
3311
3416
|
const displayRate = selectedRate ?? bestRate;
|
|
3312
|
-
const buyAmount = displayRate.buyAmountCryptoBaseUnit ?? "0";
|
|
3313
3417
|
const swapperIcon = getSwapperIcon(displayRate.swapperName);
|
|
3314
3418
|
const swapperColor = getSwapperColor(displayRate.swapperName);
|
|
3315
|
-
const
|
|
3316
|
-
const
|
|
3317
|
-
|
|
3419
|
+
const asset = isExactOutput2 ? sellAsset : buyAsset;
|
|
3420
|
+
const amountBaseUnit = getRateAmountBaseUnit(displayRate, isExactOutput2);
|
|
3421
|
+
const formattedAmount = formatAmount(amountBaseUnit, asset.precision);
|
|
3422
|
+
const usdValue = formatUsdValue(
|
|
3423
|
+
amountBaseUnit,
|
|
3424
|
+
asset.precision,
|
|
3425
|
+
isExactOutput2 ? sellAssetUsdPrice : buyAssetUsdPrice
|
|
3426
|
+
);
|
|
3427
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3318
3428
|
/* @__PURE__ */ jsxs4("button", { className: "ssw-quote-selector", onClick: handleOpenModal, type: "button", children: [
|
|
3319
3429
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-left", children: [
|
|
3320
3430
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-provider", children: [
|
|
@@ -3340,8 +3450,8 @@ var QuoteSelector = ({
|
|
|
3340
3450
|
] }),
|
|
3341
3451
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-right", children: [
|
|
3342
3452
|
/* @__PURE__ */ jsxs4("div", { className: "ssw-quote-amount-row", children: [
|
|
3343
|
-
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-amount", children:
|
|
3344
|
-
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-symbol", children:
|
|
3453
|
+
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-amount", children: formattedAmount }),
|
|
3454
|
+
/* @__PURE__ */ jsx4("span", { className: "ssw-quote-symbol", children: asset.symbol })
|
|
3345
3455
|
] }),
|
|
3346
3456
|
alternativeRatesCount > 0 && /* @__PURE__ */ jsxs4("span", { className: "ssw-quote-more", children: [
|
|
3347
3457
|
"+",
|
|
@@ -3373,6 +3483,9 @@ var QuoteSelector = ({
|
|
|
3373
3483
|
buyAsset,
|
|
3374
3484
|
sellAsset,
|
|
3375
3485
|
sellAmountBaseUnit,
|
|
3486
|
+
buyAmountBaseUnit,
|
|
3487
|
+
isExactOutput: isExactOutput2,
|
|
3488
|
+
sellAssetUsdPrice,
|
|
3376
3489
|
buyAssetUsdPrice
|
|
3377
3490
|
}
|
|
3378
3491
|
)
|
|
@@ -3381,11 +3494,12 @@ var QuoteSelector = ({
|
|
|
3381
3494
|
|
|
3382
3495
|
// src/components/ReceiveAddressRow.tsx
|
|
3383
3496
|
import { useCallback as useCallback7, useLayoutEffect, useMemo as useMemo8, useRef as useRef5, useState as useState4 } from "react";
|
|
3384
|
-
import { Fragment as
|
|
3497
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3385
3498
|
var ReceiveAddressRow = ({
|
|
3386
3499
|
receiveAddress,
|
|
3387
3500
|
isResolving,
|
|
3388
3501
|
buyChainId,
|
|
3502
|
+
isLocked,
|
|
3389
3503
|
onSetCustomReceiveAddress
|
|
3390
3504
|
}) => {
|
|
3391
3505
|
const [isEditing, setIsEditing] = useState4(false);
|
|
@@ -3393,7 +3507,7 @@ var ReceiveAddressRow = ({
|
|
|
3393
3507
|
const [hasInteracted, setHasInteracted] = useState4(false);
|
|
3394
3508
|
const inputRef = useRef5(null);
|
|
3395
3509
|
const needsAddress = !receiveAddress;
|
|
3396
|
-
const showInput = needsAddress && !isResolving || isEditing;
|
|
3510
|
+
const showInput = !isLocked && (needsAddress && !isResolving || isEditing);
|
|
3397
3511
|
const showAttention = needsAddress && !isResolving;
|
|
3398
3512
|
useLayoutEffect(() => {
|
|
3399
3513
|
if (isEditing) inputRef.current?.focus();
|
|
@@ -3413,6 +3527,7 @@ var ReceiveAddressRow = ({
|
|
|
3413
3527
|
[trimmedDraft, buyChainId]
|
|
3414
3528
|
);
|
|
3415
3529
|
const formatHint = useMemo8(() => getAddressFormatHint(buyChainId), [buyChainId]);
|
|
3530
|
+
const chainName = useMemo8(() => getChainName(buyChainId), [buyChainId]);
|
|
3416
3531
|
const startEditing = useCallback7(() => {
|
|
3417
3532
|
setDraft(receiveAddress ?? "");
|
|
3418
3533
|
setHasInteracted(false);
|
|
@@ -3436,36 +3551,48 @@ var ReceiveAddressRow = ({
|
|
|
3436
3551
|
}, [onSetCustomReceiveAddress]);
|
|
3437
3552
|
const showReset = !!draft || isEditing;
|
|
3438
3553
|
if (!showInput) {
|
|
3439
|
-
return /* @__PURE__ */ jsxs5(
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
"
|
|
3445
|
-
{
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3554
|
+
return /* @__PURE__ */ jsxs5(
|
|
3555
|
+
"div",
|
|
3556
|
+
{
|
|
3557
|
+
className: `ssw-receive-row ssw-receive-row-resolved${showAttention ? " ssw-receive-row-invalid" : ""}`,
|
|
3558
|
+
children: [
|
|
3559
|
+
/* @__PURE__ */ jsx5("span", { className: "ssw-receive-label", children: "Receive address" }),
|
|
3560
|
+
/* @__PURE__ */ jsx5("div", { className: "ssw-receive-resolved-value", children: isResolving ? /* @__PURE__ */ jsx5("span", { className: "ssw-balance-skeleton" }) : showAttention ? (
|
|
3561
|
+
// Locked only - an unlocked row with no address shows the input instead
|
|
3562
|
+
/* @__PURE__ */ jsxs5("span", { className: "ssw-receive-error", children: [
|
|
3563
|
+
"Not valid for ",
|
|
3564
|
+
chainName
|
|
3565
|
+
] })
|
|
3566
|
+
) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3567
|
+
/* @__PURE__ */ jsx5("span", { className: "ssw-receive-address", children: truncateAddress(receiveAddress ?? "", 6) }),
|
|
3568
|
+
!isLocked && /* @__PURE__ */ jsx5(
|
|
3569
|
+
"button",
|
|
3452
3570
|
{
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3571
|
+
className: "ssw-receive-edit-btn",
|
|
3572
|
+
onClick: startEditing,
|
|
3573
|
+
type: "button",
|
|
3574
|
+
"aria-label": "Edit receive address",
|
|
3575
|
+
children: /* @__PURE__ */ jsxs5(
|
|
3576
|
+
"svg",
|
|
3577
|
+
{
|
|
3578
|
+
width: "14",
|
|
3579
|
+
height: "14",
|
|
3580
|
+
viewBox: "0 0 24 24",
|
|
3581
|
+
fill: "none",
|
|
3582
|
+
stroke: "currentColor",
|
|
3583
|
+
strokeWidth: "2",
|
|
3584
|
+
children: [
|
|
3585
|
+
/* @__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" }),
|
|
3586
|
+
/* @__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" })
|
|
3587
|
+
]
|
|
3588
|
+
}
|
|
3589
|
+
)
|
|
3463
3590
|
}
|
|
3464
3591
|
)
|
|
3465
|
-
}
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3592
|
+
] }) })
|
|
3593
|
+
]
|
|
3594
|
+
}
|
|
3595
|
+
);
|
|
3469
3596
|
}
|
|
3470
3597
|
return /* @__PURE__ */ jsxs5(
|
|
3471
3598
|
"div",
|
|
@@ -3549,39 +3676,23 @@ var ReceiveAddressRow = ({
|
|
|
3549
3676
|
};
|
|
3550
3677
|
|
|
3551
3678
|
// src/components/InputStep.tsx
|
|
3552
|
-
import { Fragment as
|
|
3679
|
+
import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3553
3680
|
var InputStep = ({
|
|
3554
3681
|
displayValues,
|
|
3555
3682
|
onOpenTokenModal,
|
|
3556
3683
|
onSellAmountChange,
|
|
3684
|
+
onBuyAmountChange,
|
|
3557
3685
|
onToggleSellFiat,
|
|
3558
3686
|
onSwapTokens,
|
|
3559
3687
|
onSelectRate,
|
|
3560
3688
|
onButtonClick,
|
|
3561
3689
|
isBuyAssetLocked,
|
|
3690
|
+
isBuyAmountLocked,
|
|
3691
|
+
isReceiveAddressLocked,
|
|
3562
3692
|
allowShapeshiftRedirect
|
|
3563
3693
|
}) => {
|
|
3564
3694
|
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
3565
3695
|
const isQuoting = SwapMachineCtx.useSelector((s) => s.matches("quoting"));
|
|
3566
|
-
const {
|
|
3567
|
-
rates,
|
|
3568
|
-
isLoadingRates,
|
|
3569
|
-
ratesError,
|
|
3570
|
-
sellAssetBalance,
|
|
3571
|
-
buyAssetBalance,
|
|
3572
|
-
isSellBalanceLoading,
|
|
3573
|
-
isBuyBalanceLoading,
|
|
3574
|
-
sellUsdValue,
|
|
3575
|
-
sellAssetUsdPrice,
|
|
3576
|
-
buyUsdValue,
|
|
3577
|
-
sellChainInfo,
|
|
3578
|
-
buyChainInfo,
|
|
3579
|
-
buyAmount,
|
|
3580
|
-
buyAssetUsdPrice,
|
|
3581
|
-
networkFeeDisplay,
|
|
3582
|
-
sellBalanceFiatValue,
|
|
3583
|
-
buyBalanceFiatValue
|
|
3584
|
-
} = displayValues;
|
|
3585
3696
|
const {
|
|
3586
3697
|
sendAddress,
|
|
3587
3698
|
receiveAddress,
|
|
@@ -3591,22 +3702,48 @@ var InputStep = ({
|
|
|
3591
3702
|
bitcoin: bitcoin3,
|
|
3592
3703
|
solana: solana3
|
|
3593
3704
|
} = useSwapWallet();
|
|
3594
|
-
const
|
|
3595
|
-
sellAsset,
|
|
3596
|
-
buyAsset,
|
|
3597
|
-
selectedRate,
|
|
3598
|
-
sellAmount,
|
|
3599
|
-
sellAmountBaseUnit,
|
|
3600
|
-
isSellAmountFiat,
|
|
3601
|
-
sellAmountFiat,
|
|
3602
|
-
isSellAssetEvm,
|
|
3603
|
-
isSellAssetUtxo,
|
|
3604
|
-
isSellAssetSolana
|
|
3605
|
-
} = context;
|
|
3606
|
-
const buyChainId = buyAsset.chainId;
|
|
3705
|
+
const buyChainId = context.buyAsset.chainId;
|
|
3607
3706
|
const hasAnyWalletAddress = !!evm.address || !!bitcoin3.address || !!solana3.address;
|
|
3608
3707
|
const hasActiveWallet = !!receiveAddress || hasAnyWalletAddress || isReceiveAddressResolving;
|
|
3609
|
-
const isUnsupportedChain = !isSellAssetEvm && !isSellAssetUtxo && !isSellAssetSolana;
|
|
3708
|
+
const isUnsupportedChain = !context.isSellAssetEvm && !context.isSellAssetUtxo && !context.isSellAssetSolana;
|
|
3709
|
+
const amountBaseUnit = displayValues.isExactOutput ? context.buyAmountBaseUnit : context.sellAmountBaseUnit;
|
|
3710
|
+
const isSellAmountReadOnly = displayValues.isExactOutput && isBuyAmountLocked;
|
|
3711
|
+
const isSellAmountPending = displayValues.isExactOutput && displayValues.isLoadingRates;
|
|
3712
|
+
const isBuyAmountPending = !displayValues.isExactOutput && displayValues.isLoadingRates;
|
|
3713
|
+
const sellAmountCrypto = useMemo9(
|
|
3714
|
+
() => displayValues.sellAmountBaseUnit ? formatAmount(displayValues.sellAmountBaseUnit, context.sellAsset.precision, 6) : "",
|
|
3715
|
+
[displayValues.sellAmountBaseUnit, context.sellAsset.precision]
|
|
3716
|
+
);
|
|
3717
|
+
const buyAmountValue = useMemo9(() => {
|
|
3718
|
+
if (displayValues.isExactOutput) return context.buyAmount;
|
|
3719
|
+
if (!displayValues.buyAmount) return "";
|
|
3720
|
+
return formatAmount(displayValues.buyAmount, context.buyAsset.precision);
|
|
3721
|
+
}, [
|
|
3722
|
+
displayValues.isExactOutput,
|
|
3723
|
+
displayValues.buyAmount,
|
|
3724
|
+
context.buyAmount,
|
|
3725
|
+
context.buyAsset.precision
|
|
3726
|
+
]);
|
|
3727
|
+
const sellAmountValue = useMemo9(() => {
|
|
3728
|
+
if (!displayValues.isExactOutput) {
|
|
3729
|
+
return context.isSellAmountFiat ? context.sellAmountFiat : context.sellAmount;
|
|
3730
|
+
}
|
|
3731
|
+
if (!context.isSellAmountFiat) return sellAmountCrypto;
|
|
3732
|
+
return cryptoToFiat(
|
|
3733
|
+
displayValues.sellAmountBaseUnit,
|
|
3734
|
+
displayValues.sellAssetUsdPrice ?? "",
|
|
3735
|
+
context.sellAsset.precision
|
|
3736
|
+
);
|
|
3737
|
+
}, [
|
|
3738
|
+
displayValues.isExactOutput,
|
|
3739
|
+
displayValues.sellAmountBaseUnit,
|
|
3740
|
+
displayValues.sellAssetUsdPrice,
|
|
3741
|
+
context.isSellAmountFiat,
|
|
3742
|
+
context.sellAmountFiat,
|
|
3743
|
+
context.sellAmount,
|
|
3744
|
+
context.sellAsset.precision,
|
|
3745
|
+
sellAmountCrypto
|
|
3746
|
+
]);
|
|
3610
3747
|
const { text: buttonText, disabled: isButtonDisabled } = useMemo9(() => {
|
|
3611
3748
|
if (isUnsupportedChain) {
|
|
3612
3749
|
if (!allowShapeshiftRedirect) return { text: "Route not supported", disabled: true };
|
|
@@ -3614,39 +3751,43 @@ var InputStep = ({
|
|
|
3614
3751
|
}
|
|
3615
3752
|
if (!sendAddress) return { text: "Connect Wallet", disabled: false };
|
|
3616
3753
|
if (!receiveAddress) return { text: "Enter receive address", disabled: true };
|
|
3617
|
-
|
|
3618
|
-
if (
|
|
3619
|
-
if (
|
|
3620
|
-
if (
|
|
3754
|
+
const drivingAmount = displayValues.isExactOutput ? context.buyAmountBaseUnit : context.sellAmount;
|
|
3755
|
+
if (!drivingAmount || drivingAmount === "0") return { text: "Enter an amount", disabled: true };
|
|
3756
|
+
if (displayValues.isLoadingRates) return { text: "Finding rates...", disabled: true };
|
|
3757
|
+
if (displayValues.ratesError) return { text: "No routes available", disabled: true };
|
|
3758
|
+
if (!displayValues.rates?.length) return { text: "No routes found", disabled: true };
|
|
3621
3759
|
return { text: "Swap", disabled: false };
|
|
3622
3760
|
}, [
|
|
3623
3761
|
isUnsupportedChain,
|
|
3624
3762
|
allowShapeshiftRedirect,
|
|
3625
3763
|
sendAddress,
|
|
3626
3764
|
receiveAddress,
|
|
3627
|
-
sellAmount,
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3765
|
+
context.sellAmount,
|
|
3766
|
+
displayValues.isExactOutput,
|
|
3767
|
+
context.buyAmountBaseUnit,
|
|
3768
|
+
displayValues.isLoadingRates,
|
|
3769
|
+
displayValues.ratesError,
|
|
3770
|
+
displayValues.rates
|
|
3631
3771
|
]);
|
|
3632
|
-
return /* @__PURE__ */ jsxs6(
|
|
3772
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3633
3773
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-swap-container", children: [
|
|
3634
3774
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-section ssw-sell", children: [
|
|
3635
3775
|
/* @__PURE__ */ jsx6("div", { className: "ssw-section-header", children: /* @__PURE__ */ jsx6("span", { className: "ssw-section-label", children: "Sell" }) }),
|
|
3636
3776
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-input-row", children: [
|
|
3637
|
-
isSellAmountFiat && /* @__PURE__ */ jsx6("span", { className: "ssw-fiat-prefix", children: "$" }),
|
|
3777
|
+
context.isSellAmountFiat && /* @__PURE__ */ jsx6("span", { className: "ssw-fiat-prefix", children: "$" }),
|
|
3638
3778
|
/* @__PURE__ */ jsx6(
|
|
3639
3779
|
"input",
|
|
3640
3780
|
{
|
|
3641
3781
|
type: "text",
|
|
3642
|
-
className: "ssw-amount-input"
|
|
3643
|
-
placeholder: "0",
|
|
3644
|
-
value:
|
|
3782
|
+
className: `ssw-amount-input${isSellAmountReadOnly ? " ssw-amount-input-locked" : ""}${isSellAmountPending ? " ssw-amount-input-pending" : ""}`,
|
|
3783
|
+
placeholder: isSellAmountPending ? "..." : "0",
|
|
3784
|
+
value: sellAmountValue,
|
|
3785
|
+
readOnly: isSellAmountReadOnly,
|
|
3645
3786
|
onChange: (e) => {
|
|
3646
3787
|
const raw = e.target.value.replace(/[^0-9.]/g, "");
|
|
3647
3788
|
const parts = raw.split(".");
|
|
3648
3789
|
const sanitized = parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : raw;
|
|
3649
|
-
onSellAmountChange(sanitized, sellAssetUsdPrice);
|
|
3790
|
+
onSellAmountChange(sanitized, displayValues.sellAssetUsdPrice);
|
|
3650
3791
|
}
|
|
3651
3792
|
}
|
|
3652
3793
|
),
|
|
@@ -3657,10 +3798,17 @@ var InputStep = ({
|
|
|
3657
3798
|
onClick: () => onOpenTokenModal("sell"),
|
|
3658
3799
|
type: "button",
|
|
3659
3800
|
children: [
|
|
3660
|
-
sellAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3801
|
+
context.sellAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3802
|
+
"img",
|
|
3803
|
+
{
|
|
3804
|
+
src: context.sellAsset.icon,
|
|
3805
|
+
alt: context.sellAsset.symbol,
|
|
3806
|
+
className: "ssw-token-icon"
|
|
3807
|
+
}
|
|
3808
|
+
) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.sellAsset.symbol.charAt(0) }),
|
|
3661
3809
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
|
|
3662
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: sellAsset.symbol }),
|
|
3663
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: sellChainInfo?.name ?? sellAsset.networkName ?? sellAsset.name })
|
|
3810
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.sellAsset.symbol }),
|
|
3811
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.sellChainInfo?.name ?? context.sellAsset.networkName ?? context.sellAsset.name })
|
|
3664
3812
|
] }),
|
|
3665
3813
|
/* @__PURE__ */ jsx6(
|
|
3666
3814
|
"svg",
|
|
@@ -3679,14 +3827,14 @@ var InputStep = ({
|
|
|
3679
3827
|
)
|
|
3680
3828
|
] }),
|
|
3681
3829
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
|
|
3682
|
-
sellAssetUsdPrice ? /* @__PURE__ */ jsxs6(
|
|
3830
|
+
!displayValues.sellAssetUsdPrice ? /* @__PURE__ */ jsx6("span", { className: "ssw-usd-value" }) : /* @__PURE__ */ jsxs6(
|
|
3683
3831
|
"button",
|
|
3684
3832
|
{
|
|
3685
3833
|
type: "button",
|
|
3686
3834
|
className: "ssw-usd-value ssw-usd-value-toggle",
|
|
3687
|
-
onClick: () => onToggleSellFiat(sellAssetUsdPrice),
|
|
3835
|
+
onClick: () => onToggleSellFiat(displayValues.sellAssetUsdPrice),
|
|
3688
3836
|
children: [
|
|
3689
|
-
/* @__PURE__ */ jsx6("span", { children: isSellAmountFiat ? `\u2248 ${
|
|
3837
|
+
/* @__PURE__ */ jsx6("span", { children: context.isSellAmountFiat ? `\u2248 ${sellAmountCrypto || "0"} ${context.sellAsset.symbol}` : displayValues.sellUsdValue }),
|
|
3690
3838
|
/* @__PURE__ */ jsx6(
|
|
3691
3839
|
"svg",
|
|
3692
3840
|
{
|
|
@@ -3702,13 +3850,14 @@ var InputStep = ({
|
|
|
3702
3850
|
)
|
|
3703
3851
|
]
|
|
3704
3852
|
}
|
|
3705
|
-
)
|
|
3706
|
-
hasAnyWalletAddress && (isSellBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : sellAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3853
|
+
),
|
|
3854
|
+
hasAnyWalletAddress && (displayValues.isSellBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.sellAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3707
3855
|
"Balance: ",
|
|
3708
|
-
sellAssetBalance.balanceFormatted,
|
|
3709
|
-
sellBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3710
|
-
"
|
|
3711
|
-
|
|
3856
|
+
displayValues.sellAssetBalance.balanceFormatted,
|
|
3857
|
+
displayValues.sellBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3858
|
+
" ",
|
|
3859
|
+
"(",
|
|
3860
|
+
displayValues.sellBalanceFiatValue,
|
|
3712
3861
|
")"
|
|
3713
3862
|
] })
|
|
3714
3863
|
] }) : null)
|
|
@@ -3742,10 +3891,15 @@ var InputStep = ({
|
|
|
3742
3891
|
"input",
|
|
3743
3892
|
{
|
|
3744
3893
|
type: "text",
|
|
3745
|
-
className: "ssw-amount-input"
|
|
3746
|
-
placeholder: "0",
|
|
3747
|
-
value:
|
|
3748
|
-
readOnly:
|
|
3894
|
+
className: `ssw-amount-input${isBuyAmountLocked ? " ssw-amount-input-locked" : ""}${isBuyAmountPending ? " ssw-amount-input-pending" : ""}`,
|
|
3895
|
+
placeholder: isBuyAmountPending ? "..." : "0",
|
|
3896
|
+
value: buyAmountValue,
|
|
3897
|
+
readOnly: isBuyAmountLocked,
|
|
3898
|
+
onChange: (e) => {
|
|
3899
|
+
const raw = e.target.value.replace(/[^0-9.]/g, "");
|
|
3900
|
+
const parts = raw.split(".");
|
|
3901
|
+
onBuyAmountChange(parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : raw);
|
|
3902
|
+
}
|
|
3749
3903
|
}
|
|
3750
3904
|
),
|
|
3751
3905
|
/* @__PURE__ */ jsxs6(
|
|
@@ -3756,10 +3910,17 @@ var InputStep = ({
|
|
|
3756
3910
|
disabled: isBuyAssetLocked,
|
|
3757
3911
|
type: "button",
|
|
3758
3912
|
children: [
|
|
3759
|
-
buyAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3913
|
+
context.buyAsset.icon ? /* @__PURE__ */ jsx6(
|
|
3914
|
+
"img",
|
|
3915
|
+
{
|
|
3916
|
+
src: context.buyAsset.icon,
|
|
3917
|
+
alt: context.buyAsset.symbol,
|
|
3918
|
+
className: "ssw-token-icon"
|
|
3919
|
+
}
|
|
3920
|
+
) : /* @__PURE__ */ jsx6("div", { className: "ssw-token-icon-placeholder", children: context.buyAsset.symbol.charAt(0) }),
|
|
3760
3921
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-token-info", children: [
|
|
3761
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: buyAsset.symbol }),
|
|
3762
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: buyChainInfo?.name ?? buyAsset.networkName ?? buyAsset.name })
|
|
3922
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-symbol", children: context.buyAsset.symbol }),
|
|
3923
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-token-chain", children: displayValues.buyChainInfo?.name ?? context.buyAsset.networkName ?? context.buyAsset.name })
|
|
3763
3924
|
] }),
|
|
3764
3925
|
!isBuyAssetLocked && /* @__PURE__ */ jsx6(
|
|
3765
3926
|
"svg",
|
|
@@ -3778,13 +3939,13 @@ var InputStep = ({
|
|
|
3778
3939
|
)
|
|
3779
3940
|
] }),
|
|
3780
3941
|
/* @__PURE__ */ jsxs6("div", { className: "ssw-section-footer", children: [
|
|
3781
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-usd-value", children: buyUsdValue }),
|
|
3782
|
-
hasAnyWalletAddress && (isBuyBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : buyAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3942
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-usd-value", children: displayValues.buyUsdValue }),
|
|
3943
|
+
hasAnyWalletAddress && (displayValues.isBuyBalanceLoading ? /* @__PURE__ */ jsx6("span", { className: "ssw-balance-skeleton" }) : displayValues.buyAssetBalance ? /* @__PURE__ */ jsxs6("span", { className: "ssw-balance", children: [
|
|
3783
3944
|
"Balance: ",
|
|
3784
|
-
buyAssetBalance.balanceFormatted,
|
|
3785
|
-
buyBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3945
|
+
displayValues.buyAssetBalance.balanceFormatted,
|
|
3946
|
+
displayValues.buyBalanceFiatValue && /* @__PURE__ */ jsxs6("span", { className: "ssw-balance-fiat", children: [
|
|
3786
3947
|
" (",
|
|
3787
|
-
buyBalanceFiatValue,
|
|
3948
|
+
displayValues.buyBalanceFiatValue,
|
|
3788
3949
|
")"
|
|
3789
3950
|
] })
|
|
3790
3951
|
] }) : null)
|
|
@@ -3796,26 +3957,30 @@ var InputStep = ({
|
|
|
3796
3957
|
receiveAddress,
|
|
3797
3958
|
isResolving: isReceiveAddressResolving,
|
|
3798
3959
|
buyChainId,
|
|
3960
|
+
isLocked: isReceiveAddressLocked,
|
|
3799
3961
|
onSetCustomReceiveAddress: setCustomReceiveAddress
|
|
3800
3962
|
}
|
|
3801
3963
|
)
|
|
3802
3964
|
] }),
|
|
3803
|
-
|
|
3965
|
+
amountBaseUnit && amountBaseUnit !== "0" && (displayValues.rates?.length || displayValues.isLoadingRates) && /* @__PURE__ */ jsx6("div", { className: "ssw-quotes", children: /* @__PURE__ */ jsx6(
|
|
3804
3966
|
QuoteSelector,
|
|
3805
3967
|
{
|
|
3806
|
-
rates: rates ?? [],
|
|
3807
|
-
selectedRate,
|
|
3968
|
+
rates: displayValues.rates ?? [],
|
|
3969
|
+
selectedRate: context.selectedRate,
|
|
3808
3970
|
onSelectRate,
|
|
3809
|
-
buyAsset,
|
|
3810
|
-
sellAsset,
|
|
3811
|
-
sellAmountBaseUnit,
|
|
3812
|
-
|
|
3813
|
-
|
|
3971
|
+
buyAsset: context.buyAsset,
|
|
3972
|
+
sellAsset: context.sellAsset,
|
|
3973
|
+
sellAmountBaseUnit: displayValues.sellAmountBaseUnit ?? "0",
|
|
3974
|
+
buyAmountBaseUnit: context.buyAmountBaseUnit ?? "0",
|
|
3975
|
+
isExactOutput: displayValues.isExactOutput,
|
|
3976
|
+
isLoading: displayValues.isLoadingRates,
|
|
3977
|
+
sellAssetUsdPrice: displayValues.sellAssetUsdPrice,
|
|
3978
|
+
buyAssetUsdPrice: displayValues.buyAssetUsdPrice
|
|
3814
3979
|
}
|
|
3815
3980
|
) }),
|
|
3816
|
-
networkFeeDisplay && /* @__PURE__ */ jsxs6("div", { className: "ssw-network-fee", children: [
|
|
3981
|
+
displayValues.networkFeeDisplay && /* @__PURE__ */ jsxs6("div", { className: "ssw-network-fee", children: [
|
|
3817
3982
|
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-label", children: "Est. network fee" }),
|
|
3818
|
-
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-value", children: networkFeeDisplay })
|
|
3983
|
+
/* @__PURE__ */ jsx6("span", { className: "ssw-network-fee-value", children: displayValues.networkFeeDisplay })
|
|
3819
3984
|
] }),
|
|
3820
3985
|
/* @__PURE__ */ jsx6(
|
|
3821
3986
|
"button",
|
|
@@ -3825,7 +3990,7 @@ var InputStep = ({
|
|
|
3825
3990
|
onClick: onButtonClick,
|
|
3826
3991
|
type: "button",
|
|
3827
3992
|
style: isQuoting ? { opacity: 0.7 } : void 0,
|
|
3828
|
-
children: isQuoting ? /* @__PURE__ */ jsxs6(
|
|
3993
|
+
children: isQuoting ? /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3829
3994
|
/* @__PURE__ */ jsxs6(
|
|
3830
3995
|
"svg",
|
|
3831
3996
|
{
|
|
@@ -4012,7 +4177,7 @@ var SettingsModal = ({ isOpen, onClose, onSlippageChange }) => {
|
|
|
4012
4177
|
|
|
4013
4178
|
// src/components/StatusStep.tsx
|
|
4014
4179
|
import { useMemo as useMemo10 } from "react";
|
|
4015
|
-
import { Fragment as
|
|
4180
|
+
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4016
4181
|
var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "ssw-step-explorer-link", children: [
|
|
4017
4182
|
"View on Explorer",
|
|
4018
4183
|
/* @__PURE__ */ jsx8(
|
|
@@ -4028,7 +4193,7 @@ var ExplorerLink = ({ url }) => /* @__PURE__ */ jsxs8("a", { href: url, target:
|
|
|
4028
4193
|
}
|
|
4029
4194
|
)
|
|
4030
4195
|
] });
|
|
4031
|
-
var StatusStep = () => {
|
|
4196
|
+
var StatusStep = ({ isPayment }) => {
|
|
4032
4197
|
const context = SwapMachineCtx.useSelector((s) => s.context);
|
|
4033
4198
|
const isPolling = SwapMachineCtx.useSelector((s) => s.matches("polling_status"));
|
|
4034
4199
|
const isComplete = SwapMachineCtx.useSelector((s) => s.matches("complete"));
|
|
@@ -4046,7 +4211,7 @@ var StatusStep = () => {
|
|
|
4046
4211
|
[error]
|
|
4047
4212
|
);
|
|
4048
4213
|
return /* @__PURE__ */ jsxs8("div", { className: "ssw-step-screen", children: [
|
|
4049
|
-
isPolling && /* @__PURE__ */ jsxs8(
|
|
4214
|
+
isPolling && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4050
4215
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-accent", children: /* @__PURE__ */ jsxs8(
|
|
4051
4216
|
"svg",
|
|
4052
4217
|
{
|
|
@@ -4067,7 +4232,7 @@ var StatusStep = () => {
|
|
|
4067
4232
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-subtitle", children: "Your swap is being processed\u2026" }),
|
|
4068
4233
|
explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl })
|
|
4069
4234
|
] }),
|
|
4070
|
-
isComplete && /* @__PURE__ */ jsxs8(
|
|
4235
|
+
isComplete && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4071
4236
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-success", children: /* @__PURE__ */ jsx8(
|
|
4072
4237
|
"svg",
|
|
4073
4238
|
{
|
|
@@ -4088,7 +4253,7 @@ var StatusStep = () => {
|
|
|
4088
4253
|
buyAsset.symbol
|
|
4089
4254
|
] }),
|
|
4090
4255
|
explorerUrl && /* @__PURE__ */ jsx8(ExplorerLink, { url: explorerUrl }),
|
|
4091
|
-
/* @__PURE__ */ jsx8("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx8(
|
|
4256
|
+
!isPayment && /* @__PURE__ */ jsx8("div", { className: "ssw-step-actions", children: /* @__PURE__ */ jsx8(
|
|
4092
4257
|
"button",
|
|
4093
4258
|
{
|
|
4094
4259
|
className: "ssw-action-btn",
|
|
@@ -4098,7 +4263,7 @@ var StatusStep = () => {
|
|
|
4098
4263
|
}
|
|
4099
4264
|
) })
|
|
4100
4265
|
] }),
|
|
4101
|
-
isError && /* @__PURE__ */ jsxs8(
|
|
4266
|
+
isError && /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
4102
4267
|
/* @__PURE__ */ jsx8("div", { className: "ssw-step-icon-circle ssw-ic-error", children: /* @__PURE__ */ jsxs8(
|
|
4103
4268
|
"svg",
|
|
4104
4269
|
{
|
|
@@ -4141,10 +4306,10 @@ var StatusStep = () => {
|
|
|
4141
4306
|
};
|
|
4142
4307
|
|
|
4143
4308
|
// src/components/TokenSelectModal.tsx
|
|
4144
|
-
import { bnOrZero as
|
|
4309
|
+
import { bnOrZero as bnOrZero2 } from "@shapeshiftoss/utils";
|
|
4145
4310
|
import { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo11, useRef as useRef6, useState as useState6 } from "react";
|
|
4146
4311
|
import { Virtuoso } from "react-virtuoso";
|
|
4147
|
-
import { Fragment as
|
|
4312
|
+
import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4148
4313
|
var VISIBLE_BUFFER = 10;
|
|
4149
4314
|
var useLockBodyScroll3 = (isLocked) => {
|
|
4150
4315
|
useEffect8(() => {
|
|
@@ -4325,7 +4490,7 @@ var TokenSelectModal = ({
|
|
|
4325
4490
|
const balance = balances[asset.assetId];
|
|
4326
4491
|
if (balance && balance.balance !== "0") {
|
|
4327
4492
|
const price = marketData?.[asset.assetId]?.price;
|
|
4328
|
-
const fiatValue = price ?
|
|
4493
|
+
const fiatValue = price ? bnOrZero2(balance.balance).div(bnOrZero2(10).pow(asset.precision)).times(bnOrZero2(price)).toNumber() : 0;
|
|
4329
4494
|
withBalance.push({ asset, fiatValue });
|
|
4330
4495
|
} else {
|
|
4331
4496
|
withoutBalance.push(asset);
|
|
@@ -4529,10 +4694,10 @@ var TokenSelectModal = ({
|
|
|
4529
4694
|
/* @__PURE__ */ jsx9("span", { className: "ssw-token-symbol", children: asset.symbol }),
|
|
4530
4695
|
/* @__PURE__ */ jsx9("span", { className: "ssw-token-name", children: chainInfo?.name ?? asset.networkName ?? asset.name })
|
|
4531
4696
|
] }),
|
|
4532
|
-
/* @__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(
|
|
4697
|
+
/* @__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: [
|
|
4533
4698
|
marketData?.[asset.assetId]?.price && /* @__PURE__ */ jsxs9("span", { className: "ssw-token-fiat-value", children: [
|
|
4534
4699
|
"$",
|
|
4535
|
-
|
|
4700
|
+
bnOrZero2(balance.balance).div(bnOrZero2(10).pow(asset.precision)).times(bnOrZero2(marketData[asset.assetId].price)).toNumber().toLocaleString(void 0, {
|
|
4536
4701
|
minimumFractionDigits: 2,
|
|
4537
4702
|
maximumFractionDigits: 2
|
|
4538
4703
|
})
|
|
@@ -4674,8 +4839,11 @@ var SwapWidgetContent = ({
|
|
|
4674
4839
|
showPoweredBy,
|
|
4675
4840
|
showConnectButton,
|
|
4676
4841
|
isBuyAssetLocked,
|
|
4842
|
+
isBuyAmountLocked,
|
|
4843
|
+
isReceiveAddressLocked,
|
|
4844
|
+
isPayment,
|
|
4677
4845
|
partnerCode,
|
|
4678
|
-
|
|
4846
|
+
canRedirectToShapeshift,
|
|
4679
4847
|
onSwapSuccess,
|
|
4680
4848
|
onSwapError,
|
|
4681
4849
|
sellFilters,
|
|
@@ -4699,11 +4867,12 @@ var SwapWidgetContent = ({
|
|
|
4699
4867
|
handleSellAssetSelect,
|
|
4700
4868
|
handleBuyAssetSelect,
|
|
4701
4869
|
handleSellAmountChange,
|
|
4870
|
+
handleBuyAmountChange,
|
|
4702
4871
|
handleToggleSellFiat,
|
|
4703
4872
|
handleSelectRate,
|
|
4704
4873
|
handleSlippageChange,
|
|
4705
4874
|
handleButtonClick
|
|
4706
|
-
} = useSwapHandlers({ partnerCode, allowShapeshiftRedirect });
|
|
4875
|
+
} = useSwapHandlers({ partnerCode, allowShapeshiftRedirect: canRedirectToShapeshift });
|
|
4707
4876
|
useSwapQuoting({ apiClient, rates, sellAssetBalance });
|
|
4708
4877
|
useSwapApproval();
|
|
4709
4878
|
useSwapExecution();
|
|
@@ -4799,17 +4968,20 @@ var SwapWidgetContent = ({
|
|
|
4799
4968
|
displayValues,
|
|
4800
4969
|
onOpenTokenModal: setTokenModalType,
|
|
4801
4970
|
onSellAmountChange: handleSellAmountChange,
|
|
4971
|
+
onBuyAmountChange: handleBuyAmountChange,
|
|
4802
4972
|
onToggleSellFiat: handleToggleSellFiat,
|
|
4803
4973
|
onSwapTokens: handleSwapTokens,
|
|
4804
4974
|
onSelectRate: handleSelectRate,
|
|
4805
4975
|
onButtonClick: handleButtonClick,
|
|
4806
4976
|
isBuyAssetLocked,
|
|
4807
|
-
|
|
4977
|
+
isBuyAmountLocked,
|
|
4978
|
+
isReceiveAddressLocked,
|
|
4979
|
+
allowShapeshiftRedirect: canRedirectToShapeshift
|
|
4808
4980
|
}
|
|
4809
4981
|
),
|
|
4810
4982
|
(state.matches("approval_needed") || state.matches("approving")) && /* @__PURE__ */ jsx11(ApprovalStep, {}),
|
|
4811
4983
|
state.matches("executing") && /* @__PURE__ */ jsx11(ExecutionStep, {}),
|
|
4812
|
-
(state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx11(StatusStep, {})
|
|
4984
|
+
(state.matches("polling_status") || state.matches("complete") || state.matches("error")) && /* @__PURE__ */ jsx11(StatusStep, { isPayment })
|
|
4813
4985
|
] }),
|
|
4814
4986
|
showPoweredBy && /* @__PURE__ */ jsxs11("div", { className: "ssw-powered-by", children: [
|
|
4815
4987
|
"Powered by",
|
|
@@ -4838,7 +5010,7 @@ var SwapWidgetContent = ({
|
|
|
4838
5010
|
disabledChainIds: (tokenModalType === "buy" ? buyFilters : sellFilters).disabledChainIds ?? [],
|
|
4839
5011
|
allowedChainIds: (tokenModalType === "buy" ? buyFilters : sellFilters).allowedChainIds,
|
|
4840
5012
|
allowedAssetIds: (tokenModalType === "buy" ? buyFilters : sellFilters).allowedAssetIds,
|
|
4841
|
-
allowShapeshiftRedirect
|
|
5013
|
+
allowShapeshiftRedirect: canRedirectToShapeshift
|
|
4842
5014
|
}
|
|
4843
5015
|
),
|
|
4844
5016
|
/* @__PURE__ */ jsx11(
|
|
@@ -4862,6 +5034,10 @@ var SwapWidgetCore = ({
|
|
|
4862
5034
|
showPoweredBy,
|
|
4863
5035
|
showConnectButton,
|
|
4864
5036
|
isBuyAssetLocked,
|
|
5037
|
+
defaultReceiveAddress,
|
|
5038
|
+
isReceiveAddressLocked,
|
|
5039
|
+
defaultBuyAmountCryptoBaseUnit,
|
|
5040
|
+
isBuyAmountLocked,
|
|
4865
5041
|
partnerCode,
|
|
4866
5042
|
allowShapeshiftRedirect,
|
|
4867
5043
|
onSwapSuccess,
|
|
@@ -4875,7 +5051,9 @@ var SwapWidgetCore = ({
|
|
|
4875
5051
|
const evm = useEvmSigning();
|
|
4876
5052
|
const bitcoin3 = useBitcoinSigning();
|
|
4877
5053
|
const solana3 = useSolanaSigning();
|
|
4878
|
-
const [customReceiveAddress, setCustomReceiveAddress] = useState8(
|
|
5054
|
+
const [customReceiveAddress, setCustomReceiveAddress] = useState8(
|
|
5055
|
+
defaultReceiveAddress ?? ""
|
|
5056
|
+
);
|
|
4879
5057
|
const sellChainId = SwapMachineCtx.useSelector((s) => s.context.sellAsset.chainId);
|
|
4880
5058
|
const buyChainId = SwapMachineCtx.useSelector((s) => s.context.buyAsset.chainId);
|
|
4881
5059
|
const sellChainType = getChainType(sellChainId);
|
|
@@ -4908,14 +5086,30 @@ var SwapWidgetCore = ({
|
|
|
4908
5086
|
() => addressForChain(buyChainType),
|
|
4909
5087
|
[addressForChain, buyChainType]
|
|
4910
5088
|
);
|
|
4911
|
-
const isCustomReceiveAddressValid = useMemo12(
|
|
4912
|
-
() => !!customReceiveAddress && validateAddress(customReceiveAddress, buyChainId).valid,
|
|
4913
|
-
[customReceiveAddress, buyChainId]
|
|
4914
|
-
);
|
|
4915
5089
|
const receiveAddress = useMemo12(
|
|
4916
|
-
() =>
|
|
4917
|
-
|
|
5090
|
+
() => resolveReceiveAddress({
|
|
5091
|
+
isLocked: isReceiveAddressLocked,
|
|
5092
|
+
defaultAddress: defaultReceiveAddress,
|
|
5093
|
+
customAddress: customReceiveAddress,
|
|
5094
|
+
walletAddress: walletReceiveAddress,
|
|
5095
|
+
buyChainId
|
|
5096
|
+
}),
|
|
5097
|
+
[
|
|
5098
|
+
isReceiveAddressLocked,
|
|
5099
|
+
defaultReceiveAddress,
|
|
5100
|
+
customReceiveAddress,
|
|
5101
|
+
walletReceiveAddress,
|
|
5102
|
+
buyChainId
|
|
5103
|
+
]
|
|
4918
5104
|
);
|
|
5105
|
+
useEffect10(() => {
|
|
5106
|
+
if (!isBuyAmountLocked) return;
|
|
5107
|
+
actorRef.send({
|
|
5108
|
+
type: "SET_BUY_AMOUNT",
|
|
5109
|
+
amount: defaultBuyAmountCryptoBaseUnit ? formatAmountForInput(defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision) : "",
|
|
5110
|
+
amountBaseUnit: defaultBuyAmountCryptoBaseUnit
|
|
5111
|
+
});
|
|
5112
|
+
}, [isBuyAmountLocked, defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision, actorRef]);
|
|
4919
5113
|
const initialSyncRef = useRef7(false);
|
|
4920
5114
|
useEffect10(() => {
|
|
4921
5115
|
if (initialSyncRef.current) return;
|
|
@@ -4923,6 +5117,11 @@ var SwapWidgetCore = ({
|
|
|
4923
5117
|
actorRef.send({ type: "SET_SELL_ASSET", asset: defaultSellAsset });
|
|
4924
5118
|
actorRef.send({ type: "SET_BUY_ASSET", asset: defaultBuyAsset });
|
|
4925
5119
|
actorRef.send({ type: "SET_SLIPPAGE", slippage: defaultSlippage });
|
|
5120
|
+
actorRef.send({
|
|
5121
|
+
type: "SET_BUY_AMOUNT",
|
|
5122
|
+
amount: defaultBuyAmountCryptoBaseUnit ? formatAmountForInput(defaultBuyAmountCryptoBaseUnit, defaultBuyAsset.precision) : "",
|
|
5123
|
+
amountBaseUnit: defaultBuyAmountCryptoBaseUnit
|
|
5124
|
+
});
|
|
4926
5125
|
}, [actorRef]);
|
|
4927
5126
|
useEffect10(() => {
|
|
4928
5127
|
actorRef.send({ type: "SET_SEND_ADDRESS", address: sendAddress });
|
|
@@ -4939,6 +5138,7 @@ var SwapWidgetCore = ({
|
|
|
4939
5138
|
sendAddress,
|
|
4940
5139
|
receiveAddress,
|
|
4941
5140
|
isReceiveAddressResolving,
|
|
5141
|
+
isReceiveAddressBlocked: isReceiveAddressLocked && !receiveAddress,
|
|
4942
5142
|
customReceiveAddress,
|
|
4943
5143
|
setCustomReceiveAddress,
|
|
4944
5144
|
evm,
|
|
@@ -4949,12 +5149,16 @@ var SwapWidgetCore = ({
|
|
|
4949
5149
|
sendAddress,
|
|
4950
5150
|
receiveAddress,
|
|
4951
5151
|
isReceiveAddressResolving,
|
|
5152
|
+
isReceiveAddressLocked,
|
|
4952
5153
|
customReceiveAddress,
|
|
4953
5154
|
evm,
|
|
4954
5155
|
bitcoin3,
|
|
4955
5156
|
solana3
|
|
4956
5157
|
]
|
|
4957
5158
|
);
|
|
5159
|
+
const hasLockedBuyAmount = isBuyAmountLocked && !!defaultBuyAmountCryptoBaseUnit;
|
|
5160
|
+
const isPayment = hasLockedBuyAmount && isReceiveAddressLocked && !!defaultReceiveAddress;
|
|
5161
|
+
const canRedirectToShapeshift = allowShapeshiftRedirect && !hasLockedBuyAmount && !isReceiveAddressLocked;
|
|
4958
5162
|
return /* @__PURE__ */ jsx11(SwapWalletProvider, { value: walletValue, children: /* @__PURE__ */ jsx11(
|
|
4959
5163
|
SwapWidgetContent,
|
|
4960
5164
|
{
|
|
@@ -4962,9 +5166,12 @@ var SwapWidgetCore = ({
|
|
|
4962
5166
|
theme,
|
|
4963
5167
|
showPoweredBy,
|
|
4964
5168
|
showConnectButton,
|
|
4965
|
-
isBuyAssetLocked,
|
|
5169
|
+
isBuyAssetLocked: isBuyAssetLocked || hasLockedBuyAmount,
|
|
5170
|
+
isBuyAmountLocked,
|
|
5171
|
+
isReceiveAddressLocked,
|
|
5172
|
+
isPayment,
|
|
4966
5173
|
partnerCode,
|
|
4967
|
-
|
|
5174
|
+
canRedirectToShapeshift,
|
|
4968
5175
|
onSwapSuccess,
|
|
4969
5176
|
onSwapError,
|
|
4970
5177
|
sellFilters,
|
|
@@ -4993,6 +5200,10 @@ var SwapWidget = (props) => {
|
|
|
4993
5200
|
showPoweredBy: props.showPoweredBy ?? true,
|
|
4994
5201
|
showConnectButton: props.showConnectButton ?? true,
|
|
4995
5202
|
isBuyAssetLocked: props.isBuyAssetLocked ?? false,
|
|
5203
|
+
defaultReceiveAddress: props.defaultReceiveAddress,
|
|
5204
|
+
isReceiveAddressLocked: props.isReceiveAddressLocked ?? false,
|
|
5205
|
+
defaultBuyAmountCryptoBaseUnit: props.defaultBuyAmountCryptoBaseUnit,
|
|
5206
|
+
isBuyAmountLocked: props.isBuyAmountLocked ?? false,
|
|
4996
5207
|
partnerCode: props.partnerCode,
|
|
4997
5208
|
allowShapeshiftRedirect: props.allowShapeshiftRedirect ?? true,
|
|
4998
5209
|
onSwapSuccess: props.onSwapSuccess,
|