@ape.swap/bonds-sdk 6.1.15-test.0 → 6.1.17-test.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ConnectButton/index.js +3 -4
- package/dist/components/ConnectButton/index.js.map +1 -1
- package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js +5 -3
- package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js +7 -2
- package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js +5 -1
- package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js +9 -2
- package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js.map +1 -1
- package/dist/config/constants/aptosZapTokens.js +1 -15
- package/dist/config/constants/aptosZapTokens.js.map +1 -1
- package/dist/config/constants/walletConnectors.d.ts +6 -0
- package/dist/config/constants/walletConnectors.js +25 -0
- package/dist/config/constants/walletConnectors.js.map +1 -0
- package/dist/constants/aptosConstants.js +1 -5
- package/dist/constants/aptosConstants.js.map +1 -1
- package/dist/constants/suiConstants.js +1 -3
- package/dist/constants/suiConstants.js.map +1 -1
- package/dist/state/useSDKConfig.d.ts +13 -3
- package/dist/state/useSDKConfig.js +22 -10
- package/dist/state/useSDKConfig.js.map +1 -1
- package/dist/utils/aptosHelpers.js +1 -25
- package/dist/utils/aptosHelpers.js.map +1 -1
- package/dist/views/BuyBond/BuyBondModal.js +14 -3
- package/dist/views/BuyBond/BuyBondModal.js.map +1 -1
- package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js +3 -1
- package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js.map +1 -1
- package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js +5 -1
- package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js.map +1 -1
- package/package.json +1 -2
- package/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js +0 -39
- package/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js.map +0 -1
- package/dist/components/ConnectButton/AppKitButton.d.ts +0 -3
- package/dist/components/ConnectButton/AppKitButton.js +0 -9
- package/dist/components/ConnectButton/AppKitButton.js.map +0 -1
- package/dist/components/ConnectButton/RainbowKitButton.d.ts +0 -3
- package/dist/components/ConnectButton/RainbowKitButton.js +0 -22
- package/dist/components/ConnectButton/RainbowKitButton.js.map +0 -1
- package/dist/config/constants/suiCallbacks.d.ts +0 -2
- package/dist/config/constants/suiCallbacks.js +0 -17
- package/dist/config/constants/suiCallbacks.js.map +0 -1
- package/dist/config/constants/suiZapTokens.js +0 -36
- package/dist/config/constants/suiZapTokens.js.map +0 -1
- package/dist/state/zap/useAptosZapQuote.js +0 -83
- package/dist/state/zap/useAptosZapQuote.js.map +0 -1
- package/dist/state/zap/useSuiZapQuote.js +0 -96
- package/dist/state/zap/useSuiZapQuote.js.map +0 -1
- package/dist/views/BuyBond/BuyComponentAptos.js +0 -349
- package/dist/views/BuyBond/BuyComponentAptos.js.map +0 -1
- package/dist/views/BuyBond/BuyComponentSui.js +0 -500
- package/dist/views/BuyBond/BuyComponentSui.js.map +0 -1
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import BigNumber from 'bignumber.js';
|
|
3
|
-
import { ChainId } from '@ape.swap/apeswap-lists';
|
|
4
|
-
import { useQuery } from '@tanstack/react-query';
|
|
5
|
-
import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
|
|
6
|
-
import useDebounce from '../../hooks/useDebounce.js';
|
|
7
|
-
import axios from 'axios';
|
|
8
|
-
|
|
9
|
-
// =============================================================================
|
|
10
|
-
// useAptosZapQuote — Panora DEX aggregator quote for Aptos zap
|
|
11
|
-
// =============================================================================
|
|
12
|
-
//
|
|
13
|
-
// Mirrors useJupiterSolanaQuote.ts: fetches a swap quote from Panora
|
|
14
|
-
// (Aptos DEX aggregator) when the user selects an input token different
|
|
15
|
-
// from the bond's principal token.
|
|
16
|
-
//
|
|
17
|
-
// Panora API: POST https://api.panora.exchange/swap
|
|
18
|
-
// Docs: https://docs.panora.exchange/developer/swap/api
|
|
19
|
-
const PANORA_API_URL = 'https://api.panora.exchange/swap';
|
|
20
|
-
// TODO(aptos): Move to environment variable or SDK config. This is Panora's
|
|
21
|
-
// public API key — monitor usage and rotate if needed for production.
|
|
22
|
-
const PANORA_PUBLIC_API_KEY = 'a4^KV_EaTf4MW#ZdvgGKX#HUD^3IFEAOV_kzpIE^3BQGA8pDnrkT7JcIy#HNlLGi';
|
|
23
|
-
const useAptosZapQuote = (typedValue, inputToken, bond, account, slippage = 0.5) => {
|
|
24
|
-
const debouncedInput = useDebounce(typedValue, 400);
|
|
25
|
-
const principalTokenAddress = bond?.lpToken?.address?.[ChainId.APTOS];
|
|
26
|
-
const inputTokenAddress = inputToken?.faAddress;
|
|
27
|
-
// Panora uses human-readable amounts (no decimals conversion needed)
|
|
28
|
-
const inputAmount = new BigNumber(debouncedInput ?? '0').toString();
|
|
29
|
-
const queryParams = useMemo(() => {
|
|
30
|
-
if (!inputTokenAddress ||
|
|
31
|
-
!principalTokenAddress ||
|
|
32
|
-
inputAmount === '0' ||
|
|
33
|
-
inputAmount === 'NaN' ||
|
|
34
|
-
!account ||
|
|
35
|
-
inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
fromTokenAddress: inputTokenAddress,
|
|
40
|
-
toTokenAddress: principalTokenAddress,
|
|
41
|
-
fromTokenAmount: inputAmount,
|
|
42
|
-
toWalletAddress: account,
|
|
43
|
-
slippagePercentage: slippage.toString(),
|
|
44
|
-
};
|
|
45
|
-
}, [inputTokenAddress, principalTokenAddress, inputAmount, account, slippage]);
|
|
46
|
-
const fetchPanoraQuote = async () => {
|
|
47
|
-
if (!queryParams)
|
|
48
|
-
return null;
|
|
49
|
-
const params = new URLSearchParams(queryParams);
|
|
50
|
-
const response = await axios.post(`${PANORA_API_URL}?${params.toString()}`, null, {
|
|
51
|
-
headers: { 'x-api-key': PANORA_PUBLIC_API_KEY },
|
|
52
|
-
});
|
|
53
|
-
const data = response.data;
|
|
54
|
-
// Panora returns the quote at the top level. Fall back to quotes[] if present.
|
|
55
|
-
if (data?.quotes?.length)
|
|
56
|
-
return data.quotes[0];
|
|
57
|
-
if (data?.txData)
|
|
58
|
-
return data;
|
|
59
|
-
return null;
|
|
60
|
-
};
|
|
61
|
-
const { data: quoteData, isLoading, isFetching, error, } = useQuery({
|
|
62
|
-
queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'panora-aptos', queryParams],
|
|
63
|
-
queryFn: fetchPanoraQuote,
|
|
64
|
-
refetchInterval: 60000,
|
|
65
|
-
enabled: !!queryParams,
|
|
66
|
-
retry: 1,
|
|
67
|
-
staleTime: 30000,
|
|
68
|
-
});
|
|
69
|
-
const zapError = !!error;
|
|
70
|
-
const principalDecimals = bond?.lpToken?.decimals?.[ChainId.APTOS] ?? 6;
|
|
71
|
-
// Panora returns amounts in human-readable format (no decimal conversion needed)
|
|
72
|
-
const estimatedDepositAmount = quoteData?.toTokenAmount
|
|
73
|
-
? new BigNumber(quoteData.toTokenAmount).toFixed(principalDecimals)
|
|
74
|
-
: '0';
|
|
75
|
-
const minimumDepositAmount = quoteData?.minToTokenAmount
|
|
76
|
-
? new BigNumber(quoteData.minToTokenAmount).toFixed(principalDecimals)
|
|
77
|
-
: '0';
|
|
78
|
-
const zapLoading = isLoading || isFetching;
|
|
79
|
-
return [zapLoading, quoteData ?? null, estimatedDepositAmount, zapError, minimumDepositAmount];
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export { useAptosZapQuote as default };
|
|
83
|
-
//# sourceMappingURL=useAptosZapQuote.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useAptosZapQuote.js","sources":["../../../src/state/zap/useAptosZapQuote.ts"],"sourcesContent":["// =============================================================================\n// useAptosZapQuote — Panora DEX aggregator quote for Aptos zap\n// =============================================================================\n//\n// Mirrors useJupiterSolanaQuote.ts: fetches a swap quote from Panora\n// (Aptos DEX aggregator) when the user selects an input token different\n// from the bond's principal token.\n//\n// Panora API: POST https://api.panora.exchange/swap\n// Docs: https://docs.panora.exchange/developer/swap/api\n\nimport { useMemo } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BondsData } from '../../types/bonds'\nimport useDebounce from '../../hooks/useDebounce'\nimport axios from 'axios'\nimport type { AptosZapToken } from '../../config/constants/aptosZapTokens'\n\nconst PANORA_API_URL = 'https://api.panora.exchange/swap'\n// TODO(aptos): Move to environment variable or SDK config. This is Panora's\n// public API key — monitor usage and rotate if needed for production.\nconst PANORA_PUBLIC_API_KEY = 'a4^KV_EaTf4MW#ZdvgGKX#HUD^3IFEAOV_kzpIE^3BQGA8pDnrkT7JcIy#HNlLGi'\n\nexport interface PanoraQuote {\n toTokenAmount: string\n toTokenAmountUSD: string | null\n priceImpact: string | null\n slippagePercentage: string\n minToTokenAmount: string\n feeTokenAmount: string\n txData: Record<string, unknown>\n}\n\n// Panora /swap returns the quote at the top level (not inside a `quotes` array).\nexport interface PanoraSwapResponse extends PanoraQuote {\n fromToken: { address: string; decimals: number; current_price: string }\n toToken: { address: string; decimals: number; current_price: string }\n fromTokenAmount: string\n fromTokenAmountUSD: string | null\n quotes?: PanoraQuote[] // legacy — may not exist\n}\n\nconst useAptosZapQuote = (\n typedValue: string,\n inputToken: AptosZapToken | undefined,\n bond: BondsData | undefined,\n account?: string,\n slippage = 0.5,\n): [\n loading: boolean,\n response: PanoraQuote | null,\n depositAmount: string,\n error: boolean,\n minimumDepositAmount: string,\n] => {\n const debouncedInput = useDebounce(typedValue, 400)\n\n const principalTokenAddress = bond?.lpToken?.address?.[ChainId.APTOS]\n const inputTokenAddress = inputToken?.faAddress\n\n // Panora uses human-readable amounts (no decimals conversion needed)\n const inputAmount = new BigNumber(debouncedInput ?? '0').toString()\n\n const queryParams = useMemo(() => {\n if (\n !inputTokenAddress ||\n !principalTokenAddress ||\n inputAmount === '0' ||\n inputAmount === 'NaN' ||\n !account ||\n inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()\n ) {\n return null\n }\n\n return {\n fromTokenAddress: inputTokenAddress,\n toTokenAddress: principalTokenAddress,\n fromTokenAmount: inputAmount,\n toWalletAddress: account,\n slippagePercentage: slippage.toString(),\n }\n }, [inputTokenAddress, principalTokenAddress, inputAmount, account, slippage])\n\n const fetchPanoraQuote = async (): Promise<PanoraQuote | null> => {\n if (!queryParams) return null\n\n const params = new URLSearchParams(queryParams)\n const response = await axios.post<PanoraSwapResponse>(`${PANORA_API_URL}?${params.toString()}`, null, {\n headers: { 'x-api-key': PANORA_PUBLIC_API_KEY },\n })\n\n const data = response.data\n // Panora returns the quote at the top level. Fall back to quotes[] if present.\n if (data?.quotes?.length) return data.quotes[0]\n if (data?.txData) return data as PanoraQuote\n return null\n }\n\n const {\n data: quoteData,\n isLoading,\n isFetching,\n error,\n } = useQuery({\n queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'panora-aptos', queryParams],\n queryFn: fetchPanoraQuote,\n refetchInterval: 60000,\n enabled: !!queryParams,\n retry: 1,\n staleTime: 30000,\n })\n\n const zapError = !!error\n\n const principalDecimals = bond?.lpToken?.decimals?.[ChainId.APTOS] ?? 6\n\n // Panora returns amounts in human-readable format (no decimal conversion needed)\n const estimatedDepositAmount = quoteData?.toTokenAmount\n ? new BigNumber(quoteData.toTokenAmount).toFixed(principalDecimals)\n : '0'\n\n const minimumDepositAmount = quoteData?.minToTokenAmount\n ? new BigNumber(quoteData.minToTokenAmount).toFixed(principalDecimals)\n : '0'\n\n const zapLoading = isLoading || isFetching\n\n return [zapLoading, quoteData ?? null, estimatedDepositAmount, zapError, minimumDepositAmount]\n}\n\nexport default useAptosZapQuote\n"],"names":[],"mappings":"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"}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import BigNumber from 'bignumber.js';
|
|
3
|
-
import { ChainId } from '@ape.swap/apeswap-lists';
|
|
4
|
-
import { useQuery } from '@tanstack/react-query';
|
|
5
|
-
import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
|
|
6
|
-
import useDebounce from '../../hooks/useDebounce.js';
|
|
7
|
-
import axios from 'axios';
|
|
8
|
-
import '../../constants/suiConstants.js';
|
|
9
|
-
|
|
10
|
-
// =============================================================================
|
|
11
|
-
// useSuiZapQuote — Aftermath Finance DEX aggregator quote for Sui zap
|
|
12
|
-
// =============================================================================
|
|
13
|
-
//
|
|
14
|
-
// Mainnet: fetches a swap quote from Aftermath Finance (Sui DEX aggregator)
|
|
15
|
-
// when the user selects an input token different from the bond's principal token.
|
|
16
|
-
//
|
|
17
|
-
// Testnet: no DEX aggregator supports Sui testnet or our custom test tokens.
|
|
18
|
-
// Returns a mock quote calculated from fallback prices so the full zap UI and
|
|
19
|
-
// two-TX flow (mint → deposit) can be tested end-to-end.
|
|
20
|
-
//
|
|
21
|
-
// Aftermath API: POST https://aftermath.finance/api/router/trade-route
|
|
22
|
-
const AFTERMATH_API_URL = 'https://aftermath.finance/api/router/trade-route';
|
|
23
|
-
const AFTERMATH_TX_API_URL = 'https://aftermath.finance/api/router/transactions/trade';
|
|
24
|
-
/** Parse Aftermath amount strings — they may have a trailing "n" (BigInt notation) */
|
|
25
|
-
const parseAftermathAmount = (amount) => {
|
|
26
|
-
return amount.replace(/n$/, '');
|
|
27
|
-
};
|
|
28
|
-
const useSuiZapQuote = (typedValue, inputToken, bond, account, slippage = 0.5) => {
|
|
29
|
-
const debouncedInput = useDebounce(typedValue, 400);
|
|
30
|
-
const principalTokenAddress = bond?.lpToken?.address?.[ChainId.SUI];
|
|
31
|
-
const inputTokenAddress = inputToken?.address?.[ChainId.SUI];
|
|
32
|
-
// Aftermath uses atomic units — convert from human-readable
|
|
33
|
-
const inputDecimals = inputToken?.decimals?.[ChainId.SUI] ?? 9;
|
|
34
|
-
const inputAmountAtomic = useMemo(() => {
|
|
35
|
-
const val = new BigNumber(debouncedInput ?? '0');
|
|
36
|
-
if (val.isNaN() || val.lte(0))
|
|
37
|
-
return '0';
|
|
38
|
-
return val.times(new BigNumber(10).pow(inputDecimals)).integerValue(BigNumber.ROUND_FLOOR).toFixed(0);
|
|
39
|
-
}, [debouncedInput, inputDecimals]);
|
|
40
|
-
const principalDecimals = bond?.lpToken?.decimals?.[ChainId.SUI] ?? 6;
|
|
41
|
-
const queryParams = useMemo(() => {
|
|
42
|
-
if (!inputTokenAddress ||
|
|
43
|
-
!principalTokenAddress ||
|
|
44
|
-
inputAmountAtomic === '0' ||
|
|
45
|
-
!account ||
|
|
46
|
-
inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
coinInType: inputTokenAddress,
|
|
51
|
-
coinOutType: principalTokenAddress,
|
|
52
|
-
coinInAmount: inputAmountAtomic,
|
|
53
|
-
};
|
|
54
|
-
}, [inputTokenAddress, principalTokenAddress, inputAmountAtomic, account]);
|
|
55
|
-
// -------------------------------------------------------------------------
|
|
56
|
-
// Mainnet: fetch real quote from Aftermath
|
|
57
|
-
// -------------------------------------------------------------------------
|
|
58
|
-
const fetchAftermathQuote = async () => {
|
|
59
|
-
if (!queryParams)
|
|
60
|
-
return null;
|
|
61
|
-
const response = await axios.post(AFTERMATH_API_URL, queryParams);
|
|
62
|
-
const data = response.data;
|
|
63
|
-
if (!data?.coinOut?.amount)
|
|
64
|
-
return null;
|
|
65
|
-
return data;
|
|
66
|
-
};
|
|
67
|
-
const { data: quoteData, isLoading, isFetching, error, } = useQuery({
|
|
68
|
-
queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'aftermath-sui', queryParams],
|
|
69
|
-
queryFn: fetchAftermathQuote,
|
|
70
|
-
refetchInterval: 60000,
|
|
71
|
-
enabled: !!queryParams,
|
|
72
|
-
retry: 1,
|
|
73
|
-
staleTime: 30000,
|
|
74
|
-
});
|
|
75
|
-
// Use testnet mock on testnet, real quote on mainnet
|
|
76
|
-
const activeQuote = quoteData ?? null;
|
|
77
|
-
const zapError = !!error;
|
|
78
|
-
// Convert amounts to human-readable
|
|
79
|
-
const estimatedDepositAmount = activeQuote?.coinOut?.amount
|
|
80
|
-
? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))
|
|
81
|
-
.div(new BigNumber(10).pow(principalDecimals))
|
|
82
|
-
.toFixed(principalDecimals)
|
|
83
|
-
: '0';
|
|
84
|
-
// Apply slippage for minimum deposit amount
|
|
85
|
-
const minimumDepositAmount = activeQuote?.coinOut?.amount
|
|
86
|
-
? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))
|
|
87
|
-
.div(new BigNumber(10).pow(principalDecimals))
|
|
88
|
-
.times(1 - slippage / 100)
|
|
89
|
-
.toFixed(principalDecimals)
|
|
90
|
-
: '0';
|
|
91
|
-
const zapLoading = isLoading || isFetching ;
|
|
92
|
-
return [zapLoading, activeQuote, estimatedDepositAmount, zapError, minimumDepositAmount];
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export { AFTERMATH_TX_API_URL, useSuiZapQuote as default };
|
|
96
|
-
//# sourceMappingURL=useSuiZapQuote.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useSuiZapQuote.js","sources":["../../../src/state/zap/useSuiZapQuote.ts"],"sourcesContent":["// =============================================================================\n// useSuiZapQuote — Aftermath Finance DEX aggregator quote for Sui zap\n// =============================================================================\n//\n// Mainnet: fetches a swap quote from Aftermath Finance (Sui DEX aggregator)\n// when the user selects an input token different from the bond's principal token.\n//\n// Testnet: no DEX aggregator supports Sui testnet or our custom test tokens.\n// Returns a mock quote calculated from fallback prices so the full zap UI and\n// two-TX flow (mint → deposit) can be tested end-to-end.\n//\n// Aftermath API: POST https://aftermath.finance/api/router/trade-route\n\nimport { useMemo } from 'react'\nimport BigNumber from 'bignumber.js'\nimport { ChainId, Token } from '@ape.swap/apeswap-lists'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BondsData } from '../../types/bonds'\nimport useDebounce from '../../hooks/useDebounce'\nimport axios from 'axios'\nimport { IS_SUI_MAINNET } from '../../constants/suiConstants'\n\nconst AFTERMATH_API_URL = 'https://aftermath.finance/api/router/trade-route'\nconst AFTERMATH_TX_API_URL = 'https://aftermath.finance/api/router/transactions/trade'\n\ninterface AftermathCoinInfo {\n type: string\n amount: string // atomic units with BigInt \"n\" suffix, e.g. \"963906n\"\n tradeFee: string\n}\n\nexport interface AftermathTradeRoute {\n routes: Array<{\n paths: Array<Record<string, unknown>>\n portion: string\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n }>\n coinIn: AftermathCoinInfo\n coinOut: AftermathCoinInfo\n spotPrice: number\n netTradeFeePercentage: number\n}\n\n/** Parse Aftermath amount strings — they may have a trailing \"n\" (BigInt notation) */\nconst parseAftermathAmount = (amount: string): string => {\n return amount.replace(/n$/, '')\n}\n\nconst useSuiZapQuote = (\n typedValue: string,\n inputToken: Token | undefined,\n bond: BondsData | undefined,\n account?: string,\n slippage = 0.5,\n): [\n loading: boolean,\n response: AftermathTradeRoute | null,\n depositAmount: string,\n error: boolean,\n minimumDepositAmount: string,\n] => {\n const debouncedInput = useDebounce(typedValue, 400)\n\n const principalTokenAddress = bond?.lpToken?.address?.[ChainId.SUI]\n const inputTokenAddress = inputToken?.address?.[ChainId.SUI]\n\n // Aftermath uses atomic units — convert from human-readable\n const inputDecimals = inputToken?.decimals?.[ChainId.SUI] ?? 9\n const inputAmountAtomic = useMemo(() => {\n const val = new BigNumber(debouncedInput ?? '0')\n if (val.isNaN() || val.lte(0)) return '0'\n return val.times(new BigNumber(10).pow(inputDecimals)).integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n }, [debouncedInput, inputDecimals])\n\n const principalDecimals = bond?.lpToken?.decimals?.[ChainId.SUI] ?? 6\n\n const queryParams = useMemo(() => {\n if (\n !inputTokenAddress ||\n !principalTokenAddress ||\n inputAmountAtomic === '0' ||\n !account ||\n inputTokenAddress.toLowerCase() === principalTokenAddress.toLowerCase()\n ) {\n return null\n }\n\n return {\n coinInType: inputTokenAddress,\n coinOutType: principalTokenAddress,\n coinInAmount: inputAmountAtomic,\n }\n }, [inputTokenAddress, principalTokenAddress, inputAmountAtomic, account])\n\n // -------------------------------------------------------------------------\n // Mainnet: fetch real quote from Aftermath\n // -------------------------------------------------------------------------\n const fetchAftermathQuote = async (): Promise<AftermathTradeRoute | null> => {\n if (!queryParams) return null\n\n const response = await axios.post<AftermathTradeRoute>(AFTERMATH_API_URL, queryParams)\n const data = response.data\n if (!data?.coinOut?.amount) return null\n return data\n }\n\n const {\n data: quoteData,\n isLoading,\n isFetching,\n error,\n } = useQuery({\n queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, 'aftermath-sui', queryParams],\n queryFn: fetchAftermathQuote,\n refetchInterval: 60000,\n enabled: IS_SUI_MAINNET && !!queryParams,\n retry: 1,\n staleTime: 30000,\n })\n\n // Use testnet mock on testnet, real quote on mainnet\n const activeQuote = quoteData ?? null\n const zapError = !!error\n\n // Convert amounts to human-readable\n const estimatedDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .toFixed(principalDecimals)\n : '0'\n\n // Apply slippage for minimum deposit amount\n const minimumDepositAmount = activeQuote?.coinOut?.amount\n ? new BigNumber(parseAftermathAmount(activeQuote.coinOut.amount))\n .div(new BigNumber(10).pow(principalDecimals))\n .times(1 - slippage / 100)\n .toFixed(principalDecimals)\n : '0'\n\n const zapLoading = IS_SUI_MAINNET ? isLoading || isFetching : false\n\n return [zapLoading, activeQuote, estimatedDepositAmount, zapError, minimumDepositAmount]\n}\n\nexport { AFTERMATH_TX_API_URL }\n\nexport default useSuiZapQuote\n"],"names":[],"mappings":"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"}
|
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs, Fragment } from 'theme-ui/jsx-runtime';
|
|
2
|
-
import { useState, useCallback, useEffect } from 'react';
|
|
3
|
-
import BigNumber from 'bignumber.js';
|
|
4
|
-
import { ChainId } from '@ape.swap/apeswap-lists';
|
|
5
|
-
import useBondsData from '../../state/bonds/useBondsData.js';
|
|
6
|
-
import { useSDKConfig } from '../../state/useSDKConfig.js';
|
|
7
|
-
import { usePopups } from '../../state/popups/usePopups.js';
|
|
8
|
-
import { useSlippage } from '../../state/slippage/useSlippage.js';
|
|
9
|
-
import { formatUSDNumber, getMaxBuy, getPayoutAmount, getPrincipalAmount } from '../../utils/displayHelpers.js';
|
|
10
|
-
import { formatNumberSI } from '../../utils/formatNumber.js';
|
|
11
|
-
import { findHighestTrueBondPrice } from '../../utils/bondPriceHelpers.js';
|
|
12
|
-
import { reportError } from '../../utils/reportError.js';
|
|
13
|
-
import { MCBuyComponentStyles } from '../../utils/campaignStyles.js';
|
|
14
|
-
import track from '../../utils/track.js';
|
|
15
|
-
import { remove0xPrefix } from '../../utils/remove0xPrefix.js';
|
|
16
|
-
import { getSymbol } from '../../utils/getNativeTicker.js';
|
|
17
|
-
import useAPTAccount from '../../hooks/accounts/useAPTAccount.js';
|
|
18
|
-
import useTokenFromZapList from '../../hooks/useTokenFromZapList.js';
|
|
19
|
-
import useSortedZapList from '../../hooks/useSortedZapList.js';
|
|
20
|
-
import useAptosZapQuote from '../../state/zap/useAptosZapQuote.js';
|
|
21
|
-
import { findAptosZapToken } from '../../config/constants/aptosZapTokens.js';
|
|
22
|
-
import ConnectAptosWalletButton from '../../components/ConnectAptosWalletButton/ConnectAptosWalletButton.js';
|
|
23
|
-
import TokenSelectorPanel from '../../components/TokenSelectorPanel/index.js';
|
|
24
|
-
import BondModalHeader from './components/BondModalHeader.js';
|
|
25
|
-
import BondCards from './components/BondCards/BondCards.js';
|
|
26
|
-
import Estimations from './components/Estimations.js';
|
|
27
|
-
import ProjectDescription from './components/ProjectDescription.js';
|
|
28
|
-
import Flex from '../../components/uikit-sdk/Flex/index.js';
|
|
29
|
-
import Text from '../../components/uikit-sdk/Text/index.js';
|
|
30
|
-
import Button from '../../components/uikit-sdk/Button/Button.js';
|
|
31
|
-
import SafeHTMLComponent from '../../components/SafeHTMLComponent/index.js';
|
|
32
|
-
import { APTOS_DEPOSIT_FUNCTION } from '../../constants/aptosConstants.js';
|
|
33
|
-
import { getAptosClient, readAptosMarketInfo, extractDepositEvent, extractBillMinted } from '../../utils/aptosHelpers.js';
|
|
34
|
-
|
|
35
|
-
const BuyComponentAptos = ({ onDismiss, bondAddress, bondChain, isProjectView, setBillId, }) => {
|
|
36
|
-
const SDKConfig = useSDKConfig();
|
|
37
|
-
// Hooks
|
|
38
|
-
const { address: aptosAccount, signAndSubmitTransaction } = useAPTAccount();
|
|
39
|
-
const { data: bonds } = useBondsData();
|
|
40
|
-
const { addToastError, addToastSuccess } = usePopups();
|
|
41
|
-
const { solSlippage: slippage } = useSlippage(); // reuse Sol slippage bucket for Aptos
|
|
42
|
-
const bondData = bonds?.find((bond) => bond?.contractAddress?.[bond?.chainId]?.toLowerCase() === bondAddress?.toLowerCase());
|
|
43
|
-
// Derived pricing (same path the Solana no-tier branch uses).
|
|
44
|
-
const trueBondPriceData = findHighestTrueBondPrice('0', bondData?.trueBondPrices);
|
|
45
|
-
// State
|
|
46
|
-
const [inputValue, setInputValue] = useState('');
|
|
47
|
-
const [inputTokenString, setInputTokenString] = useState(bondData?.lpToken?.address?.[bondData?.chainId]);
|
|
48
|
-
const [loadingTx, setLoadingTx] = useState(false);
|
|
49
|
-
// Token selection — reuses the same infrastructure as Solana
|
|
50
|
-
const inputToken = useTokenFromZapList(inputTokenString, bondData?.chainId, bondData?.lpToken);
|
|
51
|
-
const principalAddress = bondData?.lpToken?.address?.[bondData?.chainId];
|
|
52
|
-
// APT native ('NATIVE') and APT metadata ('0xa') are the same token — not a zap
|
|
53
|
-
const isNativeMatchingPrincipal = inputTokenString === 'NATIVE' && principalAddress?.toLowerCase() === '0xa';
|
|
54
|
-
const isZap = !!inputTokenString &&
|
|
55
|
-
!!principalAddress &&
|
|
56
|
-
!isNativeMatchingPrincipal &&
|
|
57
|
-
inputTokenString.toLowerCase() !== principalAddress.toLowerCase();
|
|
58
|
-
// Zap quote from Panora DEX aggregator
|
|
59
|
-
const aptosZapToken = findAptosZapToken(inputToken && inputToken !== 'NATIVE'
|
|
60
|
-
? inputToken?.address?.[ChainId.APTOS]
|
|
61
|
-
: inputToken === 'NATIVE'
|
|
62
|
-
? '0xa'
|
|
63
|
-
: undefined);
|
|
64
|
-
const [fetchingZapQuote, panoraQuote, zapDepositAmount, zapError] = useAptosZapQuote(inputValue, aptosZapToken, bondData, aptosAccount, slippage);
|
|
65
|
-
// Sorted zap list (balances + prices)
|
|
66
|
-
const { sortedZapList, isFetched: zapListFetched } = useSortedZapList(bondChain, bondData?.lpToken);
|
|
67
|
-
const enrichedTokenData = sortedZapList.find((item) => item.token === 'NATIVE' || inputToken === 'NATIVE'
|
|
68
|
-
? item.token === inputToken
|
|
69
|
-
: item?.token?.address?.[bondChain]?.toLowerCase() ===
|
|
70
|
-
inputToken?.address?.[bondChain]?.toLowerCase());
|
|
71
|
-
const inputCurrencyBalance = enrichedTokenData?.balance;
|
|
72
|
-
const inputTokenPrice = enrichedTokenData?.price;
|
|
73
|
-
// Estimations — use zapDepositAmount if swapping
|
|
74
|
-
const depositAmount = isZap ? zapDepositAmount : inputValue;
|
|
75
|
-
const youSpendString = `${formatNumberSI(inputValue)} ${getSymbol(inputToken, bondData?.chainId)} = $${formatUSDNumber((parseFloat(inputValue || '0') * (inputTokenPrice ?? 0)).toString())}`;
|
|
76
|
-
const exceedsRealMaxBuy = getMaxBuy(bondData, true).lte(getPayoutAmount(bondData, depositAmount, '0'));
|
|
77
|
-
const exceedsSafeMaxBuy = getMaxBuy(bondData, false)
|
|
78
|
-
.times(isZap ? 0.995 : 0.9995)
|
|
79
|
-
.lte(getPayoutAmount(bondData, depositAmount, '0'));
|
|
80
|
-
const exceedsBalance = new BigNumber(inputCurrencyBalance ?? '0').lt(inputValue);
|
|
81
|
-
const load = loadingTx || (fetchingZapQuote && !!inputValue);
|
|
82
|
-
// Handlers
|
|
83
|
-
const handleCurrencySelect = useCallback((newInputToken) => {
|
|
84
|
-
setInputValue('');
|
|
85
|
-
setInputTokenString(newInputToken);
|
|
86
|
-
}, []);
|
|
87
|
-
const handleMaxButton = () => {
|
|
88
|
-
const balance = new BigNumber(inputCurrencyBalance ?? '0');
|
|
89
|
-
const principalDecimals = bondData?.lpToken?.decimals?.[bondData?.chainId] ?? 6;
|
|
90
|
-
const maxBuyAmount = getMaxBuy(bondData, SDKConfig.showLowValueBonds);
|
|
91
|
-
if (!isZap) {
|
|
92
|
-
const maxPossibleUserPurchase = getPayoutAmount(bondData, balance.toString(), '0');
|
|
93
|
-
if (maxPossibleUserPurchase > maxBuyAmount.toNumber()) {
|
|
94
|
-
const principalForMaxBuy = getPrincipalAmount(bondData, maxBuyAmount.toString(), '0');
|
|
95
|
-
setInputValue(new BigNumber(principalForMaxBuy).toFixed(principalDecimals));
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
setInputValue(balance.toFixed(principalDecimals));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
const principalForMaxBuy = getPrincipalAmount(bondData, maxBuyAmount.toString(), '0');
|
|
103
|
-
const principalForMaxBuyUSD = new BigNumber(principalForMaxBuy).times(bondData?.principalTokenPrice ?? 0);
|
|
104
|
-
const maxBuyAmountInSelectedToken = principalForMaxBuyUSD.div(inputTokenPrice ?? 0);
|
|
105
|
-
const decimals = enrichedTokenData?.token === 'NATIVE' ? 8 : (enrichedTokenData?.token.decimals[bondData?.chainId] ?? 8);
|
|
106
|
-
if (balance.gte(maxBuyAmountInSelectedToken)) {
|
|
107
|
-
setInputValue(maxBuyAmountInSelectedToken.toFixed(decimals));
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
setInputValue(balance.toFixed(decimals));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
const handleBuyCallback = async () => {
|
|
115
|
-
if (!aptosAccount || !bondData || !inputValue)
|
|
116
|
-
return;
|
|
117
|
-
track({
|
|
118
|
-
event: 'buyBondClick',
|
|
119
|
-
chain: bondChain,
|
|
120
|
-
data: {
|
|
121
|
-
cat: bondData?.billType,
|
|
122
|
-
bond: bondData?.earnToken.symbol,
|
|
123
|
-
value: parseFloat(inputValue) * (inputTokenPrice ?? 0),
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
try {
|
|
127
|
-
setLoadingTx(true);
|
|
128
|
-
const principalDecimals = bondData.lpToken.decimals[bondData.chainId] ?? 6;
|
|
129
|
-
const atomicAmount = new BigNumber(inputValue)
|
|
130
|
-
.times(new BigNumber(10).pow(principalDecimals))
|
|
131
|
-
.integerValue(BigNumber.ROUND_FLOOR)
|
|
132
|
-
.toFixed(0);
|
|
133
|
-
const market = bondData.contractAddress[bondData.chainId] ?? '';
|
|
134
|
-
// Read fresh pricing from the contract
|
|
135
|
-
const marketInfo = await readAptosMarketInfo(market);
|
|
136
|
-
const trueBillPriceU64 = marketInfo[17]; // u64 scaled 1e8
|
|
137
|
-
const atomicMaxPrice = new BigNumber(trueBillPriceU64)
|
|
138
|
-
.times(new BigNumber(100 + slippage))
|
|
139
|
-
.dividedBy(new BigNumber(100))
|
|
140
|
-
.integerValue(BigNumber.ROUND_CEIL)
|
|
141
|
-
.toFixed(0);
|
|
142
|
-
const response = await signAndSubmitTransaction?.({
|
|
143
|
-
data: {
|
|
144
|
-
function: APTOS_DEPOSIT_FUNCTION,
|
|
145
|
-
typeArguments: [],
|
|
146
|
-
functionArguments: [market, atomicAmount, atomicMaxPrice, aptosAccount],
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
if (!response?.hash)
|
|
150
|
-
throw new Error('No tx hash returned by wallet');
|
|
151
|
-
const aptos = getAptosClient();
|
|
152
|
-
await aptos.waitForTransaction({ transactionHash: response.hash });
|
|
153
|
-
// waitForTransaction may not include events — fetch full tx details separately
|
|
154
|
-
const txDetails = await aptos.getTransactionByHash({ transactionHash: response.hash });
|
|
155
|
-
const txnWithEvents = txDetails;
|
|
156
|
-
const depositEvent = extractDepositEvent(txnWithEvents);
|
|
157
|
-
const newBillId = depositEvent?.bill_id ?? extractBillMinted(txnWithEvents)?.bill_id ?? '';
|
|
158
|
-
track({
|
|
159
|
-
event: 'bond',
|
|
160
|
-
chain: bondChain,
|
|
161
|
-
data: {
|
|
162
|
-
cat: 'lp-buy',
|
|
163
|
-
type: bondData?.billType ?? '',
|
|
164
|
-
typedValue: inputValue,
|
|
165
|
-
principalToken: bondData?.lpToken.symbol ?? '',
|
|
166
|
-
earnToken: bondData?.earnToken.symbol ?? '',
|
|
167
|
-
address: remove0xPrefix(market),
|
|
168
|
-
usdAmount: parseFloat(inputValue) * (inputTokenPrice ?? 0),
|
|
169
|
-
},
|
|
170
|
-
});
|
|
171
|
-
addToastSuccess(response.hash, bondChain);
|
|
172
|
-
setBillId?.(newBillId);
|
|
173
|
-
}
|
|
174
|
-
catch (error) {
|
|
175
|
-
console.error('Error during Aptos bond purchase:', error);
|
|
176
|
-
addToastError(error?.message || 'Unknown error');
|
|
177
|
-
reportError({
|
|
178
|
-
apiUrl: SDKConfig?.urls?.apiV2,
|
|
179
|
-
error: error?.message,
|
|
180
|
-
extraInfo: { type: 'aptosBuyBond', error: error?.message },
|
|
181
|
-
chainId: bondChain,
|
|
182
|
-
account: aptosAccount,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
finally {
|
|
186
|
-
setLoadingTx(false);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
const handleZapCallback = async () => {
|
|
190
|
-
if (loadingTx || !aptosAccount || !bondData || !panoraQuote || !signAndSubmitTransaction)
|
|
191
|
-
return;
|
|
192
|
-
track({
|
|
193
|
-
event: 'buyBondClick',
|
|
194
|
-
chain: bondChain,
|
|
195
|
-
data: {
|
|
196
|
-
cat: bondData?.billType,
|
|
197
|
-
bond: bondData?.earnToken.symbol,
|
|
198
|
-
value: parseFloat(inputValue) * (inputTokenPrice ?? 0),
|
|
199
|
-
},
|
|
200
|
-
});
|
|
201
|
-
try {
|
|
202
|
-
setLoadingTx(true);
|
|
203
|
-
const aptos = getAptosClient();
|
|
204
|
-
// TX1: Execute Panora swap — the quote's txData contains the entry
|
|
205
|
-
// function payload ready for the wallet adapter.
|
|
206
|
-
const swapTxData = panoraQuote.txData;
|
|
207
|
-
if (!swapTxData || !swapTxData.function) {
|
|
208
|
-
throw new Error('Panora quote missing txData');
|
|
209
|
-
}
|
|
210
|
-
const swapResponse = await signAndSubmitTransaction({
|
|
211
|
-
data: swapTxData,
|
|
212
|
-
});
|
|
213
|
-
if (!swapResponse?.hash)
|
|
214
|
-
throw new Error('No tx hash returned for swap');
|
|
215
|
-
await aptos.waitForTransaction({ transactionHash: swapResponse.hash });
|
|
216
|
-
// TX2: Deposit into bond with the swapped principal tokens.
|
|
217
|
-
// Use the deposit amount from the quote (what we received from the swap).
|
|
218
|
-
const principalDecimals = bondData.lpToken.decimals[bondData.chainId] ?? 6;
|
|
219
|
-
const depositAmountAtomic = new BigNumber(zapDepositAmount)
|
|
220
|
-
.times(new BigNumber(10).pow(principalDecimals))
|
|
221
|
-
.integerValue(BigNumber.ROUND_FLOOR)
|
|
222
|
-
.toFixed(0);
|
|
223
|
-
const market = bondData.contractAddress[bondData.chainId] ?? '';
|
|
224
|
-
// Read fresh pricing
|
|
225
|
-
const marketInfo = await readAptosMarketInfo(market);
|
|
226
|
-
const trueBillPriceU64 = marketInfo[17];
|
|
227
|
-
const atomicMaxPrice = new BigNumber(trueBillPriceU64)
|
|
228
|
-
.times(new BigNumber(100 + slippage))
|
|
229
|
-
.dividedBy(new BigNumber(100))
|
|
230
|
-
.integerValue(BigNumber.ROUND_CEIL)
|
|
231
|
-
.toFixed(0);
|
|
232
|
-
const depositResponse = await signAndSubmitTransaction({
|
|
233
|
-
data: {
|
|
234
|
-
function: APTOS_DEPOSIT_FUNCTION,
|
|
235
|
-
typeArguments: [],
|
|
236
|
-
functionArguments: [market, depositAmountAtomic, atomicMaxPrice, aptosAccount],
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
if (!depositResponse?.hash)
|
|
240
|
-
throw new Error('No tx hash returned for deposit');
|
|
241
|
-
await aptos.waitForTransaction({ transactionHash: depositResponse.hash });
|
|
242
|
-
const txDetails = await aptos.getTransactionByHash({ transactionHash: depositResponse.hash });
|
|
243
|
-
const txnWithEvents = txDetails;
|
|
244
|
-
const depositEvent = extractDepositEvent(txnWithEvents);
|
|
245
|
-
const newBillId = depositEvent?.bill_id ?? extractBillMinted(txnWithEvents)?.bill_id ?? '';
|
|
246
|
-
// Track zap events
|
|
247
|
-
track({
|
|
248
|
-
event: 'zap',
|
|
249
|
-
chain: bondChain,
|
|
250
|
-
data: {
|
|
251
|
-
cat: 'bond',
|
|
252
|
-
token1: getSymbol(inputToken),
|
|
253
|
-
token2: bondData?.lpToken.symbol ?? '',
|
|
254
|
-
amount: parseFloat(inputValue) * (inputTokenPrice ?? 0),
|
|
255
|
-
},
|
|
256
|
-
});
|
|
257
|
-
track({
|
|
258
|
-
event: 'bond',
|
|
259
|
-
chain: bondChain,
|
|
260
|
-
data: {
|
|
261
|
-
cat: 'zap-buy-two-tx',
|
|
262
|
-
type: bondData?.billType ?? '',
|
|
263
|
-
typedValue: inputValue,
|
|
264
|
-
principalToken: bondData?.lpToken.symbol ?? '',
|
|
265
|
-
earnToken: bondData?.earnToken.symbol ?? '',
|
|
266
|
-
address: remove0xPrefix(market),
|
|
267
|
-
usdAmount: parseFloat(inputValue) * (inputTokenPrice ?? 0),
|
|
268
|
-
},
|
|
269
|
-
});
|
|
270
|
-
addToastSuccess(depositResponse.hash, bondChain);
|
|
271
|
-
setBillId?.(newBillId);
|
|
272
|
-
}
|
|
273
|
-
catch (error) {
|
|
274
|
-
console.error('Error during Aptos zap + bond purchase:', error);
|
|
275
|
-
addToastError(error?.message || 'Unknown error during swap and bond');
|
|
276
|
-
reportError({
|
|
277
|
-
apiUrl: SDKConfig?.urls?.apiV2,
|
|
278
|
-
error: error?.message,
|
|
279
|
-
extraInfo: { type: 'aptosPanoraZapBuyBond', error: error?.message, quote: panoraQuote },
|
|
280
|
-
chainId: bondChain,
|
|
281
|
-
account: aptosAccount,
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
finally {
|
|
285
|
-
setLoadingTx(false);
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
const handleBuy = () => {
|
|
289
|
-
if (loadingTx)
|
|
290
|
-
return;
|
|
291
|
-
if (isZap) {
|
|
292
|
-
handleZapCallback();
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
handleBuyCallback();
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
// Sync inputTokenString when bondData loads after initial render
|
|
299
|
-
useEffect(() => {
|
|
300
|
-
const addr = bondData?.lpToken?.address?.[bondData?.chainId];
|
|
301
|
-
if (addr && !inputTokenString) {
|
|
302
|
-
setInputTokenString(addr);
|
|
303
|
-
}
|
|
304
|
-
}, [bondData?.lpToken?.address, bondData?.chainId]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
305
|
-
// Auto-select highest balance token when zap list loads
|
|
306
|
-
const [hasChecked, setHasChecked] = useState(false);
|
|
307
|
-
useEffect(() => {
|
|
308
|
-
if (zapListFetched && !hasChecked) {
|
|
309
|
-
if (parseFloat(inputCurrencyBalance ?? '0') < 0.0001) {
|
|
310
|
-
setInputTokenString(sortedZapList[0]?.token === 'NATIVE' ? 'NATIVE' : sortedZapList[0]?.token.address[bondChain]);
|
|
311
|
-
}
|
|
312
|
-
setHasChecked(true);
|
|
313
|
-
}
|
|
314
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
315
|
-
}, [inputCurrencyBalance, zapListFetched]);
|
|
316
|
-
const hasPositiveBonus = (trueBondPriceData?.bonusWithFee ?? 0) > 0;
|
|
317
|
-
const canBuy = !load &&
|
|
318
|
-
!!aptosAccount &&
|
|
319
|
-
!bondData?.soldOut &&
|
|
320
|
-
!!inputValue &&
|
|
321
|
-
parseFloat(inputValue) > 0 &&
|
|
322
|
-
!exceedsRealMaxBuy &&
|
|
323
|
-
!exceedsBalance &&
|
|
324
|
-
hasPositiveBonus &&
|
|
325
|
-
!SDKConfig.blockSales &&
|
|
326
|
-
!zapError &&
|
|
327
|
-
!(isZap && !panoraQuote);
|
|
328
|
-
return bondData ? (jsx(Flex, { className: "modal-content", sx: { ...MCBuyComponentStyles[bondData?.marketingCampaign] }, children: jsxs(Flex, { className: "modaltable-container", children: [jsx(BondModalHeader, { bondData: bondData, onDismiss: onDismiss, hidePromotionUi: true }), jsx(ProjectDescription, { description: bondData.shortDescription, isProjectView: true }), jsx(Flex, { sx: { width: '100%', display: isProjectView ? ['flex', 'flex', 'flex', 'none'] : 'flex' }, children: jsx(BondCards, { bondData: bondData, isDoingMaxBuy: exceedsSafeMaxBuy && !exceedsRealMaxBuy }) }), jsx(Estimations, { depositAmount: depositAmount, inputValue: inputValue, inputTokenPrice: inputTokenPrice, bondData: bondData, youSpendString: youSpendString, isZap: isZap, fetchingZapQuote: fetchingZapQuote, zapError: zapError }), jsx(TokenSelectorPanel, { typedValue: inputValue, setTypedValue: setInputValue, selectedToken: inputToken, handleValueBtn: handleMaxButton, handleCurrencySelect: handleCurrencySelect, bondChainId: ChainId.APTOS, enableZap: true, bondPrincipalToken: bondData?.lpToken, tokenBalance: inputCurrencyBalance ?? undefined, selectedTokenPrice: inputTokenPrice, isConnected: !!aptosAccount }), bondData?.warningCard && (jsx(Flex, { sx: {
|
|
329
|
-
width: '100%',
|
|
330
|
-
background: '#DE62F366',
|
|
331
|
-
justifyContent: 'center',
|
|
332
|
-
mt: '10px',
|
|
333
|
-
borderRadius: 'normal',
|
|
334
|
-
p: '2px 10px',
|
|
335
|
-
}, children: jsx(Text, { sx: { fontSize: '12px', fontWeight: 400, display: 'flex', alignItems: 'center', gap: '10px' }, children: jsx(SafeHTMLComponent, { html: bondData?.warningCard }) }) })), jsx(Flex, { className: "modaltable-container button-container", children: jsx(Flex, { className: "button-container buy", children: !aptosAccount ? (jsx(ConnectAptosWalletButton, {})) : (jsx(Button, { className: "action-button", load: load, disabled: !canBuy, onClick: handleBuy, sx: { width: '100%', fontSize: ['14px', '14px', '14px', '16px'] }, children: SDKConfig.blockSales
|
|
336
|
-
? 'Complete KYC to Buy'
|
|
337
|
-
: exceedsRealMaxBuy
|
|
338
|
-
? 'Exceeds Max Buy. Reduce amount'
|
|
339
|
-
: exceedsBalance
|
|
340
|
-
? 'Insufficient balance'
|
|
341
|
-
: zapError
|
|
342
|
-
? 'Swap quote failed'
|
|
343
|
-
: !inputValue || parseFloat(inputValue) === 0
|
|
344
|
-
? 'Insert amount'
|
|
345
|
-
: 'buy' })) }) })] }) })) : (jsx(Fragment, {}));
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
export { BuyComponentAptos as default };
|
|
349
|
-
//# sourceMappingURL=BuyComponentAptos.js.map
|