@ape.swap/bonds-sdk 7.0.2 → 7.0.4-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.
Files changed (145) hide show
  1. package/dist/adapters/evm/index.d.ts +3 -2
  2. package/dist/adapters/evm/index.js +11 -2
  3. package/dist/adapters/evm/index.js.map +1 -1
  4. package/dist/adapters/evm/state/balances.js +1 -1
  5. package/dist/adapters/evm/state/balances.js.map +1 -1
  6. package/dist/adapters/evm/state/fetchBondsDataEVM.js +65 -2
  7. package/dist/adapters/evm/state/fetchBondsDataEVM.js.map +1 -1
  8. package/dist/adapters/evm/state/fetchUsersBondsEVM.js +234 -2
  9. package/dist/adapters/evm/state/fetchUsersBondsEVM.js.map +1 -1
  10. package/dist/adapters/evm/state/lpStaking/fetchLpStakingLimits.d.ts +24 -0
  11. package/dist/adapters/evm/state/lpStaking/fetchLpStakingLimits.js +118 -0
  12. package/dist/adapters/evm/state/lpStaking/fetchLpStakingLimits.js.map +1 -0
  13. package/dist/adapters/evm/state/lpStaking/useSoulZapLpStakingQuote.d.ts +4 -0
  14. package/dist/adapters/evm/state/lpStaking/useSoulZapLpStakingQuote.js +140 -0
  15. package/dist/adapters/evm/state/lpStaking/useSoulZapLpStakingQuote.js.map +1 -0
  16. package/dist/adapters/evm/state/useSoulZapBondQuote.js +1 -1
  17. package/dist/adapters/evm/views/BuyComponent.js +1 -1
  18. package/dist/adapters/evm/views/BuyComponent.js.map +1 -1
  19. package/dist/adapters/evm/views/lpStaking/BuyComponentLpStaking.d.ts +4 -0
  20. package/dist/adapters/evm/views/lpStaking/BuyComponentLpStaking.js +212 -0
  21. package/dist/adapters/evm/views/lpStaking/BuyComponentLpStaking.js.map +1 -0
  22. package/dist/adapters/evm/views/lpStaking/LpBondModalHeader.d.ts +7 -0
  23. package/dist/adapters/evm/views/lpStaking/LpBondModalHeader.js +66 -0
  24. package/dist/adapters/evm/views/lpStaking/LpBondModalHeader.js.map +1 -0
  25. package/dist/adapters/evm/views/lpStaking/LpStakingEstimations.d.ts +23 -0
  26. package/dist/adapters/evm/views/lpStaking/LpStakingEstimations.js +40 -0
  27. package/dist/adapters/evm/views/lpStaking/LpStakingEstimations.js.map +1 -0
  28. package/dist/adapters/evm/views/lpStaking/ModalHandlerLpStaking.d.ts +3 -0
  29. package/dist/adapters/evm/views/lpStaking/ModalHandlerLpStaking.js +90 -0
  30. package/dist/adapters/evm/views/lpStaking/ModalHandlerLpStaking.js.map +1 -0
  31. package/dist/adapters/evm/views/lpStaking/UserLpStakingBondRow.d.ts +5 -0
  32. package/dist/adapters/evm/views/lpStaking/UserLpStakingBondRow.js +32 -0
  33. package/dist/adapters/evm/views/lpStaking/UserLpStakingBondRow.js.map +1 -0
  34. package/dist/adapters/evm/views/lpStaking/YourLpBondModalHeader.d.ts +7 -0
  35. package/dist/adapters/evm/views/lpStaking/YourLpBondModalHeader.js +20 -0
  36. package/dist/adapters/evm/views/lpStaking/YourLpBondModalHeader.js.map +1 -0
  37. package/dist/adapters/evm/views/lpStaking/YourLpStakingBondModal.d.ts +7 -0
  38. package/dist/adapters/evm/views/lpStaking/YourLpStakingBondModal.js +78 -0
  39. package/dist/adapters/evm/views/lpStaking/YourLpStakingBondModal.js.map +1 -0
  40. package/dist/adapters/solana/index.js +1 -1
  41. package/dist/adapters/solana/index.js.map +1 -1
  42. package/dist/adapters/solana/state/fetchUsersBondsSOL.d.ts +5 -1
  43. package/dist/adapters/solana/state/fetchUsersBondsSOL.js +152 -154
  44. package/dist/adapters/solana/state/fetchUsersBondsSOL.js.map +1 -1
  45. package/dist/adapters/solana/state/fetchUsersBondsSOLMulticall.d.ts +12 -0
  46. package/dist/adapters/solana/state/fetchUsersBondsSOLMulticall.js +162 -0
  47. package/dist/adapters/solana/state/fetchUsersBondsSOLMulticall.js.map +1 -0
  48. package/dist/adapters/solana/utils/calculatePendingRewards.d.ts +2 -0
  49. package/dist/adapters/solana/utils/calculatePendingRewards.js +53 -0
  50. package/dist/adapters/solana/utils/calculatePendingRewards.js.map +1 -0
  51. package/dist/adapters/solana/utils/fetchUserAssetsSOL.d.ts +3 -0
  52. package/dist/adapters/solana/utils/fetchUserAssetsSOL.js +49 -0
  53. package/dist/adapters/solana/utils/fetchUserAssetsSOL.js.map +1 -0
  54. package/dist/adapters/solana/utils/getSolanaAccount.d.ts +5 -0
  55. package/dist/adapters/solana/utils/getSolanaAccount.js +26 -23
  56. package/dist/adapters/solana/utils/getSolanaAccount.js.map +1 -1
  57. package/dist/adapters/solana/utils/solanaMulticall.js +4 -2
  58. package/dist/adapters/solana/utils/solanaMulticall.js.map +1 -1
  59. package/dist/adapters/types.d.ts +21 -6
  60. package/dist/components/TokenInfoAndName/index.js +4 -1
  61. package/dist/components/TokenInfoAndName/index.js.map +1 -1
  62. package/dist/components/Tooltip/ButtonsRow.js +1 -1
  63. package/dist/components/Tooltip/ButtonsRow.js.map +1 -1
  64. package/dist/components/Tooltip/Tooltip.js +3 -2
  65. package/dist/components/Tooltip/Tooltip.js.map +1 -1
  66. package/dist/components/uikit-sdk/TokenImage/index.js +3 -1
  67. package/dist/components/uikit-sdk/TokenImage/index.js.map +1 -1
  68. package/dist/config/abi/apeBondPositionAdapter.json.js +1347 -0
  69. package/dist/config/abi/apeBondPositionAdapter.json.js.map +1 -0
  70. package/dist/config/abi/bonusEscrow.json.js +33 -0
  71. package/dist/config/abi/bonusEscrow.json.js.map +1 -0
  72. package/dist/config/abi/lpStakingVault.json.js +34 -0
  73. package/dist/config/abi/lpStakingVault.json.js.map +1 -0
  74. package/dist/config/abi/uniswapV3Pool.json.js +47 -0
  75. package/dist/config/abi/uniswapV3Pool.json.js.map +1 -0
  76. package/dist/config/abi/uniswapV3QuoterV2.json.js +66 -0
  77. package/dist/config/abi/uniswapV3QuoterV2.json.js.map +1 -0
  78. package/dist/config/constants/addresses.d.ts +1 -0
  79. package/dist/config/constants/addresses.js +7 -1
  80. package/dist/config/constants/addresses.js.map +1 -1
  81. package/dist/config/constants/chains.js +3 -1
  82. package/dist/config/constants/chains.js.map +1 -1
  83. package/dist/config/constants/networks.d.ts +1 -1
  84. package/dist/config/constants/networks.js +10 -8
  85. package/dist/config/constants/networks.js.map +1 -1
  86. package/dist/config/constants/variables.d.ts +2 -2
  87. package/dist/config/constants/variables.js +3 -1
  88. package/dist/config/constants/variables.js.map +1 -1
  89. package/dist/state/bonds/useBondsData.js +1 -0
  90. package/dist/state/bonds/useBondsData.js.map +1 -1
  91. package/dist/state/bonds/useUserBonds.d.ts +10 -1
  92. package/dist/state/bonds/useUserBonds.js +19 -12
  93. package/dist/state/bonds/useUserBonds.js.map +1 -1
  94. package/dist/state/useSDKConfig.js +2 -2
  95. package/dist/state/useSDKConfig.js.map +1 -1
  96. package/dist/state/zap/getChainParam.d.ts +1 -16
  97. package/dist/state/zap/getChainParam.js +16 -40
  98. package/dist/state/zap/getChainParam.js.map +1 -1
  99. package/dist/styles.css +1 -1
  100. package/dist/types/yourbonds.d.ts +24 -0
  101. package/dist/views/Bonds/components/BondRows/ActiveBondRows.js +19 -2
  102. package/dist/views/Bonds/components/BondRows/ActiveBondRows.js.map +1 -1
  103. package/dist/views/Bonds/components/BondRows/BondRow.d.ts +3 -2
  104. package/dist/views/Bonds/components/BondRows/BondRow.js +15 -10
  105. package/dist/views/Bonds/components/BondRows/BondRow.js.map +1 -1
  106. package/dist/views/Bonds/components/BondRows/ModalHandler.js +1 -1
  107. package/dist/views/Bonds/components/BondRows/ModalHandler.js.map +1 -1
  108. package/dist/views/Bonds/components/BondRows/SoldOutRows.js +1 -1
  109. package/dist/views/Bonds/components/BondRows/SoldOutRows.js.map +1 -1
  110. package/dist/views/Bonds/components/BondsMenu/BondsMenu.js +1 -1
  111. package/dist/views/Bonds/components/BondsMenu/BondsMenu.js.map +1 -1
  112. package/dist/views/Bonds/components/BonusComponents/BonusComponent.js +1 -1
  113. package/dist/views/Bonds/components/BonusComponents/BonusComponent.js.map +1 -1
  114. package/dist/views/Bonds/components/BuyAgainRow/index.js +1 -1
  115. package/dist/views/Bonds/components/BuyAgainRow/index.js.map +1 -1
  116. package/dist/views/Bonds/components/CheckURL/index.js +20 -15
  117. package/dist/views/Bonds/components/CheckURL/index.js.map +1 -1
  118. package/dist/views/BuyBond/ChainBuyComponent.d.ts +4 -1
  119. package/dist/views/BuyBond/ChainBuyComponent.js +14 -2
  120. package/dist/views/BuyBond/ChainBuyComponent.js.map +1 -1
  121. package/dist/views/BuyBond/components/BondCards/BondCards.js +1 -7
  122. package/dist/views/BuyBond/components/BondCards/BondCards.js.map +1 -1
  123. package/dist/views/BuyBond/components/BondModalHeader.d.ts +1 -2
  124. package/dist/views/BuyBond/components/BondModalHeader.js +13 -5
  125. package/dist/views/BuyBond/components/BondModalHeader.js.map +1 -1
  126. package/dist/views/BuyBond/components/Estimations.js +1 -1
  127. package/dist/views/BuyBond/components/Estimations.js.map +1 -1
  128. package/dist/views/BuyBond/components/ExpandedViewButton.d.ts +2 -2
  129. package/dist/views/BuyBond/components/ExpandedViewButton.js +2 -2
  130. package/dist/views/BuyBond/components/ExpandedViewButton.js.map +1 -1
  131. package/dist/views/FullBondsView/FullBondsView.js +2 -1
  132. package/dist/views/FullBondsView/FullBondsView.js.map +1 -1
  133. package/dist/views/FullBondsView/YourBondsStatus.d.ts +3 -0
  134. package/dist/views/FullBondsView/YourBondsStatus.js +54 -0
  135. package/dist/views/FullBondsView/YourBondsStatus.js.map +1 -0
  136. package/dist/views/SingleBond/SoldOutBuyBondPlaceholder.js +2 -5
  137. package/dist/views/SingleBond/SoldOutBuyBondPlaceholder.js.map +1 -1
  138. package/dist/views/YourBonds/YourBonds.js +6 -1
  139. package/dist/views/YourBonds/YourBonds.js.map +1 -1
  140. package/dist/views/YourBonds/components/YourBondsMenu/YourBondsMenu.js +2 -1
  141. package/dist/views/YourBonds/components/YourBondsMenu/YourBondsMenu.js.map +1 -1
  142. package/dist/views/YourBondsModal/components/YourBondModalHeader/YourBondModalHeader.d.ts +2 -1
  143. package/dist/views/YourBondsModal/components/YourBondModalHeader/YourBondModalHeader.js +2 -2
  144. package/dist/views/YourBondsModal/components/YourBondModalHeader/YourBondModalHeader.js.map +1 -1
  145. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"fetchUsersBondsEVM.js","sources":["../../../../src/adapters/evm/state/fetchUsersBondsEVM.ts"],"sourcesContent":["import billAbi from '../../../config/abi/BOND_2_0_0.json'\nimport multicall from '../utils/multicall'\nimport { UserBill, UserOwnedBillsData } from '../../../types/yourbonds'\nimport { BillsConfig, BillVersion, ChainId } from '@ape.swap/apeswap-lists'\nimport { TokenPrices } from '../../../state/tokenPrices/useTokenPrices'\nimport { BondsData } from '../../../types/bonds'\nimport { apiGet } from '../../../utils/httpClient'\nimport { PRICE_API_URL } from '../../../config/constants/variables'\n\nexport const fetchUsersBondsEVM = async (\n chainId: ChainId,\n account: string,\n bondData: BillsConfig[],\n tokenPrices: Partial<Record<ChainId, TokenPrices[]>>,\n): Promise<UserOwnedBillsData[]> => {\n try {\n if (!account) {\n return []\n }\n const bonds: BillsConfig[] = bondData\n\n // Fetch and set user owned bill data without NFT Data\n const userOwnedBills = await fetchUserOwnedBills(chainId, account, bonds, tokenPrices)\n const mapUserOwnedBills = bonds.map((bill: BillsConfig) =>\n userOwnedBills.filter((b) => b.address.toLowerCase() === bill.contractAddress[bill.chainId]?.toLowerCase()),\n )\n const userOwnedBillsData = bonds.map((bill: BillsConfig, i: number) => ({\n index: bill.index,\n userOwnedBills: mapUserOwnedBills[i],\n }))\n\n const combinedData = userOwnedBillsData.map((data) => {\n const enrichedUserBills = data.userOwnedBills.map((bill) => {\n return {\n ...bill,\n }\n })\n return {\n ...data,\n userOwnedBills: enrichedUserBills,\n }\n })\n\n return Promise.resolve(combinedData)\n } catch (error) {\n console.error('Error fetching user owned bills data:', error)\n return Promise.reject(error)\n }\n}\n\nconst fetchUserOwnedBills = async (\n chainId: ChainId,\n account: string,\n bonds: BillsConfig[],\n tokenPrices: Partial<Record<ChainId, TokenPrices[]>>,\n): Promise<UserBill[]> => {\n // Maps all the bills in the list repo to make a call to each of them to get Bills Id and paused state (only for V4)\n const billIdAndPausedCalls = bonds.flatMap((b, index) => {\n const calls = [\n {\n address: b.contractAddress[b.chainId] ?? '',\n name: 'getBillIds',\n params: [account],\n bondIndex: index,\n },\n ]\n // Only add paused call for V4 bonds\n if (b.billVersion === BillVersion.V4) {\n calls.push({\n address: b.contractAddress[b.chainId] ?? '',\n name: 'paused',\n params: [],\n bondIndex: index,\n })\n }\n return calls\n })\n const billIdAndPausedResults = await multicall(chainId, billAbi, billIdAndPausedCalls, true, 15)\n\n // Separate billIds and pausedStates from results, tracking which bonds have paused calls\n const billIds: any[] = []\n const pausedStates: Map<string, boolean> = new Map()\n let resultIndex = 0\n\n bonds.forEach((b) => {\n // First result is always getBillIds\n billIds.push(billIdAndPausedResults?.[resultIndex])\n resultIndex++\n\n // Next result is paused only if V4\n if (b.billVersion === BillVersion.V4) {\n pausedStates.set(\n b.contractAddress[b.chainId]?.toLowerCase() as string,\n billIdAndPausedResults?.[resultIndex]?.[0] ?? false,\n )\n resultIndex++\n }\n })\n const billDataCalls: any = []\n const billVersions: any = []\n\n billIds?.forEach((idArray: any, index: number) =>\n idArray[0].forEach((id: bigint) => {\n if (id > 0) {\n billDataCalls.push({\n address: bonds[index].contractAddress[bonds[index].chainId],\n name: bonds[index].billVersion !== BillVersion.V1 ? 'getBillInfo' : 'billInfo',\n params: [id],\n bond: bonds[index],\n })\n billDataCalls.push({\n address: bonds[index].contractAddress[bonds[index].chainId],\n name: bonds[index].billVersion !== BillVersion.V1 ? 'claimablePayout' : 'pendingPayoutFor',\n params: [id],\n bond: bonds[index],\n })\n billVersions.push(bonds[index].billVersion)\n }\n }),\n )\n const billData = await multicall(chainId, billAbi, billDataCalls, true, 150)\n const result = []\n\n for (let i = 0; i < billVersions.length; i++) {\n const billPos = i === 0 ? 0 : i * 2\n let bond: BondsData = billDataCalls[billPos].bond\n\n let principalTokenPrice = tokenPrices?.[bond.chainId]?.find(\n (tokenPrice) => tokenPrice.tokenAddress?.toLowerCase() === bond?.lpToken?.address?.[bond.chainId]?.toLowerCase(),\n )?.price\n\n let payoutTokenPrice = tokenPrices?.[bond.chainId]?.find(\n (tokenPrice: TokenPrices) =>\n tokenPrice?.tokenAddress?.toLowerCase() === bond?.earnToken?.address?.[bond.chainId]?.toLowerCase(),\n )?.price\n\n if (principalTokenPrice === undefined) {\n try {\n const res = await apiGet<{ price: string }>(\n `${PRICE_API_URL}/realtime/price?token=${bond?.lpToken?.address?.[bond?.chainId]}&chain=${bond?.chainId}`,\n )\n console.log('Individual call for: ', bond.lpToken.symbol, '. Price: ', res.price)\n principalTokenPrice = parseFloat(res.price ?? '0')\n } catch {\n principalTokenPrice = 0\n }\n }\n if (payoutTokenPrice === undefined) {\n try {\n const res = await apiGet<{ price: string }>(\n `${PRICE_API_URL}/realtime/price?token=${bond?.earnToken?.address?.[bond?.chainId]}&chain=${bond?.chainId}`,\n )\n console.log('Individual call for: ', bond.earnToken.symbol, '. Price: ', res.price)\n payoutTokenPrice = parseFloat(res.price ?? '0')\n } catch {\n payoutTokenPrice = 0\n }\n }\n\n bond = {\n ...bond,\n payoutTokenPrice: payoutTokenPrice?.toString(),\n principalTokenPrice: principalTokenPrice?.toString(),\n }\n const paused = pausedStates.get(bond.contractAddress[bond.chainId]?.toLowerCase() as string) ?? false\n\n const data =\n billVersions[i] !== BillVersion.V1\n ? {\n address: billDataCalls[billPos].address,\n id: billDataCalls[billPos].params[0].toString(),\n payout: (\n BigInt(billData[billPos][0]?.payout.toString()) - BigInt(billData[billPos][0]?.payoutClaimed.toString())\n ).toString(),\n totalPayout: billData[billPos][0]?.payout.toString(),\n payoutClaimed: billData[billPos][0]?.payoutClaimed.toString(),\n billNftAddress: bond.billNnftAddress[bond.chainId] ?? '',\n vesting: billData[billPos][0]?.vesting.toString(),\n vestingTerm: billData[billPos][0]?.vestingTerm.toString(),\n lastBlockTimestamp: billData[billPos][0]?.lastClaimTimestamp.toString(),\n vestingStartTimestamp: billData[billPos][0]?.vestingStartTimestamp.toString(),\n truePricePaid: billData[billPos][0]?.truePricePaid.toString(),\n pendingRewards: billData[billPos + 1][0].toString(),\n paused,\n bond,\n }\n : {\n address: billDataCalls[billPos].address,\n id: billDataCalls[billPos].params[0].toString(),\n payoutClaimed: billData?.[billPos]?.[0]?.payoutClaimed?.toString(),\n payout: billData[billPos][0].toString(),\n billNftAddress: bond.billNnftAddress[bond.chainId] ?? '',\n vesting: billData[billPos][1].toString(),\n lastBlockTimestamp: billData[billPos][2].toString(),\n truePricePaid: billData[billPos][3].toString(),\n pendingRewards: billData[billPos + 1][0].toString(),\n paused,\n bond,\n }\n result.push(data)\n }\n\n return result\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetchUsersBondsEVM.js","sources":["../../../../src/adapters/evm/state/fetchUsersBondsEVM.ts"],"sourcesContent":["import billAbi from '../../../config/abi/BOND_2_0_0.json'\nimport multicall from '../utils/multicall'\nimport { UserBill, UserOwnedBillsData } from '../../../types/yourbonds'\nimport { BillsConfig, BillVersion, ChainId } from '@ape.swap/apeswap-lists'\nimport { TokenPrices } from '../../../state/tokenPrices/useTokenPrices'\nimport { BondsData } from '../../../types/bonds'\nimport { apiGet } from '../../../utils/httpClient'\nimport { PRICE_API_URL } from '../../../config/constants/variables'\nimport partition from 'lodash-es/partition.js'\nimport APE_BOND_POSITION_ADAPTER_ABI from '../../../config/abi/apeBondPositionAdapter.json'\nexport const fetchUsersBondsEVM = async (\n chainId: ChainId,\n account: string,\n bondData: BillsConfig[],\n tokenPrices: Partial<Record<ChainId, TokenPrices[]>>,\n): Promise<UserOwnedBillsData[]> => {\n try {\n if (!account) {\n return []\n }\n const [lpStakingBonds, bonds] = partition(bondData, (bond) => bond.billType === 'lpStaking')\n\n // Fetch and set user owned bill data without NFT Data\n const userOwnedBills = await fetchUserOwnedBills(chainId, account, bonds, tokenPrices)\n const mapUserOwnedBills = bonds.map((bill: BillsConfig) =>\n userOwnedBills.filter((b) => b.address.toLowerCase() === bill.contractAddress[bill.chainId]?.toLowerCase()),\n )\n const userOwnedBillsData = bonds.map((bill: BillsConfig, i: number) => ({\n index: bill.index,\n userOwnedBills: mapUserOwnedBills[i],\n }))\n\n const combinedData = userOwnedBillsData.map((data) => {\n const enrichedUserBills = data.userOwnedBills.map((bill) => {\n return {\n ...bill,\n }\n })\n return {\n ...data,\n userOwnedBills: enrichedUserBills,\n }\n })\n\n const lpStakingData =\n lpStakingBonds.length > 0 ? await fetchUserLpStakingBonds(chainId, account, lpStakingBonds) : []\n\n return Promise.resolve([...combinedData, ...lpStakingData])\n } catch (error) {\n console.error('Error fetching user owned bills data:', error)\n return Promise.reject(error)\n }\n}\n\n// REAL's API only answers browsers from origins it allowlists, so it's called through ape.bond's proxy, which\n// forwards to REAL's API (test stack or mainnet, set on ape.bond's side).\n// TODO: staging proxy for now; switch to the production one (https://ape.bond/api/real-lp) once it's deployed.\nconst REAL_LP_API = 'https://staging.ape.bond/api/real-lp'\n// A position's page on REAL's site, where its bonus and pool rewards are claimed.\n// TODO: test site for now; REAL will send the production URL when mainnet is live.\nconst REAL_LP_DASHBOARD = 'https://staking-test.real.finance/lp/dashboard'\n\n// REAL's /rewards/<wallet>: the pool (epoch) rewards, lifetime figures. Only the fields used below are typed.\ninterface RealLpRewards {\n tokens: { token: string; symbol: string; decimals: number; claims_enabled: boolean }[]\n positions: { lineage_id: string; tokens: { token: string; claimable_wei: string }[] }[]\n}\n\n// One row of REAL's /positions/<wallet>: one episode of a position, i.e. one NFT while it sits in the vault.\n// Only the fields used below are typed.\ninterface RealLpPosition {\n token_id: string\n lineage_id: string\n next_episode_id: string | null\n stake_ordinal: number\n status: 'active' | 'rebalanced' | 'unstaked'\n tick_lower: number\n tick_upper: number\n liquidity_wei: string\n principal_usd: string\n value_usd_now: string | null\n apebond: {\n campaign_id: string\n deposited_at: number\n bonus: {\n token: string\n amount_wei: string\n unlock_at: number\n status: 'reserved' | 'claimable' | 'claimed' | 'forfeited'\n claimed_at: number | null\n token_id: string\n } | null\n } | null\n}\n\n/**\n * Raw token amounts (wei) a Uniswap v3 position holds at the pool's current tick: all token0 below its range, all\n * token1 above it, both inside. Floating point: it's for display only.\n */\nconst getPositionAmounts = (liquidity: number, tickLower: number, tickUpper: number, currentTick: number) => {\n const sqrtPrice = (tick: number) => Math.pow(1.0001, tick / 2)\n const sqrtLower = sqrtPrice(tickLower)\n const sqrtUpper = sqrtPrice(tickUpper)\n const sqrtCurrent = sqrtPrice(Math.min(Math.max(currentTick, tickLower), tickUpper))\n return {\n amount0: (liquidity * (sqrtUpper - sqrtCurrent)) / (sqrtCurrent * sqrtUpper),\n amount1: liquidity * (sqrtCurrent - sqrtLower),\n }\n}\n\n/**\n * The user's LP staking positions, shaped as purchased bonds. A position has no bill: it's a Uniswap v3 NFT staked\n * in REAL's vault, and what ApeBond pays is its bonus, reserved in REAL's escrow until the cliff. So each position\n * becomes one bill whose payout is that bonus, vesting all at once at the cliff (`vestingCliff` = `vestingTerm`).\n * Claims happen on REAL's site, so the bills are marked paused (the row's claim button would call `redeem` on the\n * vault). See docs/lp-staking-bonds/2026-10-23-real-lp-positions-rewards-api.md.\n */\nconst fetchUserLpStakingBonds = async (\n chainId: ChainId,\n account: string,\n lpStakingBonds: BillsConfig[],\n): Promise<UserOwnedBillsData[]> => {\n let rows: RealLpPosition[]\n let assetPriceUsd: string | undefined\n let assetIsToken0 = true\n let currentTick = 0\n let rewards: RealLpRewards | undefined\n try {\n const [response, rewardsResponse] = await Promise.all([\n apiGet<{\n current_tick: number\n current_price_usd: string\n asset_is_token0: boolean\n positions: RealLpPosition[]\n }>(`${REAL_LP_API}/positions/${account}`),\n // The positions still show without their pool rewards if this fails\n apiGet<RealLpRewards>(`${REAL_LP_API}/rewards/${account}`).catch((error) => {\n console.error('Error fetching LP staking rewards:', error)\n return undefined\n }),\n ])\n rewards = rewardsResponse\n rows = response?.positions ?? []\n assetPriceUsd = response?.current_price_usd\n assetIsToken0 = response?.asset_is_token0 ?? true\n currentTick = response?.current_tick ?? 0\n } catch (error) {\n // Don't fail the chain's regular bonds because REAL's API is unreachable (or refuses our origin)\n console.error('Error fetching LP staking positions:', error)\n return []\n }\n\n // All episodes of a position share its lineage_id; the one with no next episode is its current state.\n // Only positions bought through ApeBond have an apebond block.\n const currentPositions = rows.filter((row) => row.apebond && row.next_episode_id === null)\n\n // Each campaign's bonus rate and minimum bonus, for the minimum position value that earns a bonus.\n // campaigns() → (enabled, downTicks, upTicks, toleranceTicks, bonusCliffSeconds, bonusBps, minBonusAmount)\n const campaigns = await multicall(\n chainId,\n APE_BOND_POSITION_ADAPTER_ABI,\n lpStakingBonds.map((bond) => ({\n address: bond.lpStakingConfig!.adapter,\n name: 'campaigns',\n params: [bond.lpStakingConfig!.campaignId],\n })),\n )\n\n return lpStakingBonds.map((bond, bondIndex) => {\n const lpStakingConfig = bond.lpStakingConfig!\n const campaign = campaigns?.[bondIndex]\n const bonusDecimals = lpStakingConfig.bonusRewardToken.decimals[bond.chainId] ?? 18\n const bonusThreshold =\n campaign && Number(campaign[5]) > 0\n ? (Number(campaign[6]) / 10 ** bonusDecimals) * (10000 / Number(campaign[5]))\n : undefined\n const userOwnedBills: UserBill[] = currentPositions\n .filter((row) => row.apebond!.campaign_id.toLowerCase() === lpStakingConfig.campaignId.toLowerCase())\n .map((row) => {\n const { deposited_at: depositedAt, bonus } = row.apebond!\n // No bonus when the purchase was below the campaign minimum; forfeited bonuses have amount 0\n const amount = bonus?.amount_wei ?? '0'\n const cliff = bonus ? bonus.unlock_at - depositedAt : 0\n const chainId = bond.chainId\n const bonusToken = lpStakingConfig.bonusRewardToken\n // The pool is the bonus token ($ASSET) paired with the bond's principal token (USDC)\n const assetToken = {\n address: bonusToken.address[chainId] ?? '',\n symbol: bonusToken.symbol,\n name: bonusToken.symbol,\n decimals: bonusToken.decimals,\n }\n const pairedToken = {\n address: bond.lpToken.address[chainId] ?? '',\n symbol: bond.lpToken.symbol,\n name: bond.lpToken.symbol,\n decimals: bond.lpToken.decimals,\n }\n // Value of the position when it was staked: what the buyer paid, minus the zap fees and the change returned\n const principalUsd = parseFloat(row.principal_usd ?? '0')\n // Value of the position now (null once unstaked: the vault no longer holds it)\n const valueUsdNow = parseFloat(row.value_usd_now ?? '0')\n const assetPrice = parseFloat(assetPriceUsd ?? '0')\n // What the staked position holds now. An unstaked position is back in the wallet, so nothing is staked.\n // current_price_usd is $ASSET's price in USDC, and USDC is counted at $1 (as REAL's value_usd_now does).\n const { amount0, amount1 } =\n row.status === 'unstaked'\n ? { amount0: 0, amount1: 0 }\n : getPositionAmounts(parseFloat(row.liquidity_wei), row.tick_lower, row.tick_upper, currentTick)\n const [token0, token1] = assetIsToken0 ? [assetToken, pairedToken] : [pairedToken, assetToken]\n const toStakedToken = (token: typeof assetToken, rawAmount: number) => {\n const amount = rawAmount / 10 ** (token.decimals[chainId] ?? 18)\n return {\n address: token.address,\n symbol: token.symbol,\n amount,\n amountUsd: amount * (token === assetToken ? assetPrice : 1),\n }\n }\n return {\n // Rows are matched to their bond by contract address; for LP staking that's the vault\n address: bond.contractAddress[bond.chainId] ?? '',\n // The position's current NFT, the one REAL's page link uses. After a rebalance past the cliff the escrow\n // still pays on the NFT id the position had at the cliff (bonus.token_id), which has no field here.\n id: row.token_id,\n // The NFT contract is the position manager. The price range (price_lower_usd / price_upper_usd,\n // range_status_now) has no field.\n // Neither do the position's status (an unstaked position still shows, with its bonus as the API reports\n // it) and `finalized` (false for ~13 min after a purchase).\n billNftAddress: lpStakingConfig.positionManager,\n totalPayout: amount,\n // What's left to receive: everything until it's claimed (or forfeited, where amount is 0)\n payout: bonus?.status === 'claimed' ? '0' : amount,\n pendingRewards: bonus?.status === 'claimable' ? amount : '0',\n payoutClaimed: bonus?.status === 'claimed' ? amount : '0',\n vestingStartTimestamp: depositedAt.toString(),\n vestingTerm: cliff.toString(),\n lastBlockTimestamp: (bonus?.claimed_at ?? depositedAt).toString(),\n // No price per payout token: the bonus is a share of the position's value\n truePricePaid: '0',\n paused: true,\n lpStakingData: {\n token0: toStakedToken(token0, amount0),\n token1: toStakedToken(token1, amount1),\n bonusStatus: bonus?.status ?? null,\n bonusThreshold,\n // The position's page on REAL's site. The ordinal is only appended from 2 on (an NFT staked again by\n // hand after an unstake); older ids of the lineage redirect to the current one.\n positionUrl: `${REAL_LP_DASHBOARD}/${row.token_id}${row.stake_ordinal >= 2 ? `-${row.stake_ordinal}` : ''}`,\n // Matched by lineage_id, shared by every episode of the position (it survives rebalances)\n poolRewards: rewards\n ? rewards.tokens.map((rewardToken) => {\n const positionToken = rewards!.positions\n .find((position) => position.lineage_id === row.lineage_id)\n ?.tokens.find((token) => token.token.toLowerCase() === rewardToken.token.toLowerCase())\n // claimable_wei is what's earned and not claimed yet; $ASSET can't be claimed before\n // claims_enabled (mainnet launch + REAL's timelock)\n const rewardAmount = Number(positionToken?.claimable_wei ?? '0') / 10 ** rewardToken.decimals\n return {\n address: rewardToken.token,\n symbol: rewardToken.symbol,\n amount: rewardAmount,\n // Only $ASSET has a price (current_price_usd); REAL's API doesn't price $OVTR\n amountUsd:\n rewardToken.token.toLowerCase() === assetToken.address.toLowerCase()\n ? rewardAmount * assetPrice\n : undefined,\n claimsEnabled: rewardToken.claims_enabled,\n }\n })\n : undefined,\n },\n // What api-v2 provides for regular bills, here from REAL's API (useUserBonds doesn't send LP staking\n // bills to api-v2)\n nftData: {\n tokenId: parseInt(row.token_id),\n billNftId: parseInt(row.token_id),\n processing: false,\n // The position NFT is a Uniswap v3 position with no bond art\n image: 'https://www.ape.bond/images/bills/hidden-bill.jpg',\n chainId,\n contractAddress: lpStakingConfig.positionManager,\n data: {\n billContract: bond.contractAddress[chainId] ?? '',\n billNftAddress: lpStakingConfig.positionManager,\n billNftId: parseInt(row.token_id),\n // Not in REAL's API\n blockNumber: 0,\n bondArtCollection: '',\n bondPartner: bond.bondPartner ?? '',\n bondVersion: bond.billVersion ?? '',\n chainId,\n // The purchase opened the position's first episode, whose id is <token_id>-<opening tx hash>\n createTransactionHash: row.lineage_id.split('-')[1] ?? '',\n createdAddressOwner: account,\n createdAt: depositedAt,\n // The amount paid isn't in REAL's API (only in the purchase tx). The principal token is USDC, so the\n // position's USD value at purchase stands in for it.\n deposit: principalUsd,\n dollarValue: principalUsd,\n expires: depositedAt + cliff,\n pairName: assetIsToken0\n ? `${assetToken.symbol}-${pairedToken.symbol}`\n : `${pairedToken.symbol}-${assetToken.symbol}`,\n // The position's current value (used by the share image), in $ASSET (the payout token) so that\n // payout × payoutTokenPrice gives value_usd_now back. The bonus itself is in the bill's payout fields.\n payout: assetPrice > 0 ? valueUsdNow / assetPrice : 0,\n payoutToken: assetToken.address,\n payoutTokenData: {\n address: assetToken.address,\n name: assetToken.name,\n symbol: assetToken.symbol,\n decimals: assetToken.decimals,\n },\n payoutTokenPrice: assetPriceUsd ?? '0',\n principalToken: pairedToken.address,\n token0: assetIsToken0 ? assetToken : pairedToken,\n token1: assetIsToken0 ? pairedToken : assetToken,\n type: bond.billType,\n vestingPeriodSeconds: cliff,\n },\n },\n // The bonus is paid in the bonus token, not the bond's earnToken, and only unlocks at the cliff.\n // The $OVTR and $ASSET staking rewards (REAL's /rewards/<wallet>) have no field.\n bond: {\n ...bond,\n earnToken: lpStakingConfig.bonusRewardToken,\n vestingCliff: cliff,\n vestingTerm: cliff,\n payoutTokenPrice: assetPriceUsd,\n } as BondsData,\n }\n })\n return { index: bond.index, userOwnedBills }\n })\n}\n\nconst fetchUserOwnedBills = async (\n chainId: ChainId,\n account: string,\n bonds: BillsConfig[],\n tokenPrices: Partial<Record<ChainId, TokenPrices[]>>,\n): Promise<UserBill[]> => {\n // Maps all the bills in the list repo to make a call to each of them to get Bills Id and paused state (only for V4)\n const billIdAndPausedCalls = bonds.flatMap((b, index) => {\n const calls = [\n {\n address: b.contractAddress[b.chainId] ?? '',\n name: 'getBillIds',\n params: [account],\n bondIndex: index,\n },\n ]\n // Only add paused call for V4 bonds\n if (b.billVersion === BillVersion.V4) {\n calls.push({\n address: b.contractAddress[b.chainId] ?? '',\n name: 'paused',\n params: [],\n bondIndex: index,\n })\n }\n return calls\n })\n const billIdAndPausedResults = await multicall(chainId, billAbi, billIdAndPausedCalls, true, 15)\n\n // Separate billIds and pausedStates from results, tracking which bonds have paused calls\n const billIds: any[] = []\n const pausedStates: Map<string, boolean> = new Map()\n let resultIndex = 0\n\n bonds.forEach((b) => {\n // First result is always getBillIds\n billIds.push(billIdAndPausedResults?.[resultIndex])\n resultIndex++\n\n // Next result is paused only if V4\n if (b.billVersion === BillVersion.V4) {\n pausedStates.set(\n b.contractAddress[b.chainId]?.toLowerCase() as string,\n billIdAndPausedResults?.[resultIndex]?.[0] ?? false,\n )\n resultIndex++\n }\n })\n const billDataCalls: any = []\n const billVersions: any = []\n\n billIds?.forEach((idArray: any, index: number) =>\n idArray[0].forEach((id: bigint) => {\n if (id > 0) {\n billDataCalls.push({\n address: bonds[index].contractAddress[bonds[index].chainId],\n name: bonds[index].billVersion !== BillVersion.V1 ? 'getBillInfo' : 'billInfo',\n params: [id],\n bond: bonds[index],\n })\n billDataCalls.push({\n address: bonds[index].contractAddress[bonds[index].chainId],\n name: bonds[index].billVersion !== BillVersion.V1 ? 'claimablePayout' : 'pendingPayoutFor',\n params: [id],\n bond: bonds[index],\n })\n billVersions.push(bonds[index].billVersion)\n }\n }),\n )\n const billData = await multicall(chainId, billAbi, billDataCalls, true, 150)\n const result = []\n\n for (let i = 0; i < billVersions.length; i++) {\n const billPos = i === 0 ? 0 : i * 2\n let bond: BondsData = billDataCalls[billPos].bond\n\n let principalTokenPrice = tokenPrices?.[bond.chainId]?.find(\n (tokenPrice) => tokenPrice.tokenAddress?.toLowerCase() === bond?.lpToken?.address?.[bond.chainId]?.toLowerCase(),\n )?.price\n\n let payoutTokenPrice = tokenPrices?.[bond.chainId]?.find(\n (tokenPrice: TokenPrices) =>\n tokenPrice?.tokenAddress?.toLowerCase() === bond?.earnToken?.address?.[bond.chainId]?.toLowerCase(),\n )?.price\n\n if (principalTokenPrice === undefined) {\n try {\n const res = await apiGet<{ price: string }>(\n `${PRICE_API_URL}/realtime/price?token=${bond?.lpToken?.address?.[bond?.chainId]}&chain=${bond?.chainId}`,\n )\n console.log('Individual call for: ', bond.lpToken.symbol, '. Price: ', res.price)\n principalTokenPrice = parseFloat(res.price ?? '0')\n } catch {\n principalTokenPrice = 0\n }\n }\n if (payoutTokenPrice === undefined) {\n try {\n const res = await apiGet<{ price: string }>(\n `${PRICE_API_URL}/realtime/price?token=${bond?.earnToken?.address?.[bond?.chainId]}&chain=${bond?.chainId}`,\n )\n console.log('Individual call for: ', bond.earnToken.symbol, '. Price: ', res.price)\n payoutTokenPrice = parseFloat(res.price ?? '0')\n } catch {\n payoutTokenPrice = 0\n }\n }\n\n bond = {\n ...bond,\n payoutTokenPrice: payoutTokenPrice?.toString(),\n principalTokenPrice: principalTokenPrice?.toString(),\n }\n const paused = pausedStates.get(bond.contractAddress[bond.chainId]?.toLowerCase() as string) ?? false\n\n const data =\n billVersions[i] !== BillVersion.V1\n ? {\n address: billDataCalls[billPos].address,\n id: billDataCalls[billPos].params[0].toString(),\n payout: (\n BigInt(billData[billPos][0]?.payout.toString()) - BigInt(billData[billPos][0]?.payoutClaimed.toString())\n ).toString(),\n totalPayout: billData[billPos][0]?.payout.toString(),\n payoutClaimed: billData[billPos][0]?.payoutClaimed.toString(),\n billNftAddress: bond.billNnftAddress[bond.chainId] ?? '',\n vesting: billData[billPos][0]?.vesting.toString(),\n vestingTerm: billData[billPos][0]?.vestingTerm.toString(),\n lastBlockTimestamp: billData[billPos][0]?.lastClaimTimestamp.toString(),\n vestingStartTimestamp: billData[billPos][0]?.vestingStartTimestamp.toString(),\n truePricePaid: billData[billPos][0]?.truePricePaid.toString(),\n pendingRewards: billData[billPos + 1][0].toString(),\n paused,\n bond,\n }\n : {\n address: billDataCalls[billPos].address,\n id: billDataCalls[billPos].params[0].toString(),\n payoutClaimed: billData?.[billPos]?.[0]?.payoutClaimed?.toString(),\n payout: billData[billPos][0].toString(),\n billNftAddress: bond.billNnftAddress[bond.chainId] ?? '',\n vesting: billData[billPos][1].toString(),\n lastBlockTimestamp: billData[billPos][2].toString(),\n truePricePaid: billData[billPos][3].toString(),\n pendingRewards: billData[billPos + 1][0].toString(),\n paused,\n bond,\n }\n result.push(data)\n }\n\n return result\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { BillsConfig } from '@ape.swap/apeswap-lists';
2
+ export interface LpStakingLimits {
3
+ maxPayout: string;
4
+ maxTotalPayout: string;
5
+ totalPayoutGiven: string;
6
+ tokensRemaining: string;
7
+ }
8
+ /**
9
+ * Translates an LP staking bond's limits into the fields regular bonds read from their contract, all in the pool's
10
+ * stablecoin (`lpToken1`, e.g. USDC), which must also be the bond's earnToken since the UI reads them in its units:
11
+ * - `maxPayout` (per purchase): the largest buy that keeps the pool price within the TWAP guard: the adapter's
12
+ * depositFor reverts (PriceOutsideTwapBounds) when the spot tick is further than the vault's max deviation from its
13
+ * TWAP. `vault.previewTwap()` returns both ticks and the deviation (REAL's operator can change the window and the
14
+ * deviation at any time, so they're read rather than hardcoded). Whatever the buyer pays with, the zap gets the
15
+ * fluctuating token (`lpToken0`) by buying it with the stablecoin in this pool, which is what moves its price. The
16
+ * QuoterV2 returns how much stablecoin that swap can take before the price hits the bound; the zap swaps about
17
+ * half of the purchase, so the purchase can be about twice that. Purchases within the same 5 minutes add up
18
+ * against the TWAP, so it shrinks right after other buys and grows back as the TWAP catches up.
19
+ * - `maxTotalPayout` / `totalPayoutGiven` / `tokensRemaining` (bond total): the escrow's capacity to pay bonuses.
20
+ * Its bonus token balance and reserved bonuses are turned into purchase value (÷ bonus rate) and priced at the TWAP,
21
+ * as the adapter values positions. A soft cap: buys don't revert when the escrow runs short, only claims do.
22
+ * Any read that fails leaves its limits at 0.
23
+ */
24
+ export declare const fetchLpStakingLimits: (chainId: number, bond: BillsConfig, bonusBps: number) => Promise<LpStakingLimits>;
@@ -0,0 +1,118 @@
1
+ import multicall from '../../utils/multicall.js';
2
+ import UNISWAP_V3_POOL_ABI from '../../../../config/abi/uniswapV3Pool.json.js';
3
+ import LP_STAKING_VAULT_ABI from '../../../../config/abi/lpStakingVault.json.js';
4
+ import UNISWAP_V3_QUOTER_V2_ABI from '../../../../config/abi/uniswapV3QuoterV2.json.js';
5
+ import BONUS_ESCROW_ABI from '../../../../config/abi/bonusEscrow.json.js';
6
+ import APE_BOND_POSITION_ADAPTER_ABI from '../../../../config/abi/apeBondPositionAdapter.json.js';
7
+ import erc20ABI from '../../../../config/abi/erc20.json.js';
8
+ import { UNISWAP_V3_QUOTER_V2 } from '../../../../config/constants/addresses.js';
9
+ import { formatUnits } from '../../../../utils/fixedPoint.js';
10
+
11
+ // The zap swaps about half of the purchase to mint the position (Vladimir's figure: 49.2 %)
12
+ const SWAP_SHARE_BPS = 4920n;
13
+ // Margin for the zap's own fees, slippage and price moves between this read and the buy
14
+ const SAFETY_MARGIN_BPS = 9000n;
15
+ const EMPTY_LIMITS = { maxPayout: '0', maxTotalPayout: '0', totalPayoutGiven: '0', tokensRemaining: '0' };
16
+ // Float precision is enough for a swap price limit
17
+ const getSqrtPriceX96AtTick = (tick) => BigInt(Math.floor(Math.sqrt(1.0001 ** tick) * 2 ** 96));
18
+ /**
19
+ * Translates an LP staking bond's limits into the fields regular bonds read from their contract, all in the pool's
20
+ * stablecoin (`lpToken1`, e.g. USDC), which must also be the bond's earnToken since the UI reads them in its units:
21
+ * - `maxPayout` (per purchase): the largest buy that keeps the pool price within the TWAP guard: the adapter's
22
+ * depositFor reverts (PriceOutsideTwapBounds) when the spot tick is further than the vault's max deviation from its
23
+ * TWAP. `vault.previewTwap()` returns both ticks and the deviation (REAL's operator can change the window and the
24
+ * deviation at any time, so they're read rather than hardcoded). Whatever the buyer pays with, the zap gets the
25
+ * fluctuating token (`lpToken0`) by buying it with the stablecoin in this pool, which is what moves its price. The
26
+ * QuoterV2 returns how much stablecoin that swap can take before the price hits the bound; the zap swaps about
27
+ * half of the purchase, so the purchase can be about twice that. Purchases within the same 5 minutes add up
28
+ * against the TWAP, so it shrinks right after other buys and grows back as the TWAP catches up.
29
+ * - `maxTotalPayout` / `totalPayoutGiven` / `tokensRemaining` (bond total): the escrow's capacity to pay bonuses.
30
+ * Its bonus token balance and reserved bonuses are turned into purchase value (÷ bonus rate) and priced at the TWAP,
31
+ * as the adapter values positions. A soft cap: buys don't revert when the escrow runs short, only claims do.
32
+ * Any read that fails leaves its limits at 0.
33
+ */
34
+ const fetchLpStakingLimits = async (chainId, bond, bonusBps) => {
35
+ const { pool, adapter, lpToken1: stablecoin } = bond.lpStakingConfig;
36
+ const tokenIn = stablecoin.address[bond.chainId]?.toLowerCase();
37
+ const tokenInDecimals = stablecoin.decimals[bond.chainId] ?? 18;
38
+ const [poolData, adapterData] = await Promise.all([
39
+ multicall(chainId, UNISWAP_V3_POOL_ABI, [
40
+ { address: pool, name: 'token0' },
41
+ { address: pool, name: 'token1' },
42
+ { address: pool, name: 'fee' },
43
+ ]),
44
+ multicall(chainId, APE_BOND_POSITION_ADAPTER_ABI, [
45
+ { address: adapter, name: 'vault' },
46
+ { address: adapter, name: 'escrow' },
47
+ ]),
48
+ ]);
49
+ const vault = adapterData?.[0]?.[0];
50
+ const escrow = adapterData?.[1]?.[0];
51
+ if (!poolData || !tokenIn || !vault)
52
+ return EMPTY_LIMITS;
53
+ // previewTwap reverts when the pool's oracle doesn't cover the window, so it's read on its own
54
+ const twapData = await multicall(chainId, LP_STAKING_VAULT_ABI, [{ address: vault, name: 'previewTwap' }]);
55
+ if (!twapData?.[0])
56
+ return EMPTY_LIMITS;
57
+ const [[token0], [token1], [fee]] = poolData;
58
+ const [currentTick, twapTick, maxDeviationTicks] = twapData[0].map(Number);
59
+ const tokenInIsToken0 = tokenIn === token0.toLowerCase();
60
+ if (!tokenInIsToken0 && tokenIn !== token1.toLowerCase())
61
+ return EMPTY_LIMITS;
62
+ const tokenOut = tokenInIsToken0 ? token1 : token0;
63
+ // Paying with token0 lowers the tick; paying with token1 raises it
64
+ const limitTick = tokenInIsToken0 ? twapTick - maxDeviationTicks : twapTick + maxDeviationTicks;
65
+ const hasRoom = tokenInIsToken0 ? currentTick > limitTick : currentTick < limitTick;
66
+ const quoter = UNISWAP_V3_QUOTER_V2[chainId];
67
+ const [quote, escrowData] = await Promise.all([
68
+ hasRoom && quoter
69
+ ? multicall(chainId, UNISWAP_V3_QUOTER_V2_ABI, [
70
+ {
71
+ address: quoter,
72
+ name: 'quoteExactOutputSingle',
73
+ // An unreachable output amount, so the quote stops at the price limit
74
+ params: [{ tokenIn, tokenOut, amount: 2n ** 128n, fee, sqrtPriceLimitX96: getSqrtPriceX96AtTick(limitTick) }],
75
+ },
76
+ ])
77
+ : undefined,
78
+ escrow
79
+ ? multicall(chainId, BONUS_ESCROW_ABI, [
80
+ { address: escrow, name: 'bonusToken' },
81
+ { address: escrow, name: 'totalReserved' },
82
+ ])
83
+ : undefined,
84
+ ]);
85
+ const swapLimit = quote?.[0]?.[0] ?? 0n;
86
+ const maxPayout = (swapLimit * SAFETY_MARGIN_BPS) / SWAP_SHARE_BPS;
87
+ const bonusToken = escrowData?.[0]?.[0];
88
+ const totalReserved = escrowData?.[1]?.[0] ?? 0n;
89
+ const escrowBalanceRes = escrow && bonusToken
90
+ ? await multicall(chainId, erc20ABI, [{ address: bonusToken, name: 'balanceOf', params: [escrow] }])
91
+ : undefined;
92
+ const escrowBalance = escrowBalanceRes?.[0]?.[0] ?? 0n;
93
+ // Bonus token amount → value of the purchases it covers, in tokenIn units, priced at the TWAP like the adapter does
94
+ const bonusToPurchaseValue = (bonusAmount) => {
95
+ if (!bonusBps || !bonusToken)
96
+ return 0n;
97
+ const purchaseValue = (bonusAmount * 10000n) / BigInt(bonusBps);
98
+ const bonusTokenLower = bonusToken.toLowerCase();
99
+ if (bonusTokenLower === tokenIn)
100
+ return purchaseValue;
101
+ // 1.0001^tick is token0's price in token1, in raw units
102
+ const token0Price = 1.0001 ** twapTick;
103
+ const bonusIsToken0 = bonusTokenLower === token0.toLowerCase();
104
+ return BigInt(Math.floor(Number(purchaseValue) * (bonusIsToken0 ? token0Price : 1 / token0Price)));
105
+ };
106
+ const maxTotalPayout = bonusToPurchaseValue(escrowBalance);
107
+ const totalPayoutGiven = bonusToPurchaseValue(totalReserved);
108
+ const remaining = maxTotalPayout > totalPayoutGiven ? maxTotalPayout - totalPayoutGiven : 0n;
109
+ return {
110
+ maxPayout: maxPayout.toString(),
111
+ maxTotalPayout: maxTotalPayout.toString(),
112
+ totalPayoutGiven: totalPayoutGiven.toString(),
113
+ tokensRemaining: formatUnits(remaining, tokenInDecimals),
114
+ };
115
+ };
116
+
117
+ export { fetchLpStakingLimits };
118
+ //# sourceMappingURL=fetchLpStakingLimits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchLpStakingLimits.js","sources":["../../../../../src/adapters/evm/state/lpStaking/fetchLpStakingLimits.ts"],"sourcesContent":["import { BillsConfig } from '@ape.swap/apeswap-lists'\nimport multicall from '../../utils/multicall'\nimport UNISWAP_V3_POOL_ABI from '../../../../config/abi/uniswapV3Pool.json'\nimport LP_STAKING_VAULT_ABI from '../../../../config/abi/lpStakingVault.json'\nimport UNISWAP_V3_QUOTER_V2_ABI from '../../../../config/abi/uniswapV3QuoterV2.json'\nimport BONUS_ESCROW_ABI from '../../../../config/abi/bonusEscrow.json'\nimport APE_BOND_POSITION_ADAPTER_ABI from '../../../../config/abi/apeBondPositionAdapter.json'\nimport ERC20ABI from '../../../../config/abi/erc20.json'\nimport { UNISWAP_V3_QUOTER_V2 } from '../../../../config/constants/addresses'\nimport { formatUnits } from '../../../../utils/fixedPoint'\n\n// The zap swaps about half of the purchase to mint the position (Vladimir's figure: 49.2 %)\nconst SWAP_SHARE_BPS = 4920n\n// Margin for the zap's own fees, slippage and price moves between this read and the buy\nconst SAFETY_MARGIN_BPS = 9000n\n\nexport interface LpStakingLimits {\n maxPayout: string\n maxTotalPayout: string\n totalPayoutGiven: string\n tokensRemaining: string\n}\n\nconst EMPTY_LIMITS: LpStakingLimits = { maxPayout: '0', maxTotalPayout: '0', totalPayoutGiven: '0', tokensRemaining: '0' }\n\n// Float precision is enough for a swap price limit\nconst getSqrtPriceX96AtTick = (tick: number): bigint => BigInt(Math.floor(Math.sqrt(1.0001 ** tick) * 2 ** 96))\n\n/**\n * Translates an LP staking bond's limits into the fields regular bonds read from their contract, all in the pool's\n * stablecoin (`lpToken1`, e.g. USDC), which must also be the bond's earnToken since the UI reads them in its units:\n * - `maxPayout` (per purchase): the largest buy that keeps the pool price within the TWAP guard: the adapter's\n * depositFor reverts (PriceOutsideTwapBounds) when the spot tick is further than the vault's max deviation from its\n * TWAP. `vault.previewTwap()` returns both ticks and the deviation (REAL's operator can change the window and the\n * deviation at any time, so they're read rather than hardcoded). Whatever the buyer pays with, the zap gets the\n * fluctuating token (`lpToken0`) by buying it with the stablecoin in this pool, which is what moves its price. The\n * QuoterV2 returns how much stablecoin that swap can take before the price hits the bound; the zap swaps about\n * half of the purchase, so the purchase can be about twice that. Purchases within the same 5 minutes add up\n * against the TWAP, so it shrinks right after other buys and grows back as the TWAP catches up.\n * - `maxTotalPayout` / `totalPayoutGiven` / `tokensRemaining` (bond total): the escrow's capacity to pay bonuses.\n * Its bonus token balance and reserved bonuses are turned into purchase value (÷ bonus rate) and priced at the TWAP,\n * as the adapter values positions. A soft cap: buys don't revert when the escrow runs short, only claims do.\n * Any read that fails leaves its limits at 0.\n */\nexport const fetchLpStakingLimits = async (\n chainId: number,\n bond: BillsConfig,\n bonusBps: number,\n): Promise<LpStakingLimits> => {\n const { pool, adapter, lpToken1: stablecoin } = bond.lpStakingConfig!\n const tokenIn = stablecoin.address[bond.chainId]?.toLowerCase()\n const tokenInDecimals = stablecoin.decimals[bond.chainId] ?? 18\n\n const [poolData, adapterData] = await Promise.all([\n multicall(chainId, UNISWAP_V3_POOL_ABI, [\n { address: pool, name: 'token0' },\n { address: pool, name: 'token1' },\n { address: pool, name: 'fee' },\n ]),\n multicall(chainId, APE_BOND_POSITION_ADAPTER_ABI, [\n { address: adapter, name: 'vault' },\n { address: adapter, name: 'escrow' },\n ]),\n ])\n const vault: string | undefined = adapterData?.[0]?.[0]\n const escrow: string | undefined = adapterData?.[1]?.[0]\n if (!poolData || !tokenIn || !vault) return EMPTY_LIMITS\n\n // previewTwap reverts when the pool's oracle doesn't cover the window, so it's read on its own\n const twapData = await multicall(chainId, LP_STAKING_VAULT_ABI, [{ address: vault, name: 'previewTwap' }])\n if (!twapData?.[0]) return EMPTY_LIMITS\n\n const [[token0], [token1], [fee]] = poolData\n const [currentTick, twapTick, maxDeviationTicks] = (twapData[0] as [number, number, number]).map(Number)\n const tokenInIsToken0 = tokenIn === token0.toLowerCase()\n if (!tokenInIsToken0 && tokenIn !== token1.toLowerCase()) return EMPTY_LIMITS\n const tokenOut = tokenInIsToken0 ? token1 : token0\n\n // Paying with token0 lowers the tick; paying with token1 raises it\n const limitTick = tokenInIsToken0 ? twapTick - maxDeviationTicks : twapTick + maxDeviationTicks\n const hasRoom = tokenInIsToken0 ? currentTick > limitTick : currentTick < limitTick\n const quoter = UNISWAP_V3_QUOTER_V2[chainId]\n\n const [quote, escrowData] = await Promise.all([\n hasRoom && quoter\n ? multicall(chainId, UNISWAP_V3_QUOTER_V2_ABI, [\n {\n address: quoter,\n name: 'quoteExactOutputSingle',\n // An unreachable output amount, so the quote stops at the price limit\n params: [{ tokenIn, tokenOut, amount: 2n ** 128n, fee, sqrtPriceLimitX96: getSqrtPriceX96AtTick(limitTick) }],\n },\n ])\n : undefined,\n escrow\n ? multicall(chainId, BONUS_ESCROW_ABI, [\n { address: escrow, name: 'bonusToken' },\n { address: escrow, name: 'totalReserved' },\n ])\n : undefined,\n ])\n\n const swapLimit: bigint = quote?.[0]?.[0] ?? 0n\n const maxPayout = (swapLimit * SAFETY_MARGIN_BPS) / SWAP_SHARE_BPS\n\n const bonusToken: string | undefined = escrowData?.[0]?.[0]\n const totalReserved: bigint = escrowData?.[1]?.[0] ?? 0n\n const escrowBalanceRes =\n escrow && bonusToken\n ? await multicall(chainId, ERC20ABI, [{ address: bonusToken, name: 'balanceOf', params: [escrow] }])\n : undefined\n const escrowBalance: bigint = escrowBalanceRes?.[0]?.[0] ?? 0n\n\n // Bonus token amount → value of the purchases it covers, in tokenIn units, priced at the TWAP like the adapter does\n const bonusToPurchaseValue = (bonusAmount: bigint): bigint => {\n if (!bonusBps || !bonusToken) return 0n\n const purchaseValue = (bonusAmount * 10000n) / BigInt(bonusBps)\n const bonusTokenLower = bonusToken.toLowerCase()\n if (bonusTokenLower === tokenIn) return purchaseValue\n // 1.0001^tick is token0's price in token1, in raw units\n const token0Price = 1.0001 ** twapTick\n const bonusIsToken0 = bonusTokenLower === token0.toLowerCase()\n return BigInt(Math.floor(Number(purchaseValue) * (bonusIsToken0 ? token0Price : 1 / token0Price)))\n }\n const maxTotalPayout = bonusToPurchaseValue(escrowBalance)\n const totalPayoutGiven = bonusToPurchaseValue(totalReserved)\n const remaining = maxTotalPayout > totalPayoutGiven ? maxTotalPayout - totalPayoutGiven : 0n\n\n return {\n maxPayout: maxPayout.toString(),\n maxTotalPayout: maxTotalPayout.toString(),\n totalPayoutGiven: totalPayoutGiven.toString(),\n tokensRemaining: formatUnits(remaining, tokenInDecimals),\n }\n}\n"],"names":["ERC20ABI"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Token } from '@ape.swap/apeswap-lists';
2
+ import { BondsData } from '../../../../types/bonds';
3
+ declare const useSoulZapLpStakingQuote: (typedValue: string, inputCurrency: "NATIVE" | Token | undefined, bond: BondsData | undefined, account?: string) => [loading: boolean, response: any, depositAmount: string, error: boolean, trueBondPrice: string | undefined];
4
+ export default useSoulZapLpStakingQuote;
@@ -0,0 +1,140 @@
1
+ import { useMemo } from 'react';
2
+ import { getChainParam } from '../../../../state/zap/getChainParam.js';
3
+ import { apiPost } from '../../../../utils/httpClient.js';
4
+ import { useQuery } from '@tanstack/react-query';
5
+ import { QUERY_KEYS } from '../../../../config/constants/queryKeys.js';
6
+ import useCurrencyPrice from '../../../../state/price/useCurrencyPrice.js';
7
+ import { useSlippage } from '../../../../state/slippage/useSlippage.js';
8
+ import useDebounce from '../../../../hooks/useDebounce.js';
9
+ import { zapInputTokens, WNATIVE } from '@ape.swap/apeswap-lists';
10
+ import { SOUL_ZAP_API } from '../../../../config/constants/variables.js';
11
+ import { parseUnits, formatUnits } from '../../../../utils/fixedPoint.js';
12
+ import multicall from '../../utils/multicall.js';
13
+ import APE_BOND_POSITION_ADAPTER_ABI from '../../../../config/abi/apeBondPositionAdapter.json.js';
14
+
15
+ const useSoulZapLpStakingQuote = (typedValue, inputCurrency, bond, account) => {
16
+ const debouncedInput = useDebounce(typedValue, 500);
17
+ const isDebouncing = typedValue !== debouncedInput;
18
+ const { evmSlippage: slippage } = useSlippage();
19
+ const principalToken = bond?.lpToken;
20
+ const chainId = bond?.chainId;
21
+ const inputCurrencyString = inputCurrency === 'NATIVE' ? '0x0000000000000000000000000000000000000000' : inputCurrency?.address[chainId];
22
+ const inputCurrencyDecimals = inputCurrency === 'NATIVE' ? 18 : inputCurrency?.decimals[chainId];
23
+ const chainName = getChainParam(chainId);
24
+ const bigishInputAmount = parseUnits(debouncedInput ?? '0', inputCurrencyDecimals ?? 18).toString();
25
+ const lpStakingConfig = bond?.lpStakingConfig;
26
+ const zapInputData = useMemo(() => {
27
+ if (chainName &&
28
+ inputCurrencyString &&
29
+ inputCurrencyDecimals &&
30
+ bigishInputAmount !== 'NaN' &&
31
+ bigishInputAmount !== '0' &&
32
+ lpStakingConfig) {
33
+ return {
34
+ chain: chainName,
35
+ recipient: account ?? '0x0000000000000000000000000000000000000000',
36
+ user: account ?? '0x0000000000000000000000000000000000000000',
37
+ integrator: 'apebond',
38
+ lpData: {
39
+ fromToken: inputCurrencyString,
40
+ fromAmount: bigishInputAmount,
41
+ lpType: lpStakingConfig.lpType,
42
+ positionManager: lpStakingConfig.positionManager,
43
+ pool: lpStakingConfig.pool,
44
+ slippage,
45
+ tickLower: '0', //TODO add this
46
+ tickUpper: '0', //TODO add this
47
+ },
48
+ protocolData: {
49
+ protocol: 'RealFinance',
50
+ adapter: lpStakingConfig.adapter,
51
+ campaignId: lpStakingConfig.campaignId,
52
+ },
53
+ };
54
+ }
55
+ }, [account, bigishInputAmount, chainName, inputCurrencyDecimals, inputCurrencyString, lpStakingConfig, slippage]);
56
+ const queryKey = useMemo(() => {
57
+ if (!zapInputData)
58
+ return null;
59
+ return [
60
+ 'zapBondDetails',
61
+ zapInputData.chain,
62
+ zapInputData.user,
63
+ zapInputData.lpData.lpType,
64
+ zapInputData.lpData.fromToken,
65
+ zapInputData.lpData.fromAmount,
66
+ zapInputData.lpData.slippage,
67
+ ];
68
+ }, [zapInputData]);
69
+ const fetchZapDetails = async () => {
70
+ console.log('fetching zap ');
71
+ // The campaign fixes the tick range around the current pool price, so it's read right before each quote
72
+ const res = await multicall(chainId, APE_BOND_POSITION_ADAPTER_ABI, [
73
+ { address: lpStakingConfig.adapter, name: 'campaignRange', params: [lpStakingConfig.campaignId] },
74
+ ]);
75
+ if (!res[0])
76
+ throw new Error('Could not read the campaign tick range');
77
+ const [tickLower, tickUpper] = res[0];
78
+ const response = await apiPost(SOUL_ZAP_API, {
79
+ ...zapInputData,
80
+ lpData: { ...zapInputData.lpData, tickLower: Number(tickLower), tickUpper: Number(tickUpper) },
81
+ });
82
+ return response?.result?.data ?? response;
83
+ };
84
+ const { data: response, isLoading, isFetching, error, } = useQuery({
85
+ queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, queryKey],
86
+ queryFn: fetchZapDetails,
87
+ refetchInterval: 60000, // i.e. 60 sec
88
+ staleTime: 60000,
89
+ enabled: !!queryKey,
90
+ retry: 1,
91
+ });
92
+ const zapError = !!error;
93
+ const tokenList = zapInputTokens[chainId] ? zapInputTokens[chainId] : [];
94
+ // toToken0 data
95
+ const toToken0Estimate = response?.lpQuote?.token0?.fromAmountEstimate;
96
+ const toToken0 = [...tokenList, principalToken]?.find((token) => token?.address?.[chainId]?.toLowerCase() === response?.lpQuote?.token0?.address?.toLowerCase());
97
+ const toToken0Price = useCurrencyPrice(toToken0 ?? null, chainId);
98
+ // toToken1 data
99
+ const toToken1Estimate = response?.lpQuote?.token1?.fromAmountEstimate;
100
+ const toToken1 = zapInputTokens[chainId]?.find((token) => token.address[chainId]?.toLowerCase() === response?.lpQuote?.token1?.address?.toLowerCase());
101
+ const toToken1Price = useCurrencyPrice(toToken1 ?? null, chainId);
102
+ let toToken0USD = Number(formatUnits(toToken0Estimate ?? '0', toToken0?.decimals[chainId] ?? 18)) * (toToken0Price?.price ?? 0); // this is amount of swap output, converted to usd price
103
+ if (response?.lpQuote?.token0?.fromAmountUSD) {
104
+ toToken0USD = Number(response?.lpQuote?.token0?.fromAmountUSD);
105
+ }
106
+ let toToken1USD = Number(formatUnits(toToken1Estimate ?? '0', toToken1?.decimals[chainId] ?? 18)) * (toToken1Price?.price ?? 0); // this is amount of swap output, converted to usd price
107
+ if (response?.lpQuote?.token1?.fromAmountUSD) {
108
+ toToken1USD = Number(response?.lpQuote?.token1?.fromAmountUSD);
109
+ }
110
+ const youSpendUSD = toToken0USD + toToken1USD; // youSpendUSD
111
+ const estimatedDepositAmount = youSpendUSD / Number(bond?.principalTokenPrice ?? '0');
112
+ const isWrap = inputCurrency === 'NATIVE' &&
113
+ bond?.lpToken?.address?.[chainId]?.toLowerCase() === WNATIVE[chainId]?.address?.[chainId]?.toLowerCase();
114
+ const isPrincipalToken = inputCurrency !== 'NATIVE' && inputCurrency?.address[chainId] === principalToken.address[chainId];
115
+ const estimatedDepositAmountToReturn = isWrap || isPrincipalToken
116
+ ? (Number(typedValue || '0') * ((100 - bond?.tierBoostRate) / 100)).toString()
117
+ : estimatedDepositAmount.toString();
118
+ const trueBondPrice = response?.protocolQuote?.trueBondPrice;
119
+ // DEBUG: log tierOptimization when present
120
+ if (response?.protocolQuote?.tierOptimization) {
121
+ const tier = response.protocolQuote.tierOptimization;
122
+ const decimals = principalToken?.decimals?.[chainId] ?? 18;
123
+ const cost = Number(formatUnits(tier.tierCost, decimals));
124
+ const input = Number(formatUnits(tier.bondInput, decimals));
125
+ const profit = Number(formatUnits(tier.profit, decimals));
126
+ console.log('[ZAP] tierOptimization:', {
127
+ tier: `${tier.previousTier} → ${tier.newTier}`,
128
+ cost: cost.toFixed(6),
129
+ bondInput: input.toFixed(6),
130
+ profit: profit.toFixed(6),
131
+ });
132
+ }
133
+ const zapLoading = isDebouncing || isLoading || isFetching;
134
+ if (zapLoading)
135
+ return [true, undefined, '', false, undefined];
136
+ return [zapLoading, response, estimatedDepositAmountToReturn, zapError, trueBondPrice];
137
+ };
138
+
139
+ export { useSoulZapLpStakingQuote as default };
140
+ //# sourceMappingURL=useSoulZapLpStakingQuote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSoulZapLpStakingQuote.js","sources":["../../../../../src/adapters/evm/state/lpStaking/useSoulZapLpStakingQuote.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { ChainId, Token } from '@ape.swap/apeswap-lists'\nimport { getChainParam } from '../../../../state/zap/getChainParam'\nimport { apiPost } from '../../../../utils/httpClient'\nimport { useQuery } from '@tanstack/react-query'\nimport { QUERY_KEYS } from '../../../../config/constants/queryKeys'\nimport useCurrencyPrice from '../../../../state/price/useCurrencyPrice'\nimport { BondsData } from '../../../../types/bonds'\nimport { useSlippage } from '../../../../state/slippage/useSlippage'\nimport useDebounce from '../../../../hooks/useDebounce'\nimport { WNATIVE, zapInputTokens } from '@ape.swap/apeswap-lists'\nimport { SOUL_ZAP_API } from '../../../../config/constants/variables'\nimport { formatUnits, parseUnits } from '../../../../utils/fixedPoint'\nimport multicall from '../../utils/multicall'\nimport APE_BOND_POSITION_ADAPTER_ABI from '../../../../config/abi/apeBondPositionAdapter.json'\n\nconst useSoulZapLpStakingQuote = (\n typedValue: string,\n inputCurrency: 'NATIVE' | Token | undefined,\n bond: BondsData | undefined,\n account?: string,\n): [loading: boolean, response: any, depositAmount: string, error: boolean, trueBondPrice: string | undefined] => {\n const debouncedInput = useDebounce(typedValue, 500)\n const isDebouncing = typedValue !== debouncedInput\n const { evmSlippage: slippage } = useSlippage()\n\n const principalToken = bond?.lpToken as Token\n const chainId = bond?.chainId as ChainId\n const inputCurrencyString =\n inputCurrency === 'NATIVE' ? '0x0000000000000000000000000000000000000000' : inputCurrency?.address[chainId]\n const inputCurrencyDecimals = inputCurrency === 'NATIVE' ? 18 : inputCurrency?.decimals![chainId]\n const chainName = getChainParam(chainId)\n\n const bigishInputAmount = parseUnits(debouncedInput ?? '0', inputCurrencyDecimals ?? 18).toString()\n const lpStakingConfig = bond?.lpStakingConfig\n\n const zapInputData = useMemo(() => {\n if (\n chainName &&\n inputCurrencyString &&\n inputCurrencyDecimals &&\n bigishInputAmount !== 'NaN' &&\n bigishInputAmount !== '0' &&\n lpStakingConfig\n ) {\n return {\n chain: chainName,\n recipient: account ?? '0x0000000000000000000000000000000000000000',\n user: account ?? '0x0000000000000000000000000000000000000000',\n integrator: 'apebond',\n lpData: {\n fromToken: inputCurrencyString,\n fromAmount: bigishInputAmount,\n lpType: lpStakingConfig.lpType,\n positionManager: lpStakingConfig.positionManager,\n pool: lpStakingConfig.pool,\n slippage,\n tickLower: '0', //TODO add this\n tickUpper: '0', //TODO add this\n },\n protocolData: {\n protocol: 'RealFinance',\n adapter: lpStakingConfig.adapter,\n campaignId: lpStakingConfig.campaignId,\n },\n }\n }\n }, [account, bigishInputAmount, chainName, inputCurrencyDecimals, inputCurrencyString, lpStakingConfig, slippage])\n\n const queryKey = useMemo(() => {\n if (!zapInputData) return null\n return [\n 'zapBondDetails',\n zapInputData.chain,\n zapInputData.user,\n zapInputData.lpData.lpType,\n zapInputData.lpData.fromToken,\n zapInputData.lpData.fromAmount,\n zapInputData.lpData.slippage,\n ]\n }, [zapInputData])\n\n const fetchZapDetails = async () => {\n console.log('fetching zap ')\n // The campaign fixes the tick range around the current pool price, so it's read right before each quote\n const res = await multicall(chainId, APE_BOND_POSITION_ADAPTER_ABI, [\n { address: lpStakingConfig!.adapter, name: 'campaignRange', params: [lpStakingConfig!.campaignId] },\n ])\n if (!res[0]) throw new Error('Could not read the campaign tick range')\n\n const [tickLower, tickUpper] = res[0]\n\n const response = await apiPost<any>(SOUL_ZAP_API, {\n ...zapInputData,\n lpData: { ...zapInputData!.lpData, tickLower: Number(tickLower), tickUpper: Number(tickUpper) },\n })\n return response?.result?.data ?? response\n }\n\n const {\n data: response,\n isLoading,\n isFetching,\n error,\n } = useQuery({\n queryKey: [QUERY_KEYS.ZAP_TOKEN_QUOTE, queryKey],\n queryFn: fetchZapDetails,\n refetchInterval: 60000, // i.e. 60 sec\n staleTime: 60000,\n enabled: !!queryKey,\n retry: 1,\n })\n const zapError = !!error\n\n const tokenList = zapInputTokens[chainId] ? zapInputTokens[chainId] : []\n\n // toToken0 data\n const toToken0Estimate: string | undefined = response?.lpQuote?.token0?.fromAmountEstimate\n const toToken0 = [...tokenList, principalToken]?.find(\n (token) => token?.address?.[chainId]?.toLowerCase() === response?.lpQuote?.token0?.address?.toLowerCase(),\n )\n const toToken0Price = useCurrencyPrice(toToken0 ?? null, chainId)\n\n // toToken1 data\n const toToken1Estimate: string | undefined = response?.lpQuote?.token1?.fromAmountEstimate\n const toToken1 = zapInputTokens[chainId]?.find(\n (token) => token.address[chainId]?.toLowerCase() === response?.lpQuote?.token1?.address?.toLowerCase(),\n )\n const toToken1Price = useCurrencyPrice(toToken1 ?? null, chainId)\n\n let toToken0USD =\n Number(formatUnits(toToken0Estimate ?? '0', toToken0?.decimals![chainId] ?? 18)) * (toToken0Price?.price ?? 0) // this is amount of swap output, converted to usd price\n\n if (response?.lpQuote?.token0?.fromAmountUSD) {\n toToken0USD = Number(response?.lpQuote?.token0?.fromAmountUSD)\n }\n\n let toToken1USD =\n Number(formatUnits(toToken1Estimate ?? '0', toToken1?.decimals![chainId] ?? 18)) * (toToken1Price?.price ?? 0) // this is amount of swap output, converted to usd price\n\n if (response?.lpQuote?.token1?.fromAmountUSD) {\n toToken1USD = Number(response?.lpQuote?.token1?.fromAmountUSD)\n }\n\n const youSpendUSD = toToken0USD + toToken1USD // youSpendUSD\n const estimatedDepositAmount = youSpendUSD / Number(bond?.principalTokenPrice ?? '0')\n\n const isWrap =\n inputCurrency === 'NATIVE' &&\n bond?.lpToken?.address?.[chainId]?.toLowerCase() === WNATIVE[chainId]?.address?.[chainId]?.toLowerCase()\n\n const isPrincipalToken =\n inputCurrency !== 'NATIVE' && inputCurrency?.address[chainId] === principalToken.address[chainId]\n\n const estimatedDepositAmountToReturn =\n isWrap || isPrincipalToken\n ? (Number(typedValue || '0') * ((100 - bond?.tierBoostRate!) / 100)).toString()\n : estimatedDepositAmount.toString()\n\n const trueBondPrice: string | undefined = response?.protocolQuote?.trueBondPrice\n\n // DEBUG: log tierOptimization when present\n if (response?.protocolQuote?.tierOptimization) {\n const tier = response.protocolQuote.tierOptimization\n const decimals = principalToken?.decimals?.[chainId] ?? 18\n const cost = Number(formatUnits(tier.tierCost, decimals))\n const input = Number(formatUnits(tier.bondInput, decimals))\n const profit = Number(formatUnits(tier.profit, decimals))\n console.log('[ZAP] tierOptimization:', {\n tier: `${tier.previousTier} → ${tier.newTier}`,\n cost: cost.toFixed(6),\n bondInput: input.toFixed(6),\n profit: profit.toFixed(6),\n })\n }\n\n const zapLoading = isDebouncing || isLoading || isFetching\n if (zapLoading) return [true, undefined, '', false, undefined]\n\n return [zapLoading, response, estimatedDepositAmountToReturn, zapError, trueBondPrice]\n}\n\nexport default useSoulZapLpStakingQuote\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { useMemo } from 'react';
2
2
  import { dexFactories, Wrappers, BillVersion, zapInputTokens, WNATIVE } from '@ape.swap/apeswap-lists';
3
- import { getChainParam, getLpType } from '../../../state/zap/getChainParam.js';
3
+ import { getLpType, getChainParam } from '../../../state/zap/getChainParam.js';
4
4
  import { apiPost } from '../../../utils/httpClient.js';
5
5
  import { useQuery } from '@tanstack/react-query';
6
6
  import { QUERY_KEYS } from '../../../config/constants/queryKeys.js';
@@ -391,7 +391,7 @@ const BuyComponent = ({ onDismiss, bondAddress, bondChain, handlePurchasedBond,
391
391
  }
392
392
  /* eslint-disable react-hooks/exhaustive-deps */
393
393
  }, [rateChanged]);
