@ape.swap/bonds-sdk 6.1.17-test.1 → 6.2.0-test.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/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js +32 -0
- package/dist/components/ConnectAptosWalletButton/ConnectAptosWalletButton.js.map +1 -0
- package/dist/components/ConnectButton/index.js +1 -1
- package/dist/components/ConnectButton/index.js.map +1 -1
- package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js +3 -15
- package/dist/components/ConnectSolanaWalletButton/ConnectSolanaWalletButton.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js +2 -6
- package/dist/components/ConnectoToVmBanners/ConnectToAptosBanner.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js +1 -3
- package/dist/components/ConnectoToVmBanners/ConnectToSolanaBanner.js.map +1 -1
- package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js +2 -8
- package/dist/components/ConnectoToVmBanners/ConnectToSuiBanner.js.map +1 -1
- package/dist/components/uikit-sdk/Svg/Icons/NewOffer.js.map +1 -1
- package/dist/components/uikit-sdk/Svg/Icons/Robinhood.d.ts +4 -0
- package/dist/components/uikit-sdk/Svg/Icons/Robinhood.js +9 -0
- package/dist/components/uikit-sdk/Svg/Icons/Robinhood.js.map +1 -0
- package/dist/components/uikit-sdk/Svg/Icons/SellingFast.js.map +1 -1
- package/dist/components/uikit-sdk/Svg/Icons/WhaleActivity.js.map +1 -1
- package/dist/config/constants/addresses.js +3 -1
- package/dist/config/constants/addresses.js.map +1 -1
- package/dist/config/constants/aptosZapTokens.js +15 -1
- package/dist/config/constants/aptosZapTokens.js.map +1 -1
- package/dist/config/constants/chains.js +6 -0
- package/dist/config/constants/chains.js.map +1 -1
- package/dist/config/constants/networks.js +1 -0
- package/dist/config/constants/networks.js.map +1 -1
- package/dist/config/constants/suiZapTokens.js +36 -0
- package/dist/config/constants/suiZapTokens.js.map +1 -0
- package/dist/config/constants/variables.d.ts +1 -1
- package/dist/config/constants/variables.js +1 -0
- package/dist/config/constants/variables.js.map +1 -1
- package/dist/constants/aptosConstants.js +5 -1
- package/dist/constants/aptosConstants.js.map +1 -1
- package/dist/constants/suiConstants.js +3 -1
- package/dist/constants/suiConstants.js.map +1 -1
- package/dist/hooks/accounts/useSOLAccount.js +0 -1
- package/dist/hooks/accounts/useSOLAccount.js.map +1 -1
- package/dist/state/bonds/useBondsData.js +36 -51
- package/dist/state/bonds/useBondsData.js.map +1 -1
- package/dist/state/bonds/useBondsList.d.ts +3 -3
- package/dist/state/bonds/useBondsList.js +25 -6
- package/dist/state/bonds/useBondsList.js.map +1 -1
- package/dist/state/bonds/useUserBonds.d.ts +2 -2
- package/dist/state/bonds/useUserBonds.js +8 -28
- package/dist/state/bonds/useUserBonds.js.map +1 -1
- package/dist/state/historicalPrice/useHistoricalPrice.js +2 -3
- package/dist/state/historicalPrice/useHistoricalPrice.js.map +1 -1
- package/dist/state/useSDKConfig.d.ts +1 -1
- package/dist/state/useSDKConfig.js +5 -2
- package/dist/state/useSDKConfig.js.map +1 -1
- package/dist/state/zap/getChainParam.d.ts +2 -1
- package/dist/state/zap/getChainParam.js +4 -1
- package/dist/state/zap/getChainParam.js.map +1 -1
- package/dist/state/zap/useAptosZapQuote.js +83 -0
- package/dist/state/zap/useAptosZapQuote.js.map +1 -0
- package/dist/state/zap/useSuiZapQuote.js +96 -0
- package/dist/state/zap/useSuiZapQuote.js.map +1 -0
- package/dist/utils/aptosHelpers.js +25 -1
- package/dist/utils/aptosHelpers.js.map +1 -1
- package/dist/views/Bonds/Bonds.js +1 -1
- package/dist/views/Bonds/Bonds.js.map +1 -1
- package/dist/views/Bonds/components/BondRows/ModalHandler.d.ts +2 -1
- package/dist/views/Bonds/components/BondRows/ModalHandler.js +2 -4
- package/dist/views/Bonds/components/BondRows/ModalHandler.js.map +1 -1
- package/dist/views/BuyBond/BuyBondModal.js +3 -14
- package/dist/views/BuyBond/BuyBondModal.js.map +1 -1
- package/dist/views/BuyBond/BuyComponentAptos.js +349 -0
- package/dist/views/BuyBond/BuyComponentAptos.js.map +1 -0
- package/dist/views/BuyBond/BuyComponentSui.js +500 -0
- package/dist/views/BuyBond/BuyComponentSui.js.map +1 -0
- package/dist/views/BuyBond/index.d.ts +2 -2
- package/dist/views/BuyBond/index.js.map +1 -1
- package/dist/views/ProjectView/ProjectView.js +1 -1
- package/dist/views/ProjectView/ProjectView.js.map +1 -1
- package/dist/views/ProjectView/components/ProjectInfo/index.d.ts +2 -2
- package/dist/views/ProjectView/components/ProjectInfo/index.js +3 -7
- package/dist/views/ProjectView/components/ProjectInfo/index.js.map +1 -1
- package/dist/views/ProjectView/components/ProjectInfo/styles.js +1 -24
- package/dist/views/ProjectView/components/ProjectInfo/styles.js.map +1 -1
- package/dist/views/SingleBond/SingleBond.js +12 -5
- package/dist/views/SingleBond/SingleBond.js.map +1 -1
- package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js +2 -10
- package/dist/views/YourBonds/components/UserBondRow/UserBondRowSolana.js.map +1 -1
- package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js +2 -9
- package/dist/views/YourBondsModal/components/TransferBondModal/TransferActionSolana.js.map +1 -1
- package/package.json +7 -5
- package/dist/state/tokenList/useTokenList.d.ts +0 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUserBonds.js","sources":["../../../src/state/bonds/useUserBonds.ts"],"sourcesContent":["import { QueryClient, useQuery, useQueryClient, UseQueryResult } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BillsConfig, ChainId, BillVersion } from '@ape.swap/apeswap-lists'\nimport useBondsList from './useBondsList'\nimport { UserBill, UserBillNftData } from '../../types/yourbonds'\nimport { SDKProps } from '../useSDKConfig'\nimport useTokenPrices, { TokenPrices } from '../tokenPrices/useTokenPrices'\nimport { ACF_TO_ABOND } from '../../config/constants/addresses'\nimport { reportError } from '../../utils/reportError'\nimport useEVMAccount from '../../hooks/accounts/useEVMAccount'\nimport useSOLAccount from '../../hooks/accounts/useSOLAccount'\nimport useAPTAccount from '../../hooks/accounts/useAPTAccount'\nimport useSUIAccount from '../../hooks/accounts/useSUIAccount'\nimport axios from 'axios'\nimport { fetchUsersBondsSOL } from './fetchUsersBonds/fetchUsersBondsSOL'\nimport { fetchUsersBondsAptos } from './fetchUsersBonds/fetchUsersBondsAptos'\nimport { fetchUsersBondsSUI } from './fetchUsersBonds/fetchUsersBondsSUI'\nimport { fetchUsersBondsEVM } from './fetchUsersBonds/fetchUsersBondsEVM'\n\nexport default function useUserBonds(): UseQueryResult<UserBill[]> {\n // First fetch the full list of bonds\n const { data: bondList } = useBondsList()\n const { address: addressEVM } = useEVMAccount()\n const { publicKey } = useSOLAccount()\n const addressSOL = publicKey?.toBase58()\n const { address: addressAptos } = useAPTAccount()\n const { address: addressSUI } = useSUIAccount()\n const { data: tokenPrices } = useTokenPrices()\n const queryClient = useQueryClient()\n return useQuery({\n queryKey: [\n QUERY_KEYS.USER_BONDS,\n addressEVM,\n addressSOL,\n addressAptos,\n addressSUI,\n Object.keys(tokenPrices ?? {})?.length ?? null,\n ],\n queryFn: () => getUserBonds(addressEVM!, addressSOL!, addressAptos!, addressSUI!, bondList!, queryClient),\n enabled: !!bondList && !!(addressEVM || addressSOL || addressAptos || addressSUI) && !!tokenPrices,\n refetchInterval: 120000,\n refetchOnWindowFocus: false,\n refetchOnMount: false,\n refetchOnReconnect: false,\n retry: 1,\n })\n}\n\nexport const getUserBonds = async (\n account: string,\n solanaAccount: string,\n aptosAccount: string,\n suiAccount: string,\n bondList: BillsConfig[],\n queryClient: QueryClient,\n): Promise<UserBill[]> => {\n const { chains, urls } = queryClient?.getQueryData([QUERY_KEYS.SDK_CONFIG]) as SDKProps\n const apiUrl = urls['apiV2']\n const tokenPrices: Partial<Record<ChainId, TokenPrices[]>> = queryClient?.getQueryData([QUERY_KEYS.TOKEN_PRICES])!\n\n try {\n const bondsByChain = bondList.reduce(\n (acc, bond) => {\n // Exclude ACF to ABOND bonds, fixed price bonds, and migration bonds\n if (\n bond.contractAddress[bond.chainId]?.toLowerCase() === ACF_TO_ABOND.toLowerCase() ||\n bond.billVersion === BillVersion.FixedPrice ||\n bond.billType === 'migration'\n ) {\n return acc\n }\n\n // Only process bonds that belong to the specified chains\n if (chains.includes(bond.chainId)) {\n // Initialize acc[bond.chainId] if it doesn't exist yet\n if (!acc[bond.chainId]) {\n acc[bond.chainId] = []\n }\n\n // Safely push the bond to the array\n acc[bond.chainId].push(bond)\n }\n return acc\n },\n {} as Record<number, BillsConfig[]>,\n )\n\n const results = await Promise.allSettled(\n chains\n .filter((chain) => bondsByChain[chain])\n .map((chain) => {\n if (chain === ChainId.SOL) {\n return fetchUsersBondsSOL(solanaAccount, bondsByChain[chain], tokenPrices)\n } else if (chain === ChainId.APTOS) {\n return fetchUsersBondsAptos(aptosAccount, bondsByChain[chain], tokenPrices)\n } else if (chain === ChainId.SUI) {\n return fetchUsersBondsSUI(suiAccount, bondsByChain[chain], tokenPrices)\n } else return fetchUsersBondsEVM(chain, account, bondsByChain[chain], tokenPrices)\n }),\n )\n\n // Filter out only fulfilled promises\n const fulfilledResults = results\n .filter((result): result is PromiseFulfilledResult<any> => result.status === 'fulfilled')\n .map((result) => result.value)\n\n const onChainData: UserBill[] = fulfilledResults.flat().flatMap((result) => result.userOwnedBills)\n\n // Prepare body for batch API call\n // api-v2 won't support Aptos/Sui. Bills are read on-chain, no /bills/multi-batch\n // enrichment. Aptos/Sui bills use the placeholder image from their constants.\n const body = Object.values(\n onChainData\n .filter((data) => data?.bond?.chainId !== ChainId.APTOS && data?.bond?.chainId !== ChainId.SUI)\n .reduce(\n (acc, data) => {\n const contract =\n data?.bond?.chainId === ChainId.SOL ? data.bond.contractAddress[data.bond.chainId] : data.billNftAddress\n const key = `${data?.bond?.chainId}-${contract}`\n\n if (!acc[key]) {\n acc[key] = {\n chainId: data?.bond?.chainId as number,\n contract: contract as string,\n billIds: [],\n }\n }\n\n acc[key].billIds.push(parseInt(data.id))\n return acc\n },\n {} as Record<string, { chainId: number; contract: string; billIds: number[] }>,\n ),\n )\n let response\n\n try {\n response = await axios.post(`${apiUrl}/bills/multi-batch`, body, { timeout: 40000 })\n } catch (e) {\n console.error(e)\n return onChainData\n }\n // Enrich on-chain data with API data.\n // Aptos/Sui bills are not sent to api-v2 (no support), so keep their existing\n // nftData populated by fetchBillsUser{Aptos,Sui} instead of overwriting with undefined.\n const enrichedData: UserBill[] = onChainData.map((userBond) => {\n if (userBond.bond?.chainId === ChainId.APTOS || userBond.bond?.chainId === ChainId.SUI) return userBond\n\n const nftDataResponse = response.data?.find((nft: any) => {\n const contract = nft.contract.toLowerCase()\n const chain = nft.chainId\n\n // API uses contractAddress for Solana bonds instead of NFT Address\n const contractToCompare =\n chain === ChainId.SOL ? userBond.bond?.contractAddress[ChainId.SOL] : userBond.billNftAddress\n return contractToCompare?.toLowerCase() === contract && userBond.bond?.chainId === chain\n })\n const nftData: UserBillNftData | undefined = nftDataResponse?.bills?.find(\n (billApiData: UserBillNftData) => billApiData.tokenId === parseInt(userBond.id),\n )\n return {\n ...userBond,\n nftData,\n }\n })\n\n return enrichedData\n } catch (e) {\n console.error(e)\n reportError({\n apiUrl,\n error: e,\n extraInfo: { type: 'getUserBonds', bondList, chains, e },\n account,\n })\n throw new Error('Failed to fetch user bonds')\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAmBc,SAAU,YAAY,GAAA;;IAElC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE;IACzC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,aAAa,EAAE;AAC/C,IAAA,MAAM,EAAE,SAAS,EAAE,GAAG,aAAa,EAAE;AACrC,IAAA,MAAM,UAAU,GAAG,SAAS,EAAE,QAAQ,EAAE;IACxC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE;IACjD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,aAAa,EAAE;IAC/C,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,cAAc,EAAE;AAC9C,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;AACpC,IAAA,OAAO,QAAQ,CAAC;AACd,QAAA,QAAQ,EAAE;AACR,YAAA,UAAU,CAAC,UAAU;YACrB,UAAU;YACV,UAAU;YACV,YAAY;YACZ,UAAU;YACV,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,MAAM,IAAI,IAAI;AAC/C,SAAA;AACD,QAAA,OAAO,EAAE,MAAM,YAAY,CAAC,UAAW,EAAE,UAAW,EAAE,YAAa,EAAE,UAAW,EAAE,QAAS,EAAE,WAAW,CAAC;AACzG,QAAA,OAAO,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,EAAE,UAAU,IAAI,UAAU,IAAI,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,WAAW;AAClG,QAAA,eAAe,EAAE,MAAM;AACvB,QAAA,oBAAoB,EAAE,KAAK;AAC3B,QAAA,cAAc,EAAE,KAAK;AACrB,QAAA,kBAAkB,EAAE,KAAK;AACzB,QAAA,KAAK,EAAE,CAAC;AACT,KAAA,CAAC;AACJ;AAEO,MAAM,YAAY,GAAG,OAC1B,OAAe,EACf,aAAqB,EACrB,YAAoB,EACpB,UAAkB,EAClB,QAAuB,EACvB,WAAwB,KACD;AACvB,IAAA,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAa;AACvF,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;AAC5B,IAAA,MAAM,WAAW,GAA4C,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAE;AAElH,IAAA,IAAI;QACF,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAClC,CAAC,GAAG,EAAE,IAAI,KAAI;;AAEZ,YAAA,IACE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,KAAK,YAAY,CAAC,WAAW,EAAE;AAChF,gBAAA,IAAI,CAAC,WAAW,KAAK,WAAW,CAAC,UAAU;AAC3C,gBAAA,IAAI,CAAC,QAAQ,KAAK,WAAW,EAC7B;AACA,gBAAA,OAAO,GAAG;YACZ;;YAGA,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;;gBAEjC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACtB,oBAAA,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;gBACxB;;gBAGA,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAC9B;AACA,YAAA,OAAO,GAAG;QACZ,CAAC,EACD,EAAmC,CACpC;AAED,QAAA,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC;aACG,MAAM,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,KAAK,CAAC;AACrC,aAAA,GAAG,CAAC,CAAC,KAAK,KAAI;AACb,YAAA,IAAI,KAAK,KAAK,OAAO,CAAC,GAAG,EAAE;gBACzB,OAAO,kBAAkB,CAAC,aAAa,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;YAC5E;AAAO,iBAAA,IAAI,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE;gBAClC,OAAO,oBAAoB,CAAC,YAAY,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;YAC7E;AAAO,iBAAA,IAAI,KAAK,KAAK,OAAO,CAAC,GAAG,EAAE;gBAChC,OAAO,kBAAkB,CAAC,UAAU,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;YACzE;;AAAO,gBAAA,OAAO,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;QACpF,CAAC,CAAC,CACL;;QAGD,MAAM,gBAAgB,GAAG;aACtB,MAAM,CAAC,CAAC,MAAM,KAA4C,MAAM,CAAC,MAAM,KAAK,WAAW;aACvF,GAAG,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,KAAK,CAAC;AAEhC,QAAA,MAAM,WAAW,GAAe,gBAAgB,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,cAAc,CAAC;;;;AAKlG,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CACxB;aACG,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG;AAC7F,aAAA,MAAM,CACL,CAAC,GAAG,EAAE,IAAI,KAAI;AACZ,YAAA,MAAM,QAAQ,GACZ,IAAI,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc;YAC1G,MAAM,GAAG,GAAG,CAAA,EAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE;AAEhD,YAAA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBACb,GAAG,CAAC,GAAG,CAAC,GAAG;AACT,oBAAA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAiB;AACtC,oBAAA,QAAQ,EAAE,QAAkB;AAC5B,oBAAA,OAAO,EAAE,EAAE;iBACZ;YACH;AAEA,YAAA,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxC,YAAA,OAAO,GAAG;AACZ,QAAA,CAAC,EACD,EAA8E,CAC/E,CACJ;AACD,QAAA,IAAI,QAAQ;AAEZ,QAAA,IAAI;AACF,YAAA,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA,kBAAA,CAAoB,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACtF;QAAE,OAAO,CAAC,EAAE;AACV,YAAA,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAChB,YAAA,OAAO,WAAW;QACpB;;;;QAIA,MAAM,YAAY,GAAe,WAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAI;AAC5D,YAAA,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,GAAG;AAAE,gBAAA,OAAO,QAAQ;YAEvG,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,GAAQ,KAAI;gBACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE;AAC3C,gBAAA,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO;;gBAGzB,MAAM,iBAAiB,GACrB,KAAK,KAAK,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,cAAc;AAC/F,gBAAA,OAAO,iBAAiB,EAAE,WAAW,EAAE,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK;AAC1F,YAAA,CAAC,CAAC;YACF,MAAM,OAAO,GAAgC,eAAe,EAAE,KAAK,EAAE,IAAI,CACvE,CAAC,WAA4B,KAAK,WAAW,CAAC,OAAO,KAAK,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAChF;YACD,OAAO;AACL,gBAAA,GAAG,QAAQ;gBACX,OAAO;aACR;AACH,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,YAAY;IACrB;IAAE,OAAO,CAAC,EAAE;AACV,QAAA,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAChB,QAAA,WAAW,CAAC;YACV,MAAM;AACN,YAAA,KAAK,EAAE,CAAC;YACR,SAAS,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE;YACxD,OAAO;AACR,SAAA,CAAC;AACF,QAAA,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC;IAC/C;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useUserBonds.js","sources":["../../../src/state/bonds/useUserBonds.ts"],"sourcesContent":["import { QueryClient, useQuery, UseQueryResult } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { BillsConfig, ChainId } from '@ape.swap/apeswap-lists'\nimport useBondsList from './useBondsList'\nimport { UserBill, UserBillNftData } from '../../types/yourbonds'\nimport { SDKProps } from '../useSDKConfig'\nimport useTokenPrices, { TokenPrices } from '../tokenPrices/useTokenPrices'\nimport { reportError } from '../../utils/reportError'\nimport useEVMAccount from '../../hooks/accounts/useEVMAccount'\nimport useSOLAccount from '../../hooks/accounts/useSOLAccount'\nimport useAPTAccount from '../../hooks/accounts/useAPTAccount'\nimport useSUIAccount from '../../hooks/accounts/useSUIAccount'\nimport axios from 'axios'\nimport { fetchUsersBondsSOL } from './fetchUsersBonds/fetchUsersBondsSOL'\nimport { fetchUsersBondsAptos } from './fetchUsersBonds/fetchUsersBondsAptos'\nimport { fetchUsersBondsSUI } from './fetchUsersBonds/fetchUsersBondsSUI'\nimport { fetchUsersBondsEVM } from './fetchUsersBonds/fetchUsersBondsEVM'\n\nexport default function useUserBonds(): UseQueryResult<UserBill[]> {\n // First fetch the full list of bonds\n const { data: bondList } = useBondsList()\n const { address: addressEVM } = useEVMAccount()\n const { publicKey } = useSOLAccount()\n const addressSOL = publicKey?.toBase58()\n const { address: addressAptos } = useAPTAccount()\n const { address: addressSUI } = useSUIAccount()\n const { data: tokenPrices } = useTokenPrices()\n return useQuery({\n queryKey: [\n QUERY_KEYS.USER_BONDS,\n addressEVM,\n addressSOL,\n addressAptos,\n addressSUI,\n Object.keys(tokenPrices ?? {})?.length ?? null,\n ],\n queryFn: ({ client }) => getUserBonds(addressEVM!, addressSOL!, addressAptos!, addressSUI!, bondList!, client),\n enabled: !!bondList && !!(addressEVM || addressSOL || addressAptos || addressSUI) && !!tokenPrices,\n refetchInterval: 120000,\n refetchOnWindowFocus: false,\n refetchOnMount: false,\n refetchOnReconnect: false,\n retry: 1,\n })\n}\n\nexport const getUserBonds = async (\n account: string,\n solanaAccount: string,\n aptosAccount: string,\n suiAccount: string,\n bondList: Record<ChainId, BillsConfig[]>,\n queryClient: QueryClient,\n): Promise<UserBill[]> => {\n const { chains, urls } = queryClient?.getQueryData([QUERY_KEYS.SDK_CONFIG]) as SDKProps\n const apiUrl = urls['apiV2']\n const tokenPrices: Partial<Record<ChainId, TokenPrices[]>> = queryClient?.getQueryData([QUERY_KEYS.TOKEN_PRICES])!\n\n try {\n const results = await Promise.allSettled(\n chains\n .filter((chain: ChainId) => bondList[chain])\n .map((chain: ChainId) => {\n if (chain === ChainId.SOL) {\n return fetchUsersBondsSOL(solanaAccount, bondList[chain], tokenPrices)\n } else if (chain === ChainId.APTOS) {\n return fetchUsersBondsAptos(aptosAccount, bondList[chain], tokenPrices)\n } else if (chain === ChainId.SUI) {\n return fetchUsersBondsSUI(suiAccount, bondList[chain], tokenPrices)\n } else return fetchUsersBondsEVM(chain, account, bondList[chain], tokenPrices)\n }),\n )\n\n // Filter out only fulfilled promises\n const fulfilledResults = results\n .filter((result): result is PromiseFulfilledResult<any> => result.status === 'fulfilled')\n .map((result) => result.value)\n\n const onChainData: UserBill[] = fulfilledResults.flat().flatMap((result) => result.userOwnedBills)\n\n // Prepare body for batch API call\n // api-v2 won't support Aptos/Sui. Bills are read on-chain, no /bills/multi-batch\n // enrichment. Aptos/Sui bills use the placeholder image from their constants.\n const body = Object.values(\n onChainData\n .filter((data) => data?.bond?.chainId !== ChainId.APTOS && data?.bond?.chainId !== ChainId.SUI)\n .reduce(\n (acc, data) => {\n const contract =\n data?.bond?.chainId === ChainId.SOL ? data.bond.contractAddress[data.bond.chainId] : data.billNftAddress\n const key = `${data?.bond?.chainId}-${contract}`\n\n if (!acc[key]) {\n acc[key] = {\n chainId: data?.bond?.chainId as number,\n contract: contract as string,\n billIds: [],\n }\n }\n\n acc[key].billIds.push(parseInt(data.id))\n return acc\n },\n {} as Record<string, { chainId: number; contract: string; billIds: number[] }>,\n ),\n )\n let response\n\n try {\n response = await axios.post(`${apiUrl}/bills/multi-batch`, body, { timeout: 40000 })\n } catch (e) {\n console.error(e)\n return onChainData\n }\n // Enrich on-chain data with API data.\n // Aptos/Sui bills are not sent to api-v2 (no support), so keep their existing\n // nftData populated by fetchBillsUser{Aptos,Sui} instead of overwriting with undefined.\n const enrichedData: UserBill[] = onChainData.map((userBond) => {\n if (userBond.bond?.chainId === ChainId.APTOS || userBond.bond?.chainId === ChainId.SUI) return userBond\n\n const nftDataResponse = response.data?.find((nft: any) => {\n const contract = nft.contract.toLowerCase()\n const chain = nft.chainId\n\n // API uses contractAddress for Solana bonds instead of NFT Address\n const contractToCompare =\n chain === ChainId.SOL ? userBond.bond?.contractAddress[ChainId.SOL] : userBond.billNftAddress\n return contractToCompare?.toLowerCase() === contract && userBond.bond?.chainId === chain\n })\n const nftData: UserBillNftData | undefined = nftDataResponse?.bills?.find(\n (billApiData: UserBillNftData) => billApiData.tokenId === parseInt(userBond.id),\n )\n return {\n ...userBond,\n nftData,\n }\n })\n\n return enrichedData\n } catch (e) {\n console.error(e)\n reportError({\n apiUrl,\n error: e,\n extraInfo: { type: 'getUserBonds', bondList, chains, e },\n account,\n })\n throw new Error('Failed to fetch user bonds')\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
2
|
import { QUERY_KEYS } from '../../config/constants/queryKeys.js';
|
|
3
3
|
|
|
4
4
|
function useHistoricalPrice(cgId) {
|
|
5
|
-
const queryClient = useQueryClient();
|
|
6
5
|
return useQuery({
|
|
7
6
|
queryKey: [QUERY_KEYS.HISTORICAL_PRICE, cgId || ''],
|
|
8
|
-
queryFn: () => getHistoricalPrice(cgId,
|
|
7
|
+
queryFn: ({ client }) => getHistoricalPrice(cgId, client),
|
|
9
8
|
refetchOnWindowFocus: false,
|
|
10
9
|
refetchInterval: 300000,
|
|
11
10
|
enabled: !!cgId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHistoricalPrice.js","sources":["../../../src/state/historicalPrice/useHistoricalPrice.ts"],"sourcesContent":["import { QueryClient, useQuery,
|
|
1
|
+
{"version":3,"file":"useHistoricalPrice.js","sources":["../../../src/state/historicalPrice/useHistoricalPrice.ts"],"sourcesContent":["import { QueryClient, useQuery, UseQueryResult } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../config/constants/queryKeys'\nimport { HistoricalPrices } from '../../views/ProjectView/ProjectView'\nimport { SDKProps } from '../useSDKConfig'\n\nexport default function useHistoricalPrice(cgId?: string): UseQueryResult<HistoricalPrices[]> {\n return useQuery({\n queryKey: [QUERY_KEYS.HISTORICAL_PRICE, cgId || ''],\n queryFn: ({ client }) => getHistoricalPrice(cgId, client),\n refetchOnWindowFocus: false,\n refetchInterval: 300000,\n enabled: !!cgId,\n retry: 0,\n })\n}\n\nexport const getHistoricalPrice = async (cgId?: string, queryClient?: QueryClient): Promise<HistoricalPrices[]> => {\n const { urls } = queryClient?.getQueryData([QUERY_KEYS.SDK_CONFIG]) as SDKProps\n const apiUrl = urls['apiV2']\n if (!cgId) return []\n const res = await fetch(`${apiUrl}/stats/historical-prices?cgId=${cgId}`)\n const data = await res.json()\n return data\n}\n"],"names":[],"mappings":";;;AAKc,SAAU,kBAAkB,CAAC,IAAa,EAAA;AACtD,IAAA,OAAO,QAAQ,CAAC;QACd,QAAQ,EAAE,CAAC,UAAU,CAAC,gBAAgB,EAAE,IAAI,IAAI,EAAE,CAAC;AACnD,QAAA,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC;AACzD,QAAA,oBAAoB,EAAE,KAAK;AAC3B,QAAA,eAAe,EAAE,MAAM;QACvB,OAAO,EAAE,CAAC,CAAC,IAAI;AACf,QAAA,KAAK,EAAE,CAAC;AACT,KAAA,CAAC;AACJ;AAEO,MAAM,kBAAkB,GAAG,OAAO,IAAa,EAAE,WAAyB,KAAiC;AAChH,IAAA,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,YAAY,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAa;AAC/E,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;AAC5B,IAAA,IAAI,CAAC,IAAI;AAAE,QAAA,OAAO,EAAE;IACpB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,8BAAA,EAAiC,IAAI,CAAA,CAAE,CAAC;AACzE,IAAA,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE;AAC7B,IAAA,OAAO,IAAI;AACb;;;;"}
|
|
@@ -32,7 +32,7 @@ const useSDKConfig = (config) => {
|
|
|
32
32
|
blockSales: false,
|
|
33
33
|
customBranch: '',
|
|
34
34
|
...config,
|
|
35
|
-
|
|
35
|
+
openWalletConnectors: {
|
|
36
36
|
evm: !!config?.openWalletConnectors?.evm,
|
|
37
37
|
sol: !!config?.openWalletConnectors?.sol,
|
|
38
38
|
sui: !!config?.openWalletConnectors?.sui,
|
|
@@ -54,7 +54,10 @@ const useSDKConfig = (config) => {
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
setCustomRPCS(customRPCS ?? {});
|
|
57
|
-
|
|
57
|
+
if (evmConnectorOpener) {
|
|
58
|
+
console.log('set evm wallet opener');
|
|
59
|
+
setWalletConnectorOpener('evm', evmConnectorOpener);
|
|
60
|
+
}
|
|
58
61
|
setWalletConnectorOpener('sol', solConnectorOpener);
|
|
59
62
|
setWalletConnectorOpener('sui', suiConnectorOpener);
|
|
60
63
|
setWalletConnectorOpener('aptos', aptosConnectorOpener);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSDKConfig.js","sources":["../../src/state/useSDKConfig.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../config/constants/queryKeys'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { setCustomRPCS } from '../config/constants/networks'\nimport { setWalletConnectorOpener } from '../config/constants/walletConnectors'\n\n// Prod URLS. Do not make changes here\nconst defaultUrls = {\n apiV2: 'https://api.ape.bond',\n realTimeApi: 'https://realtime-api.ape.bond',\n mainUrl: 'https://ape.bond',\n}\n\n// Staging URLS.\nconst stagingUrls = {\n apiV2: 'https://staging-api.ape.bond',\n realTimeApi: 'https://realtime-api-staging.ape.bond',\n mainUrl: 'https://staging.ape.bond',\n}\n\nexport interface OpenWalletConnectorsDTO {\n evm?: () => void\n sol?: () => void\n sui?: () => void\n aptos?: () => void\n}\n\nexport interface SDKPropsDTO {\n referenceId: string\n chains: number[]\n hotBondChains?: number[]\n useHotBonds?: boolean\n useTiers?: boolean\n useTGEBonds?: boolean\n useCardsView?: boolean\n showLowValueBonds?: boolean\n bondPartner?: string\n namingPreference?: 'Discount' | 'Bonus'\n urls?: Partial<Record<URLKeys, string>>\n theme?: any\n highestCompatibleVersion?: string\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n customRPCS?: Partial<Record<ChainId, string[]>>\n openWalletConnectors?: OpenWalletConnectorsDTO\n aptosAddress?: string\n suiAddress?: string\n suiTreasuryAddresses?: string[]\n}\n\nexport interface SDKProps {\n referenceId: string\n chains: number[]\n hotBondChains: number[]\n
|
|
1
|
+
{"version":3,"file":"useSDKConfig.js","sources":["../../src/state/useSDKConfig.ts"],"sourcesContent":["import { useEffect } from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../config/constants/queryKeys'\nimport { ChainId } from '@ape.swap/apeswap-lists'\nimport { setCustomRPCS } from '../config/constants/networks'\nimport { setWalletConnectorOpener } from '../config/constants/walletConnectors'\n\n// Prod URLS. Do not make changes here\nconst defaultUrls = {\n apiV2: 'https://api.ape.bond',\n realTimeApi: 'https://realtime-api.ape.bond',\n mainUrl: 'https://ape.bond',\n}\n\n// Staging URLS.\nconst stagingUrls = {\n apiV2: 'https://staging-api.ape.bond',\n realTimeApi: 'https://realtime-api-staging.ape.bond',\n mainUrl: 'https://staging.ape.bond',\n}\n\nexport interface OpenWalletConnectorsDTO {\n evm?: () => void\n sol?: () => void\n sui?: () => void\n aptos?: () => void\n}\n\nexport interface SDKPropsDTO {\n referenceId: string\n chains: number[]\n hotBondChains?: number[]\n useHotBonds?: boolean\n useTiers?: boolean\n useTGEBonds?: boolean\n useCardsView?: boolean\n showLowValueBonds?: boolean\n bondPartner?: string\n namingPreference?: 'Discount' | 'Bonus'\n urls?: Partial<Record<URLKeys, string>>\n theme?: any\n highestCompatibleVersion?: string\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n customRPCS?: Partial<Record<ChainId, string[]>>\n openWalletConnectors?: OpenWalletConnectorsDTO\n aptosAddress?: string\n suiAddress?: string\n suiTreasuryAddresses?: string[]\n}\n\nexport interface SDKProps {\n referenceId: string\n chains: number[]\n hotBondChains: number[]\n openWalletConnectors?: {\n evm?: boolean\n sol?: boolean\n sui?: boolean\n aptos?: boolean\n }\n useHotBonds: boolean\n useTiers: boolean\n useTGEBonds: boolean\n showLowValueBonds: boolean\n bondPartner?: string\n namingPreference: 'Discount' | 'Bonus'\n urls: Record<URLKeys, string>\n theme?: any\n highestCompatibleVersion?: string\n evmAddress?: string\n solAddress?: string\n aptosAddress?: string\n suiAddress?: string\n useCardsView?: boolean\n blockSales?: boolean\n customBranch?: string\n highlightedBond?: string\n}\n\nexport const useSDKConfig = (config?: SDKPropsDTO): SDKProps => {\n const urls = process.env.NODE_ENV === 'production' ? defaultUrls : stagingUrls\n\n const initialData: SDKProps = {\n referenceId: '',\n chains: [],\n hotBondChains: [ChainId.BSC, ChainId.MATIC],\n useHotBonds: true,\n useTGEBonds: false,\n showLowValueBonds: false,\n bondPartner: undefined,\n namingPreference: 'Bonus',\n useCardsView: false,\n blockSales: false,\n customBranch: '',\n ...config,\n openWalletConnectors: {\n evm: !!config?.openWalletConnectors?.evm,\n sol: !!config?.openWalletConnectors?.sol,\n sui: !!config?.openWalletConnectors?.sui,\n aptos: !!config?.openWalletConnectors?.aptos,\n },\n useTiers: config?.namingPreference === 'Discount' ? false : (config?.useTiers ?? false), // for the time being we'll assume discount preference does not want to useTiers\n urls: { ...urls, ...config?.urls },\n highestCompatibleVersion: '2.2.0',\n }\n\n const hasConfig = config !== undefined\n const customRPCS = config?.customRPCS\n const evmConnectorOpener = config?.openWalletConnectors?.evm\n const solConnectorOpener = config?.openWalletConnectors?.sol\n const suiConnectorOpener = config?.openWalletConnectors?.sui\n const aptosConnectorOpener = config?.openWalletConnectors?.aptos\n\n useEffect(() => {\n // Calls without config only read shared settings and must not overwrite their registries.\n if (!hasConfig) {\n return\n }\n setCustomRPCS(customRPCS ?? {})\n if (evmConnectorOpener) {\n console.log('set evm wallet opener')\n setWalletConnectorOpener('evm', evmConnectorOpener)\n }\n setWalletConnectorOpener('sol', solConnectorOpener)\n setWalletConnectorOpener('sui', suiConnectorOpener)\n setWalletConnectorOpener('aptos', aptosConnectorOpener)\n }, [hasConfig, customRPCS, evmConnectorOpener, solConnectorOpener, suiConnectorOpener, aptosConnectorOpener])\n\n const { data } = useQuery({\n queryKey: [QUERY_KEYS.SDK_CONFIG],\n queryFn: () => {\n throw new Error('Just a hotfix for latest versions of react-query that make queryFn a required prop')\n },\n initialData,\n })\n return data as SDKProps\n}\n\nexport type URLKeys = 'apiV2' | 'realTimeApi' | 'mainUrl'\n\nexport const useURLByEnvironment = (key: URLKeys) => {\n const config = useSDKConfig()\n return config?.urls?.[key] as string\n}\n"],"names":[],"mappings":";;;;;;;AAOA;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,sBAAsB;AAC7B,IAAA,WAAW,EAAE,+BAA+B;AAC5C,IAAA,OAAO,EAAE,kBAAkB;CAC5B;AAED;AACA,MAAM,WAAW,GAAG;AAClB,IAAA,KAAK,EAAE,8BAA8B;AACrC,IAAA,WAAW,EAAE,uCAAuC;AACpD,IAAA,OAAO,EAAE,0BAA0B;CACpC;AA8DM,MAAM,YAAY,GAAG,CAAC,MAAoB,KAAc;AAC7D,IAAA,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,GAAG,WAAW,GAAG,WAAW;AAE9E,IAAA,MAAM,WAAW,GAAa;AAC5B,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,MAAM,EAAE,EAAE;QACV,aAAa,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC;AAC3C,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,WAAW,EAAE,KAAK;AAClB,QAAA,iBAAiB,EAAE,KAAK;AACxB,QAAA,WAAW,EAAE,SAAS;AACtB,QAAA,gBAAgB,EAAE,OAAO;AACzB,QAAA,YAAY,EAAE,KAAK;AACnB,QAAA,UAAU,EAAE,KAAK;AACjB,QAAA,YAAY,EAAE,EAAE;AAChB,QAAA,GAAG,MAAM;AACT,QAAA,oBAAoB,EAAE;AACpB,YAAA,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG;AACxC,YAAA,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG;AACxC,YAAA,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,oBAAoB,EAAE,GAAG;AACxC,YAAA,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK;AAC7C,SAAA;QACD,QAAQ,EAAE,MAAM,EAAE,gBAAgB,KAAK,UAAU,GAAG,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,KAAK,CAAC;QACvF,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE;AAClC,QAAA,wBAAwB,EAAE,OAAO;KAClC;AAED,IAAA,MAAM,SAAS,GAAG,MAAM,KAAK,SAAS;AACtC,IAAA,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU;AACrC,IAAA,MAAM,kBAAkB,GAAG,MAAM,EAAE,oBAAoB,EAAE,GAAG;AAC5D,IAAA,MAAM,kBAAkB,GAAG,MAAM,EAAE,oBAAoB,EAAE,GAAG;AAC5D,IAAA,MAAM,kBAAkB,GAAG,MAAM,EAAE,oBAAoB,EAAE,GAAG;AAC5D,IAAA,MAAM,oBAAoB,GAAG,MAAM,EAAE,oBAAoB,EAAE,KAAK;IAEhE,SAAS,CAAC,MAAK;;QAEb,IAAI,CAAC,SAAS,EAAE;YACd;QACF;AACA,QAAA,aAAa,CAAC,UAAU,IAAI,EAAE,CAAC;QAC/B,IAAI,kBAAkB,EAAE;AACtB,YAAA,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;AACpC,YAAA,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,CAAC;QACrD;AACA,QAAA,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,CAAC;AACnD,QAAA,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,CAAC;AACnD,QAAA,wBAAwB,CAAC,OAAO,EAAE,oBAAoB,CAAC;AACzD,IAAA,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,oBAAoB,CAAC,CAAC;AAE7G,IAAA,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;AACxB,QAAA,QAAQ,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QACjC,OAAO,EAAE,MAAK;AACZ,YAAA,MAAM,IAAI,KAAK,CAAC,oFAAoF,CAAC;QACvG,CAAC;QACD,WAAW;AACZ,KAAA,CAAC;AACF,IAAA,OAAO,IAAgB;AACzB;AAIO,MAAM,mBAAmB,GAAG,CAAC,GAAY,KAAI;AAClD,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;AAC7B,IAAA,OAAO,MAAM,EAAE,IAAI,GAAG,GAAG,CAAW;AACtC;;;;"}
|
|
@@ -10,7 +10,8 @@ declare enum NetworkNames {
|
|
|
10
10
|
BLAST = "bls",
|
|
11
11
|
SONIC = "son",
|
|
12
12
|
BERACHAIN = "ber",
|
|
13
|
-
HYPEREVM = "hyp"
|
|
13
|
+
HYPEREVM = "hyp",
|
|
14
|
+
ROBINHOOD = "rob"
|
|
14
15
|
}
|
|
15
16
|
export declare const getChainParam: (chain?: ChainId) => NetworkNames | null;
|
|
16
17
|
export declare const getLpType: (protocol?: Protocols) => "ichi" | "solidly" | "univ2" | "curve" | null;
|
|
@@ -13,6 +13,7 @@ var NetworkNames;
|
|
|
13
13
|
NetworkNames["SONIC"] = "son";
|
|
14
14
|
NetworkNames["BERACHAIN"] = "ber";
|
|
15
15
|
NetworkNames["HYPEREVM"] = "hyp";
|
|
16
|
+
NetworkNames["ROBINHOOD"] = "rob";
|
|
16
17
|
})(NetworkNames || (NetworkNames = {}));
|
|
17
18
|
const getChainParam = (chain) => {
|
|
18
19
|
return chain === ChainId.LINEA
|
|
@@ -37,7 +38,9 @@ const getChainParam = (chain) => {
|
|
|
37
38
|
? NetworkNames.BERACHAIN
|
|
38
39
|
: chain === ChainId.HYPEREVM
|
|
39
40
|
? NetworkNames.HYPEREVM
|
|
40
|
-
:
|
|
41
|
+
: chain === ChainId.ROBINHOOD
|
|
42
|
+
? NetworkNames.ROBINHOOD
|
|
43
|
+
: null;
|
|
41
44
|
};
|
|
42
45
|
const getLpType = (protocol) => {
|
|
43
46
|
return protocol === Protocols.Algebra
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getChainParam.js","sources":["../../../src/state/zap/getChainParam.ts"],"sourcesContent":["import { ChainId, Protocols } from '@ape.swap/apeswap-lists'\n\nenum NetworkNames {\n MAINNET = 'eth',\n BNB = 'bnb',\n POLYGON = 'pol',\n ARBITRUM = 'arb',\n LINEA = 'lna',\n BASE = 'bas',\n AVAX = 'ava',\n BLAST = 'bls',\n SONIC = 'son',\n BERACHAIN = 'ber',\n HYPEREVM = 'hyp',\n}\n\nexport const getChainParam = (chain?: ChainId): NetworkNames | null => {\n return chain === ChainId.LINEA\n ? NetworkNames.LINEA\n : chain === ChainId.MATIC\n ? NetworkNames.POLYGON\n : chain === ChainId.BSC\n ? NetworkNames.BNB\n : chain === ChainId.BASE\n ? NetworkNames.BASE\n : chain === ChainId.ARBITRUM\n ? NetworkNames.ARBITRUM\n : chain === ChainId.MAINNET\n ? NetworkNames.MAINNET\n : chain === ChainId.AVAX\n ? NetworkNames.AVAX\n : chain === ChainId.BLAST\n ? NetworkNames.BLAST\n : chain === ChainId.SONIC\n ? NetworkNames.SONIC\n : chain === ChainId.BERACHAIN\n ? NetworkNames.BERACHAIN\n : chain === ChainId.HYPEREVM\n ? NetworkNames.HYPEREVM\n : null\n}\n\nexport const getLpType = (protocol?: Protocols): 'ichi' | 'solidly' | 'univ2' | 'curve' | null => {\n return protocol === Protocols.Algebra\n ? 'ichi'\n : protocol === Protocols.Solidly\n ? 'solidly'\n : protocol === Protocols.V2\n ? 'univ2'\n : protocol === Protocols.V3 // This might be a hot fix. Lets revisit this on the future\n ? 'ichi'\n : protocol === Protocols.Curve\n ? 'curve'\n : null\n}\n"],"names":[],"mappings":";;AAEA,IAAK,
|
|
1
|
+
{"version":3,"file":"getChainParam.js","sources":["../../../src/state/zap/getChainParam.ts"],"sourcesContent":["import { ChainId, Protocols } from '@ape.swap/apeswap-lists'\n\nenum NetworkNames {\n MAINNET = 'eth',\n BNB = 'bnb',\n POLYGON = 'pol',\n ARBITRUM = 'arb',\n LINEA = 'lna',\n BASE = 'bas',\n AVAX = 'ava',\n BLAST = 'bls',\n SONIC = 'son',\n BERACHAIN = 'ber',\n HYPEREVM = 'hyp',\n ROBINHOOD = 'rob',\n}\n\nexport const getChainParam = (chain?: ChainId): NetworkNames | null => {\n return chain === ChainId.LINEA\n ? NetworkNames.LINEA\n : chain === ChainId.MATIC\n ? NetworkNames.POLYGON\n : chain === ChainId.BSC\n ? NetworkNames.BNB\n : chain === ChainId.BASE\n ? NetworkNames.BASE\n : chain === ChainId.ARBITRUM\n ? NetworkNames.ARBITRUM\n : chain === ChainId.MAINNET\n ? NetworkNames.MAINNET\n : chain === ChainId.AVAX\n ? NetworkNames.AVAX\n : chain === ChainId.BLAST\n ? NetworkNames.BLAST\n : chain === ChainId.SONIC\n ? NetworkNames.SONIC\n : chain === ChainId.BERACHAIN\n ? NetworkNames.BERACHAIN\n : chain === ChainId.HYPEREVM\n ? NetworkNames.HYPEREVM\n : chain === ChainId.ROBINHOOD\n ? NetworkNames.ROBINHOOD\n : null\n}\n\nexport const getLpType = (protocol?: Protocols): 'ichi' | 'solidly' | 'univ2' | 'curve' | null => {\n return protocol === Protocols.Algebra\n ? 'ichi'\n : protocol === Protocols.Solidly\n ? 'solidly'\n : protocol === Protocols.V2\n ? 'univ2'\n : protocol === Protocols.V3 // This might be a hot fix. Lets revisit this on the future\n ? 'ichi'\n : protocol === Protocols.Curve\n ? 'curve'\n : null\n}\n"],"names":[],"mappings":";;AAEA,IAAK,YAaJ;AAbD,CAAA,UAAK,YAAY,EAAA;AACf,IAAA,YAAA,CAAA,SAAA,CAAA,GAAA,KAAe;AACf,IAAA,YAAA,CAAA,KAAA,CAAA,GAAA,KAAW;AACX,IAAA,YAAA,CAAA,SAAA,CAAA,GAAA,KAAe;AACf,IAAA,YAAA,CAAA,UAAA,CAAA,GAAA,KAAgB;AAChB,IAAA,YAAA,CAAA,OAAA,CAAA,GAAA,KAAa;AACb,IAAA,YAAA,CAAA,MAAA,CAAA,GAAA,KAAY;AACZ,IAAA,YAAA,CAAA,MAAA,CAAA,GAAA,KAAY;AACZ,IAAA,YAAA,CAAA,OAAA,CAAA,GAAA,KAAa;AACb,IAAA,YAAA,CAAA,OAAA,CAAA,GAAA,KAAa;AACb,IAAA,YAAA,CAAA,WAAA,CAAA,GAAA,KAAiB;AACjB,IAAA,YAAA,CAAA,UAAA,CAAA,GAAA,KAAgB;AAChB,IAAA,YAAA,CAAA,WAAA,CAAA,GAAA,KAAiB;AACnB,CAAC,EAbI,YAAY,KAAZ,YAAY,GAAA,EAAA,CAAA,CAAA;AAeV,MAAM,aAAa,GAAG,CAAC,KAAe,KAAyB;AACpE,IAAA,OAAO,KAAK,KAAK,OAAO,CAAC;UACrB,YAAY,CAAC;AACf,UAAE,KAAK,KAAK,OAAO,CAAC;cAChB,YAAY,CAAC;AACf,cAAE,KAAK,KAAK,OAAO,CAAC;kBAChB,YAAY,CAAC;AACf,kBAAE,KAAK,KAAK,OAAO,CAAC;sBAChB,YAAY,CAAC;AACf,sBAAE,KAAK,KAAK,OAAO,CAAC;0BAChB,YAAY,CAAC;AACf,0BAAE,KAAK,KAAK,OAAO,CAAC;8BAChB,YAAY,CAAC;AACf,8BAAE,KAAK,KAAK,OAAO,CAAC;kCAChB,YAAY,CAAC;AACf,kCAAE,KAAK,KAAK,OAAO,CAAC;sCAChB,YAAY,CAAC;AACf,sCAAE,KAAK,KAAK,OAAO,CAAC;0CAChB,YAAY,CAAC;AACf,0CAAE,KAAK,KAAK,OAAO,CAAC;8CAChB,YAAY,CAAC;AACf,8CAAE,KAAK,KAAK,OAAO,CAAC;kDAChB,YAAY,CAAC;AACf,kDAAE,KAAK,KAAK,OAAO,CAAC;sDAChB,YAAY,CAAC;sDACb,IAAI;AAChC;AAEO,MAAM,SAAS,GAAG,CAAC,QAAoB,KAAmD;AAC/F,IAAA,OAAO,QAAQ,KAAK,SAAS,CAAC;AAC5B,UAAE;AACF,UAAE,QAAQ,KAAK,SAAS,CAAC;AACvB,cAAE;AACF,cAAE,QAAQ,KAAK,SAAS,CAAC;AACvB,kBAAE;AACF,kBAAE,QAAQ,KAAK,SAAS,CAAC,EAAE;AACzB,sBAAE;AACF,sBAAE,QAAQ,KAAK,SAAS,CAAC;AACvB,0BAAE;0BACA,IAAI;AAClB;;;;"}
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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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"}
|
|
@@ -72,6 +72,30 @@ const bytesToHex = (bytes) => {
|
|
|
72
72
|
}
|
|
73
73
|
return out;
|
|
74
74
|
};
|
|
75
|
+
const extractEventData = (txn, eventSuffix) => {
|
|
76
|
+
const event = txn?.events?.find((e) => e.type.includes(eventSuffix));
|
|
77
|
+
return event?.data;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* `bond::DepositEvent` — emitted by the deposit entry function.
|
|
81
|
+
* Contains bill_id, bill_address, deposit_amount, payout_amount, price.
|
|
82
|
+
*/
|
|
83
|
+
const extractDepositEvent = (txn) => extractEventData(txn, '::DepositEvent');
|
|
84
|
+
/**
|
|
85
|
+
* Extract bill_id from transaction events. Checks both `BillMinted` (from bond_nft)
|
|
86
|
+
* and `DepositEvent` (from bond) since the contract emits both.
|
|
87
|
+
*/
|
|
88
|
+
const extractBillMinted = (txn) => {
|
|
89
|
+
// Try BillMinted event first (emitted by bond_nft module)
|
|
90
|
+
const billMinted = extractEventData(txn, '::BillMinted');
|
|
91
|
+
if (billMinted)
|
|
92
|
+
return billMinted;
|
|
93
|
+
// Fall back to DepositEvent (emitted by bond module)
|
|
94
|
+
const deposit = extractDepositEvent(txn);
|
|
95
|
+
if (!deposit)
|
|
96
|
+
return undefined;
|
|
97
|
+
return { bill_id: deposit.bill_id, owner: deposit.depositor };
|
|
98
|
+
};
|
|
75
99
|
// ---------------------------------------------------------------------------
|
|
76
100
|
// View function readers (PLAN_001 Etapa 5b — real read skeleton)
|
|
77
101
|
// ---------------------------------------------------------------------------
|
|
@@ -174,5 +198,5 @@ const readNftAddressByBillId = async (billId) => {
|
|
|
174
198
|
return String(result[0] ?? '');
|
|
175
199
|
};
|
|
176
200
|
|
|
177
|
-
export { getAptosClient, readAptosBillInfo, readAptosMarketInfo, readBondMarketByBillId, readNftAddressByBillId, readUserBillIds, readVestingProgress, safeExtractAddress };
|
|
201
|
+
export { extractBillMinted, extractDepositEvent, extractEventData, getAptosClient, readAptosBillInfo, readAptosMarketInfo, readBondMarketByBillId, readNftAddressByBillId, readUserBillIds, readVestingProgress, safeExtractAddress };
|
|
178
202
|
//# sourceMappingURL=aptosHelpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aptosHelpers.js","sources":["../../src/utils/aptosHelpers.ts"],"sourcesContent":["import { Aptos, AptosConfig } from '@aptos-labs/ts-sdk'\nimport BigNumber from 'bignumber.js'\nimport {\n APTOS_CLAIM_FUNCTION,\n APTOS_DEPOSIT_FUNCTION,\n APTOS_FULLNODE_URL,\n APTOS_NETWORK,\n APTOS_VIEW_BILL_INFO,\n APTOS_VIEW_BOND_MARKET_BY_ID,\n APTOS_VIEW_MARKET_INFO,\n APTOS_VIEW_NFT_ADDRESS,\n APTOS_VIEW_USER_BILLS,\n APTOS_VIEW_VESTING_PROGRESS,\n getRandomAptosApiKey,\n} from '../constants/aptosConstants'\nimport type {\n AptosBillInfo,\n AptosClaimPayload,\n AptosDepositPayload,\n AptosMarketInfoTuple,\n AptosVestingProgressTuple,\n} from '../types/aptosBonds'\n\n// ---------------------------------------------------------------------------\n// Aptos client — lazy singleton\n// ---------------------------------------------------------------------------\n// We keep one client per (network, api key) pair. The API key is picked with\n// `getRandomAptosApiKey()` on first call, so different sessions hit a\n// different key (very simple load balancing). If the pool is empty we fall\n// back to unauthenticated requests.\nlet _aptosClient: Aptos | undefined\n\nexport const getAptosClient = (): Aptos => {\n if (_aptosClient) return _aptosClient\n const apiKey = getRandomAptosApiKey()\n // The Aptos ts-sdk exposes `API_KEY` directly on `clientConfig`; it adds\n // the `Authorization: Bearer <key>` header internally. This is the\n // idiomatic way to authenticate — no manual header wiring needed.\n const config = new AptosConfig({\n network: APTOS_NETWORK,\n ...(apiKey && { clientConfig: { API_KEY: apiKey } }),\n })\n _aptosClient = new Aptos(config)\n return _aptosClient\n}\n\n// ---------------------------------------------------------------------------\n// Address normalisation\n// ---------------------------------------------------------------------------\n// Aptos wallet adapters can surface account addresses in several shapes:\n// plain string, `{ data: Uint8Array }`, `Uint8Array`, or an `AccountAddress`\n// instance. This helper returns a canonical `0x`-prefixed hex string, or\n// `undefined` if the input cannot be decoded. We keep the interface loose so\n// callers can pass whatever the SDK hands them.\nexport const safeExtractAddress = (input: unknown): string | undefined => {\n if (input == null) return undefined\n\n // Already a string\n if (typeof input === 'string') {\n return input.startsWith('0x') ? input : `0x${input}`\n }\n\n // AccountAddress instance (has `toString()` that returns `0x...`)\n if (typeof input === 'object' && typeof (input as { toString?: () => string }).toString === 'function') {\n const asObject = input as { data?: Uint8Array | number[]; toString: () => string }\n // Prefer `.data` if it looks like a byte array — `.toString()` on\n // AccountAddress already returns the canonical hex, but some wallets\n // return `{ data: Uint8Array }` without the method.\n if (asObject.data instanceof Uint8Array) {\n return bytesToHex(asObject.data)\n }\n if (Array.isArray(asObject.data)) {\n return bytesToHex(new Uint8Array(asObject.data))\n }\n const stringified = asObject.toString()\n if (stringified.startsWith('0x')) return stringified\n }\n\n // Raw Uint8Array\n if (input instanceof Uint8Array) {\n return bytesToHex(input)\n }\n\n // Raw number[]\n if (Array.isArray(input)) {\n return bytesToHex(new Uint8Array(input))\n }\n\n return undefined\n}\n\nconst bytesToHex = (bytes: Uint8Array): string => {\n let out = '0x'\n for (let i = 0; i < bytes.length; i++) {\n out += bytes[i].toString(16).padStart(2, '0')\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Unit conversion\n// ---------------------------------------------------------------------------\n// User inputs live in \"whole tokens\" (e.g. \"1.5 USDC\"). The Aptos ts-sdk\n// serialises numeric function arguments from strings, so we convert to\n// atomic units and return a stringified BigInt.\nexport const toAtomicUnits = (amount: string | number, decimals: number): string => {\n if (amount === '' || amount == null) return '0'\n const bn = new BigNumber(amount).times(new BigNumber(10).pow(decimals))\n // Floor so we never over-spend what the user typed.\n return bn.integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n}\n\n// ---------------------------------------------------------------------------\n// Payload builders\n// ---------------------------------------------------------------------------\n// These return the `InputEntryFunctionData` shape consumed by\n// `wallet.signAndSubmitTransaction({ sender, data: ... })`. Keeping them in\n// one place means the buy/claim components do not have to repeat the\n// function-name and argument order.\n\nexport const buildDepositPayload = (args: AptosDepositPayload) => ({\n function: APTOS_DEPOSIT_FUNCTION,\n typeArguments: [] as string[],\n functionArguments: [args.market, args.amount, args.max_price, args.depositor] as (string | number)[],\n})\n\nexport const buildClaimPayload = (args: AptosClaimPayload) => ({\n function: APTOS_CLAIM_FUNCTION,\n typeArguments: [] as string[],\n // `apebond::bond::claim(market, bill_id: u64)` — the contract takes the\n // scalar bill_id, NOT the object address.\n functionArguments: [args.market, args.bill_id] as (string | number)[],\n})\n\n// ---------------------------------------------------------------------------\n// Event extractors\n// ---------------------------------------------------------------------------\n// Parse events out of a `waitForTransaction` response. The event `type`\n// format is `${module}::${EventStruct}`. We match by `.endsWith('::Foo')` so\n// we do not have to hard-code the full module path (which contains the\n// contract address).\n\ninterface AptosTxnWithEvents {\n events?: Array<{ type: string; data: Record<string, unknown> }>\n}\n\nexport const extractEventData = <T = Record<string, unknown>>(\n txn: AptosTxnWithEvents,\n eventSuffix: string,\n): T | undefined => {\n const event = txn?.events?.find((e) => e.type.includes(eventSuffix))\n return event?.data as T | undefined\n}\n\n/**\n * `bond::DepositEvent` — emitted by the deposit entry function.\n * Contains bill_id, bill_address, deposit_amount, payout_amount, price.\n */\nexport const extractDepositEvent = (\n txn: AptosTxnWithEvents,\n):\n | {\n bill_id: string\n bill_address: string\n market: string\n deposit_amount: string\n payout_amount: string\n price: string\n depositor: string\n recipient: string\n }\n | undefined => extractEventData(txn, '::DepositEvent')\n\n/**\n * Extract bill_id from transaction events. Checks both `BillMinted` (from bond_nft)\n * and `DepositEvent` (from bond) since the contract emits both.\n */\nexport const extractBillMinted = (txn: AptosTxnWithEvents): { bill_id: string; owner: string } | undefined => {\n // Try BillMinted event first (emitted by bond_nft module)\n const billMinted = extractEventData<{ bill_id: string; owner: string }>(txn, '::BillMinted')\n if (billMinted) return billMinted\n // Fall back to DepositEvent (emitted by bond module)\n const deposit = extractDepositEvent(txn)\n if (!deposit) return undefined\n return { bill_id: deposit.bill_id, owner: deposit.depositor }\n}\n\n// ---------------------------------------------------------------------------\n// Fetch helper — GraphQL to the Aptos indexer\n// ---------------------------------------------------------------------------\n// Uses the same API key that is configured on the Aptos client. Everything\n// else on the HTTP layer goes through the Aptos ts-sdk, but the indexer\n// needs a raw `fetch` call because GraphQL is not part of the SDK surface.\nexport const aptosIndexerFetch = async <T = unknown>(\n url: string,\n query: string,\n variables?: Record<string, unknown>,\n): Promise<T> => {\n const apiKey = getRandomAptosApiKey()\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && { Authorization: `Bearer ${apiKey}` }),\n },\n body: JSON.stringify({ query, variables }),\n })\n if (!response.ok) {\n throw new Error(`Aptos indexer request failed: ${response.status}`)\n }\n const json = (await response.json()) as { data: T; errors?: Array<{ message: string }> }\n if (json.errors?.length) {\n throw new Error(`Aptos indexer returned errors: ${json.errors.map((e) => e.message).join(', ')}`)\n }\n return json.data\n}\n\n// ---------------------------------------------------------------------------\n// View function readers (PLAN_001 Etapa 5b — real read skeleton)\n// ---------------------------------------------------------------------------\n// Thin wrappers around `aptos.view(...)` for the specific view functions the\n// SDK needs. Every reader throws on RPC / contract error — callers should\n// wrap in try/catch so a missing deployment degrades gracefully rather than\n// crashing the UI.\n//\n// Shapes are verified against apebond-move-playground pages. See the matching\n// `AptosMarketInfoTuple` / `AptosBillInfo` / `AptosVestingProgressTuple`\n// types for documentation on each field.\n\n/**\n * `bond::market_info(market)` — returns the 27-element market info tuple.\n */\nexport const readAptosMarketInfo = async (marketAddress: string): Promise<AptosMarketInfoTuple> => {\n const aptos = getAptosClient()\n const result = await aptos.view({\n payload: {\n function: APTOS_VIEW_MARKET_INFO,\n functionArguments: [marketAddress],\n },\n })\n return result as unknown as AptosMarketInfoTuple\n}\n\n/**\n * `bond::bill_info(market, bill_id)` — returns the Bill struct for a\n * specific bill. The contract takes `bill_id: u64` (NOT the object address).\n * Uses REST directly to avoid SDK remoteAbi serialisation bug with u64 args.\n */\nexport const readAptosBillInfo = async (marketAddress: string, billId: string): Promise<AptosBillInfo> => {\n const result = await viewViaRest(APTOS_VIEW_BILL_INFO, [marketAddress, billId])\n return result[0] as unknown as AptosBillInfo\n}\n\n/**\n * `bond_nft::user_bills(user)` — returns all bill_ids owned by the user\n * across every deployed market. The view returns `[bill_ids]` (the inner\n * array is at index 0), so we unwrap it here.\n */\nexport const readUserBillIds = async (user: string): Promise<string[]> => {\n const aptos = getAptosClient()\n const result = await aptos.view({\n payload: {\n function: APTOS_VIEW_USER_BILLS,\n functionArguments: [user],\n },\n })\n const ids = (result[0] ?? []) as unknown as Array<string | number>\n return ids.map((id) => String(id))\n}\n\n/**\n * `bond::vesting_progress(market, bill_id)` — returns `[vested_amount, claimable_amount]`.\n * Note: this is in `bond` module (not `bond_nft`), and takes the market as first argument.\n * Uses REST directly to avoid SDK remoteAbi serialisation bug with u64 args.\n */\nexport const readVestingProgress = async (\n marketAddress: string,\n billId: string,\n): Promise<AptosVestingProgressTuple> => {\n const result = await viewViaRest(APTOS_VIEW_VESTING_PROGRESS, [marketAddress, billId])\n return [String(result[0] ?? '0'), String(result[1] ?? '0')] as const\n}\n\n// ---------------------------------------------------------------------------\n// REST-based view call — bypasses the SDK's remoteAbi serialisation which\n// has a bug in v6.x where u64 arguments to functions returning `address` get\n// mis-serialised. The REST endpoint handles string arguments natively.\n// ---------------------------------------------------------------------------\nconst viewViaRest = async (fn: string, args: string[], typeArgs: string[] = []): Promise<unknown[]> => {\n const apiKey = getRandomAptosApiKey()\n const res = await fetch(`${APTOS_FULLNODE_URL}/view`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && { Authorization: `Bearer ${apiKey}` }),\n },\n body: JSON.stringify({\n function: fn,\n type_arguments: typeArgs,\n arguments: args,\n }),\n })\n if (!res.ok) {\n const text = await res.text()\n throw new Error(`View call ${fn} failed: ${res.status} ${text}`)\n }\n return (await res.json()) as unknown[]\n}\n\n/**\n * `bond_nft::bond_market_by_id(bill_id)` — which market owns this bill.\n * Uses REST directly — SDK's aptos.view() mis-serialises u64→address functions.\n */\nexport const readBondMarketByBillId = async (billId: string): Promise<string> => {\n const result = await viewViaRest(APTOS_VIEW_BOND_MARKET_BY_ID, [billId])\n return String(result[0] ?? '')\n}\n\n/**\n * `bond_nft::nft_address(bill_id)` — resolve the scalar bill_id to the\n * on-chain NFT object address (aka `bill_addr`). Needed to then call\n * `bond::bill_info(market, bill_addr)` or `bond::claim(market, bill_addr)`.\n * Uses REST directly — SDK's aptos.view() mis-serialises u64→address functions.\n */\nexport const readNftAddressByBillId = async (billId: string): Promise<string> => {\n const result = await viewViaRest(APTOS_VIEW_NFT_ADDRESS, [billId])\n return String(result[0] ?? '')\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aptosHelpers.js","sources":["../../src/utils/aptosHelpers.ts"],"sourcesContent":["import { Aptos, AptosConfig } from '@aptos-labs/ts-sdk'\nimport BigNumber from 'bignumber.js'\nimport {\n APTOS_CLAIM_FUNCTION,\n APTOS_DEPOSIT_FUNCTION,\n APTOS_FULLNODE_URL,\n APTOS_NETWORK,\n APTOS_VIEW_BILL_INFO,\n APTOS_VIEW_BOND_MARKET_BY_ID,\n APTOS_VIEW_MARKET_INFO,\n APTOS_VIEW_NFT_ADDRESS,\n APTOS_VIEW_USER_BILLS,\n APTOS_VIEW_VESTING_PROGRESS,\n getRandomAptosApiKey,\n} from '../constants/aptosConstants'\nimport type {\n AptosBillInfo,\n AptosClaimPayload,\n AptosDepositPayload,\n AptosMarketInfoTuple,\n AptosVestingProgressTuple,\n} from '../types/aptosBonds'\n\n// ---------------------------------------------------------------------------\n// Aptos client — lazy singleton\n// ---------------------------------------------------------------------------\n// We keep one client per (network, api key) pair. The API key is picked with\n// `getRandomAptosApiKey()` on first call, so different sessions hit a\n// different key (very simple load balancing). If the pool is empty we fall\n// back to unauthenticated requests.\nlet _aptosClient: Aptos | undefined\n\nexport const getAptosClient = (): Aptos => {\n if (_aptosClient) return _aptosClient\n const apiKey = getRandomAptosApiKey()\n // The Aptos ts-sdk exposes `API_KEY` directly on `clientConfig`; it adds\n // the `Authorization: Bearer <key>` header internally. This is the\n // idiomatic way to authenticate — no manual header wiring needed.\n const config = new AptosConfig({\n network: APTOS_NETWORK,\n ...(apiKey && { clientConfig: { API_KEY: apiKey } }),\n })\n _aptosClient = new Aptos(config)\n return _aptosClient\n}\n\n// ---------------------------------------------------------------------------\n// Address normalisation\n// ---------------------------------------------------------------------------\n// Aptos wallet adapters can surface account addresses in several shapes:\n// plain string, `{ data: Uint8Array }`, `Uint8Array`, or an `AccountAddress`\n// instance. This helper returns a canonical `0x`-prefixed hex string, or\n// `undefined` if the input cannot be decoded. We keep the interface loose so\n// callers can pass whatever the SDK hands them.\nexport const safeExtractAddress = (input: unknown): string | undefined => {\n if (input == null) return undefined\n\n // Already a string\n if (typeof input === 'string') {\n return input.startsWith('0x') ? input : `0x${input}`\n }\n\n // AccountAddress instance (has `toString()` that returns `0x...`)\n if (typeof input === 'object' && typeof (input as { toString?: () => string }).toString === 'function') {\n const asObject = input as { data?: Uint8Array | number[]; toString: () => string }\n // Prefer `.data` if it looks like a byte array — `.toString()` on\n // AccountAddress already returns the canonical hex, but some wallets\n // return `{ data: Uint8Array }` without the method.\n if (asObject.data instanceof Uint8Array) {\n return bytesToHex(asObject.data)\n }\n if (Array.isArray(asObject.data)) {\n return bytesToHex(new Uint8Array(asObject.data))\n }\n const stringified = asObject.toString()\n if (stringified.startsWith('0x')) return stringified\n }\n\n // Raw Uint8Array\n if (input instanceof Uint8Array) {\n return bytesToHex(input)\n }\n\n // Raw number[]\n if (Array.isArray(input)) {\n return bytesToHex(new Uint8Array(input))\n }\n\n return undefined\n}\n\nconst bytesToHex = (bytes: Uint8Array): string => {\n let out = '0x'\n for (let i = 0; i < bytes.length; i++) {\n out += bytes[i].toString(16).padStart(2, '0')\n }\n return out\n}\n\n// ---------------------------------------------------------------------------\n// Unit conversion\n// ---------------------------------------------------------------------------\n// User inputs live in \"whole tokens\" (e.g. \"1.5 USDC\"). The Aptos ts-sdk\n// serialises numeric function arguments from strings, so we convert to\n// atomic units and return a stringified BigInt.\nexport const toAtomicUnits = (amount: string | number, decimals: number): string => {\n if (amount === '' || amount == null) return '0'\n const bn = new BigNumber(amount).times(new BigNumber(10).pow(decimals))\n // Floor so we never over-spend what the user typed.\n return bn.integerValue(BigNumber.ROUND_FLOOR).toFixed(0)\n}\n\n// ---------------------------------------------------------------------------\n// Payload builders\n// ---------------------------------------------------------------------------\n// These return the `InputEntryFunctionData` shape consumed by\n// `wallet.signAndSubmitTransaction({ sender, data: ... })`. Keeping them in\n// one place means the buy/claim components do not have to repeat the\n// function-name and argument order.\n\nexport const buildDepositPayload = (args: AptosDepositPayload) => ({\n function: APTOS_DEPOSIT_FUNCTION,\n typeArguments: [] as string[],\n functionArguments: [args.market, args.amount, args.max_price, args.depositor] as (string | number)[],\n})\n\nexport const buildClaimPayload = (args: AptosClaimPayload) => ({\n function: APTOS_CLAIM_FUNCTION,\n typeArguments: [] as string[],\n // `apebond::bond::claim(market, bill_id: u64)` — the contract takes the\n // scalar bill_id, NOT the object address.\n functionArguments: [args.market, args.bill_id] as (string | number)[],\n})\n\n// ---------------------------------------------------------------------------\n// Event extractors\n// ---------------------------------------------------------------------------\n// Parse events out of a `waitForTransaction` response. The event `type`\n// format is `${module}::${EventStruct}`. We match by `.endsWith('::Foo')` so\n// we do not have to hard-code the full module path (which contains the\n// contract address).\n\ninterface AptosTxnWithEvents {\n events?: Array<{ type: string; data: Record<string, unknown> }>\n}\n\nexport const extractEventData = <T = Record<string, unknown>>(\n txn: AptosTxnWithEvents,\n eventSuffix: string,\n): T | undefined => {\n const event = txn?.events?.find((e) => e.type.includes(eventSuffix))\n return event?.data as T | undefined\n}\n\n/**\n * `bond::DepositEvent` — emitted by the deposit entry function.\n * Contains bill_id, bill_address, deposit_amount, payout_amount, price.\n */\nexport const extractDepositEvent = (\n txn: AptosTxnWithEvents,\n):\n | {\n bill_id: string\n bill_address: string\n market: string\n deposit_amount: string\n payout_amount: string\n price: string\n depositor: string\n recipient: string\n }\n | undefined => extractEventData(txn, '::DepositEvent')\n\n/**\n * Extract bill_id from transaction events. Checks both `BillMinted` (from bond_nft)\n * and `DepositEvent` (from bond) since the contract emits both.\n */\nexport const extractBillMinted = (txn: AptosTxnWithEvents): { bill_id: string; owner: string } | undefined => {\n // Try BillMinted event first (emitted by bond_nft module)\n const billMinted = extractEventData<{ bill_id: string; owner: string }>(txn, '::BillMinted')\n if (billMinted) return billMinted\n // Fall back to DepositEvent (emitted by bond module)\n const deposit = extractDepositEvent(txn)\n if (!deposit) return undefined\n return { bill_id: deposit.bill_id, owner: deposit.depositor }\n}\n\n// ---------------------------------------------------------------------------\n// Fetch helper — GraphQL to the Aptos indexer\n// ---------------------------------------------------------------------------\n// Uses the same API key that is configured on the Aptos client. Everything\n// else on the HTTP layer goes through the Aptos ts-sdk, but the indexer\n// needs a raw `fetch` call because GraphQL is not part of the SDK surface.\nexport const aptosIndexerFetch = async <T = unknown>(\n url: string,\n query: string,\n variables?: Record<string, unknown>,\n): Promise<T> => {\n const apiKey = getRandomAptosApiKey()\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && { Authorization: `Bearer ${apiKey}` }),\n },\n body: JSON.stringify({ query, variables }),\n })\n if (!response.ok) {\n throw new Error(`Aptos indexer request failed: ${response.status}`)\n }\n const json = (await response.json()) as { data: T; errors?: Array<{ message: string }> }\n if (json.errors?.length) {\n throw new Error(`Aptos indexer returned errors: ${json.errors.map((e) => e.message).join(', ')}`)\n }\n return json.data\n}\n\n// ---------------------------------------------------------------------------\n// View function readers (PLAN_001 Etapa 5b — real read skeleton)\n// ---------------------------------------------------------------------------\n// Thin wrappers around `aptos.view(...)` for the specific view functions the\n// SDK needs. Every reader throws on RPC / contract error — callers should\n// wrap in try/catch so a missing deployment degrades gracefully rather than\n// crashing the UI.\n//\n// Shapes are verified against apebond-move-playground pages. See the matching\n// `AptosMarketInfoTuple` / `AptosBillInfo` / `AptosVestingProgressTuple`\n// types for documentation on each field.\n\n/**\n * `bond::market_info(market)` — returns the 27-element market info tuple.\n */\nexport const readAptosMarketInfo = async (marketAddress: string): Promise<AptosMarketInfoTuple> => {\n const aptos = getAptosClient()\n const result = await aptos.view({\n payload: {\n function: APTOS_VIEW_MARKET_INFO,\n functionArguments: [marketAddress],\n },\n })\n return result as unknown as AptosMarketInfoTuple\n}\n\n/**\n * `bond::bill_info(market, bill_id)` — returns the Bill struct for a\n * specific bill. The contract takes `bill_id: u64` (NOT the object address).\n * Uses REST directly to avoid SDK remoteAbi serialisation bug with u64 args.\n */\nexport const readAptosBillInfo = async (marketAddress: string, billId: string): Promise<AptosBillInfo> => {\n const result = await viewViaRest(APTOS_VIEW_BILL_INFO, [marketAddress, billId])\n return result[0] as unknown as AptosBillInfo\n}\n\n/**\n * `bond_nft::user_bills(user)` — returns all bill_ids owned by the user\n * across every deployed market. The view returns `[bill_ids]` (the inner\n * array is at index 0), so we unwrap it here.\n */\nexport const readUserBillIds = async (user: string): Promise<string[]> => {\n const aptos = getAptosClient()\n const result = await aptos.view({\n payload: {\n function: APTOS_VIEW_USER_BILLS,\n functionArguments: [user],\n },\n })\n const ids = (result[0] ?? []) as unknown as Array<string | number>\n return ids.map((id) => String(id))\n}\n\n/**\n * `bond::vesting_progress(market, bill_id)` — returns `[vested_amount, claimable_amount]`.\n * Note: this is in `bond` module (not `bond_nft`), and takes the market as first argument.\n * Uses REST directly to avoid SDK remoteAbi serialisation bug with u64 args.\n */\nexport const readVestingProgress = async (\n marketAddress: string,\n billId: string,\n): Promise<AptosVestingProgressTuple> => {\n const result = await viewViaRest(APTOS_VIEW_VESTING_PROGRESS, [marketAddress, billId])\n return [String(result[0] ?? '0'), String(result[1] ?? '0')] as const\n}\n\n// ---------------------------------------------------------------------------\n// REST-based view call — bypasses the SDK's remoteAbi serialisation which\n// has a bug in v6.x where u64 arguments to functions returning `address` get\n// mis-serialised. The REST endpoint handles string arguments natively.\n// ---------------------------------------------------------------------------\nconst viewViaRest = async (fn: string, args: string[], typeArgs: string[] = []): Promise<unknown[]> => {\n const apiKey = getRandomAptosApiKey()\n const res = await fetch(`${APTOS_FULLNODE_URL}/view`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey && { Authorization: `Bearer ${apiKey}` }),\n },\n body: JSON.stringify({\n function: fn,\n type_arguments: typeArgs,\n arguments: args,\n }),\n })\n if (!res.ok) {\n const text = await res.text()\n throw new Error(`View call ${fn} failed: ${res.status} ${text}`)\n }\n return (await res.json()) as unknown[]\n}\n\n/**\n * `bond_nft::bond_market_by_id(bill_id)` — which market owns this bill.\n * Uses REST directly — SDK's aptos.view() mis-serialises u64→address functions.\n */\nexport const readBondMarketByBillId = async (billId: string): Promise<string> => {\n const result = await viewViaRest(APTOS_VIEW_BOND_MARKET_BY_ID, [billId])\n return String(result[0] ?? '')\n}\n\n/**\n * `bond_nft::nft_address(bill_id)` — resolve the scalar bill_id to the\n * on-chain NFT object address (aka `bill_addr`). Needed to then call\n * `bond::bill_info(market, bill_addr)` or `bond::claim(market, bill_addr)`.\n * Uses REST directly — SDK's aptos.view() mis-serialises u64→address functions.\n */\nexport const readNftAddressByBillId = async (billId: string): Promise<string> => {\n const result = await viewViaRest(APTOS_VIEW_NFT_ADDRESS, [billId])\n return String(result[0] ?? '')\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -43,7 +43,7 @@ const Bonds = () => {
|
|
|
43
43
|
if (filterOption === 'SOLD OUT') {
|
|
44
44
|
if (!allBonds || !allPreBonds)
|
|
45
45
|
return {};
|
|
46
|
-
bondsToUse = [...allPreBonds, ...allBonds];
|
|
46
|
+
bondsToUse = [...allPreBonds, ...Object.values(allBonds).flat()];
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
49
|
bondsToUse = sortBonds(sortConfig, bondData);
|