@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.
Files changed (52) hide show
  1. package/dist/components/ConnectButton/index.js +3 -4
  2. package/dist/components/ConnectButton/index.js.map +1 -1
  3. package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js +5 -3
  4. package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js.map +1 -1
  5. package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js +7 -2
  6. package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js.map +1 -1
  7. package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js +5 -1
  8. package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js.map +1 -1
  9. package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js +9 -2
  10. package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js.map +1 -1
  11. package/dist/config/constants/aptosZapTokens.js +1 -15
  12. package/dist/config/constants/aptosZapTokens.js.map +1 -1
  13. package/dist/config/constants/walletConnectors.d.ts +6 -0
  14. package/dist/config/constants/walletConnectors.js +25 -0
  15. package/dist/config/constants/walletConnectors.js.map +1 -0
  16. package/dist/constants/aptosConstants.js +1 -5
  17. package/dist/constants/aptosConstants.js.map +1 -1
  18. package/dist/constants/suiConstants.js +1 -3
  19. package/dist/constants/suiConstants.js.map +1 -1
  20. package/dist/state/useSDKConfig.d.ts +13 -3
  21. package/dist/state/useSDKConfig.js +22 -10
  22. package/dist/state/useSDKConfig.js.map +1 -1
  23. package/dist/utils/aptosHelpers.js +1 -25
  24. package/dist/utils/aptosHelpers.js.map +1 -1
  25. package/dist/views/BuyBond/BuyBondModal.js +14 -3
  26. package/dist/views/BuyBond/BuyBondModal.js.map +1 -1
  27. package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js +3 -1
  28. package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js.map +1 -1
  29. package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js +5 -1
  30. package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js.map +1 -1
  31. package/package.json +1 -2
  32. package/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js +0 -39
  33. package/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js.map +0 -1
  34. package/dist/components/ConnectButton/AppKitButton.d.ts +0 -3
  35. package/dist/components/ConnectButton/AppKitButton.js +0 -9
  36. package/dist/components/ConnectButton/AppKitButton.js.map +0 -1
  37. package/dist/components/ConnectButton/RainbowKitButton.d.ts +0 -3
  38. package/dist/components/ConnectButton/RainbowKitButton.js +0 -22
  39. package/dist/components/ConnectButton/RainbowKitButton.js.map +0 -1
  40. package/dist/config/constants/suiCallbacks.d.ts +0 -2
  41. package/dist/config/constants/suiCallbacks.js +0 -17
  42. package/dist/config/constants/suiCallbacks.js.map +0 -1
  43. package/dist/config/constants/suiZapTokens.js +0 -36
  44. package/dist/config/constants/suiZapTokens.js.map +0 -1
  45. package/dist/state/zap/useAptosZapQuote.js +0 -83
  46. package/dist/state/zap/useAptosZapQuote.js.map +0 -1
  47. package/dist/state/zap/useSuiZapQuote.js +0 -96
  48. package/dist/state/zap/useSuiZapQuote.js.map +0 -1
  49. package/dist/views/BuyBond/BuyComponentAptos.js +0 -349
  50. package/dist/views/BuyBond/BuyComponentAptos.js.map +0 -1
  51. package/dist/views/BuyBond/BuyComponentSui.js +0 -500
  52. 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