394
- return bondData ? (jsx(Flex, { className: "modal-content ape:flex ape:flex-col ape:rounded-[10px] ape:bg-white2 ape:w-full ape:p-3.75 ape:md:p-5", style: { ...MCBuyComponentStyles[bondData?.marketingCampaign] }, children: jsxs(Flex, { className: "modaltable-container ape:w-full ape:flex ape:flex-col ape:relative ape:gap-2.5", children: [jsx(BondModalHeader, { bondData: bondData, onDismiss: onDismiss, showProjectInfoButton: SDKConfig?.referenceId === 'apebond' }), jsx(ProjectDescription, { description: bondData.shortDescription, isProjectView: true }), jsx(Flex, { className: clsx('ape:w-full', isProjectView ? 'ape:flex ape:md:hidden!' : 'ape:flex'), children: jsx(BondCards, { bondData: bondData, isDoingMaxBuy: exceedsSafeMaxBuy && !exceedsRealMaxBuy }) }), jsx(Estimations, { depositAmount: depositAmount, inputValue: inputValue, inputTokenPrice: inputTokenPrice, bondData: bondData, youSpendString: youSpendString, isZap: isZapSupported, fetchingZapQuote: fetchingZapQuote, zapError: zapError }), jsx(TokenSelectorPanel, { typedValue: inputValue, setTypedValue: setInputValue, selectedToken: inputToken, handleValueBtn: handleMaxButton, handleCurrencySelect: handleCurrencySelect, bondChainId: bondData?.chainId, enableZap: isZapSupported, bondPrincipalToken: bondData?.lpToken, tokenBalance: inputCurrencyBalance, selectedTokenPrice: inputTokenPrice, inputDisabled: isUserRestricted, marketingCampaign: bondData?.marketingCampaign, isConnected: !!account }), SDKConfig.useTiers &&
394
+ return bondData ? (jsx(Flex, { className: "modal-content ape:flex ape:flex-col ape:rounded-[10px] ape:bg-white2 ape:w-full ape:p-3.75 ape:md:p-5", style: { ...MCBuyComponentStyles[bondData?.marketingCampaign] }, children: jsxs(Flex, { className: "modaltable-container ape:w-full ape:flex ape:flex-col ape:relative ape:gap-2.5", children: [jsx(BondModalHeader, { bondData: bondData, onDismiss: onDismiss }), jsx(ProjectDescription, { description: bondData.shortDescription, isProjectView: true }), jsx(Flex, { className: clsx('ape:w-full', isProjectView ? 'ape:flex ape:md:hidden!' : 'ape:flex'), children: jsx(BondCards, { bondData: bondData, isDoingMaxBuy: exceedsSafeMaxBuy && !exceedsRealMaxBuy }) }), jsx(Estimations, { depositAmount: depositAmount, inputValue: inputValue, inputTokenPrice: inputTokenPrice, bondData: bondData, youSpendString: youSpendString, isZap: isZapSupported, fetchingZapQuote: fetchingZapQuote, zapError: zapError }), jsx(TokenSelectorPanel, { typedValue: inputValue, setTypedValue: setInputValue, selectedToken: inputToken, handleValueBtn: handleMaxButton, handleCurrencySelect: handleCurrencySelect, bondChainId: bondData?.chainId, enableZap: isZapSupported, bondPrincipalToken: bondData?.lpToken, tokenBalance: inputCurrencyBalance, selectedTokenPrice: inputTokenPrice, inputDisabled: isUserRestricted, marketingCampaign: bondData?.marketingCampaign, isConnected: !!account }), SDKConfig.useTiers &&
395
395
  userTier !== LaunchBondTiers.Mythical &&
396
396
  bondData?.billVersion === BillVersion.V4 &&
397
397
  account && (jsx(PointsLeftForNextTier, { bond: bondData, inputAmount: inputValue, setInputValue: setInputValue, inputTokenPrice: inputTokenPrice, inputTokenDecimals: inputToken === 'NATIVE' ? 18 : (inputToken?.decimals?.[bondData?.chainId] ?? 18) })), bondData?.warningCard && (jsx(Flex, { className: "ape:w-full ape:rounded-normal ape:p-[2px_10px]", style: { background: '#DE62F366' }, children: jsx(Text, { as: "div", size: "12px", className: "ape:font-normal ape:flex ape:items-center ape:leading-5.5!", children: jsx(SafeHTMLComponent, { html: bondData?.warningCard }) }) })), jsx(Flex, { className: "modaltable-container button-container ape:w-full ape:flex ape:relative ape:flex-row ape:justify-between", children: jsx(Flex, { className: "button-container buy ape:justify-center ape:items-center ape:cursor-pointer ape:w-full", children: !account ? (jsx(ConnectButton, {})) : (jsxs(Flex, { className: "ape:w-full ape:gap-[10px] ape:flex-col ape:md:flex-row", children: [jsx(Button, { variant: "secondary", onClick: () => canBridge ? onOpenBridgeModal() : bondChain === ChainId.L1X ? onOpenl1xIframe() : openExternal(), onMouseEnter: canBridge ? bridge.preload : undefined, onFocus: canBridge ? bridge.preload : undefined, className: "ape:w-full ape:md:w-[35%] ape:text-[14px]! ape:lg:text-[16px]!", children: canBridge