-
+
{isConnected ? (
<>
diff --git a/src/components/TransactionButton/index.tsx b/src/components/TransactionButton/index.tsx
index 2962770..063b854 100644
--- a/src/components/TransactionButton/index.tsx
+++ b/src/components/TransactionButton/index.tsx
@@ -8,6 +8,7 @@ import { Button, ButtonProps } from '../ui/button'
import { dfmmABI } from '@/lib/abis/dfmm'
import { rmmABI } from '@/lib/abis/rmm'
import { SYABI } from '@/lib/abis/sy'
+import { liquidityManagerABI } from '@/lib/abis/liquidityManager'
const functionNameToAction: { [fnName: string]: string } = {
['swapExactSyForYt']: 'Buy Yield',
@@ -18,7 +19,7 @@ const functionNameToAction: { [fnName: string]: string } = {
export interface TransactionButtonProps extends ButtonProps {
from?: Address
to: Address
- contractName?: 'dfmm' | 'erc20' | 'rmm' | 'SY'
+ contractName?: 'dfmm' | 'erc20' | 'rmm' | 'SY' | 'liquidityManager'
functionName: string
args: any[]
txHash?: `0x${string}`
@@ -100,6 +101,7 @@ function transactionReducer(
state: TransactionState,
action: TransactionAction
): TransactionState {
+ console.log('Changing to state: ', action.type)
switch (action.type) {
case 'TRANSACTION_READY':
return TransactionState.TransactionReady
@@ -157,14 +159,16 @@ function TransactionButton(props: TransactionButtonProps): JSX.Element {
? dfmmABI
: props.contractName === 'erc20'
? erc20Abi
- : ({} as Abi)
+ : props.contractName === 'liquidityManager'
+ ? liquidityManagerABI
+ : ({} as Abi)
const simulation = useSimulateContract({
abi,
address: props.to,
functionName: props.functionName,
args: props.args,
- value: props.value,
+ value: props.value ?? 0n,
stateOverride: props.stateOverride,
query: {
enabled:
@@ -227,6 +231,7 @@ function TransactionButton(props: TransactionButtonProps): JSX.Element {
if (simulation?.error) {
dispatch({ type: 'SIMULATE_ERROR' })
+ console.log('Simulate failed with error: ')
console.error(simulation.failureReason)
return
}
diff --git a/src/data/contracts.ts b/src/data/contracts.ts
index 32656d9..e391664 100644
--- a/src/data/contracts.ts
+++ b/src/data/contracts.ts
@@ -1,9 +1 @@
-export const G3mSolver = '0x05792cA1459699A3DA6e6E7Af295E3C792D5e038'
-export const nG3mSolver = '0xF00E9B380140E47B6fe0Ece62a50af75aD4FD984'
-export const lnSolver = ''
-export const csSolver = '0xf24FF07f7556BC4B9A91f88AFe8Ea7Cb5efb71CA'
-
-export const lnStrategy = ''
-export const nG3mStrategy = '0x8Cc5377b8384F210170901c5EAb6C8a257f02316'
-export const csStrategy = '0x1623841962bCB856C44Ac55Ef1D1C3c3354F56Ac'
-export const dfmmAddress = '0x2aD77BEb56d7b1875B7bbB4cC29A7061afeF613b'
+export const liquidityManager = '0x5Cf5D175bC74319d4AF42f3026aF6446901559a7'
diff --git a/src/lib/abis/liquidityManager.ts b/src/lib/abis/liquidityManager.ts
new file mode 100644
index 0000000..a6db870
--- /dev/null
+++ b/src/lib/abis/liquidityManager.ts
@@ -0,0 +1,200 @@
+export const liquidityManagerABI = [
+ {
+ type: 'function',
+ name: 'allocateFromPt',
+ inputs: [
+ {
+ name: 'args',
+ type: 'tuple',
+ internalType: 'struct LiquidityManager.AllocateArgs',
+ components: [
+ { name: 'rmm', type: 'address', internalType: 'address' },
+ {
+ name: 'amountIn',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'minOut',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'minLiquidityDelta',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'initialGuess',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'epsilon',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ ],
+ },
+ ],
+ outputs: [
+ { name: 'liquidity', type: 'uint256', internalType: 'uint256' },
+ ],
+ stateMutability: 'nonpayable',
+ },
+ {
+ type: 'function',
+ name: 'allocateFromSy',
+ inputs: [
+ {
+ name: 'args',
+ type: 'tuple',
+ internalType: 'struct LiquidityManager.AllocateArgs',
+ components: [
+ { name: 'rmm', type: 'address', internalType: 'address' },
+ {
+ name: 'amountIn',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'minOut',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'minLiquidityDelta',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'initialGuess',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'epsilon',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ ],
+ },
+ ],
+ outputs: [
+ { name: 'liquidity', type: 'uint256', internalType: 'uint256' },
+ ],
+ stateMutability: 'nonpayable',
+ },
+ {
+ type: 'function',
+ name: 'computePtToSyToAddLiquidity',
+ inputs: [
+ {
+ name: 'args',
+ type: 'tuple',
+ internalType: 'struct LiquidityManager.ComputeArgs',
+ components: [
+ { name: 'rmm', type: 'address', internalType: 'address' },
+ { name: 'rX', type: 'uint256', internalType: 'uint256' },
+ { name: 'rY', type: 'uint256', internalType: 'uint256' },
+ { name: 'index', type: 'uint256', internalType: 'PYIndex' },
+ { name: 'maxIn', type: 'uint256', internalType: 'uint256' },
+ {
+ name: 'blockTime',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'initialGuess',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'epsilon',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ ],
+ },
+ ],
+ outputs: [
+ { name: 'guess', type: 'uint256', internalType: 'uint256' },
+ { name: 'syOut', type: 'uint256', internalType: 'uint256' },
+ ],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ name: 'computeSyToPtToAddLiquidity',
+ inputs: [
+ {
+ name: 'args',
+ type: 'tuple',
+ internalType: 'struct LiquidityManager.ComputeArgs',
+ components: [
+ { name: 'rmm', type: 'address', internalType: 'address' },
+ { name: 'rX', type: 'uint256', internalType: 'uint256' },
+ { name: 'rY', type: 'uint256', internalType: 'uint256' },
+ { name: 'index', type: 'uint256', internalType: 'PYIndex' },
+ { name: 'maxIn', type: 'uint256', internalType: 'uint256' },
+ {
+ name: 'blockTime',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'initialGuess',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ {
+ name: 'epsilon',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ ],
+ },
+ ],
+ outputs: [
+ { name: 'guess', type: 'uint256', internalType: 'uint256' },
+ { name: 'ptOut', type: 'uint256', internalType: 'uint256' },
+ ],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ name: 'mintSY',
+ inputs: [
+ { name: 'SY', type: 'address', internalType: 'address' },
+ { name: 'receiver', type: 'address', internalType: 'address' },
+ { name: 'tokenIn', type: 'address', internalType: 'address' },
+ {
+ name: 'amountTokenToDeposit',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ { name: 'minSharesOut', type: 'uint256', internalType: 'uint256' },
+ ],
+ outputs: [
+ { name: 'amountOut', type: 'uint256', internalType: 'uint256' },
+ ],
+ stateMutability: 'payable',
+ },
+ {
+ type: 'error',
+ name: 'InsufficientSYMinted',
+ inputs: [
+ { name: 'amountMinted', type: 'uint256', internalType: 'uint256' },
+ {
+ name: 'minAmountMinted',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
+ ],
+ },
+ {
+ type: 'error',
+ name: 'InvalidTokenIn',
+ inputs: [{ name: 'tokenIn', type: 'address', internalType: 'address' }],
+ },
+]
diff --git a/src/lib/abis/rmm.ts b/src/lib/abis/rmm.ts
index 0a15b7b..a6f175c 100644
--- a/src/lib/abis/rmm.ts
+++ b/src/lib/abis/rmm.ts
@@ -159,21 +159,25 @@ export const rmmABI = [
inputs: [
{ name: 'index', type: 'uint256', internalType: 'PYIndex' },
{ name: 'exactSYIn', type: 'uint256', internalType: 'uint256' },
+ { name: 'max', type: 'uint256', internalType: 'uint256' },
{ name: 'blockTime', type: 'uint256', internalType: 'uint256' },
{ name: 'initialGuess', type: 'uint256', internalType: 'uint256' },
+ { name: 'epsilon', type: 'uint256', internalType: 'uint256' },
],
- outputs: [{ name: '', type: 'uint256', internalType: 'uint256' }],
+ outputs: [{ name: 'guess', type: 'uint256', internalType: 'uint256' }],
stateMutability: 'view',
},
{
type: 'function',
- name: 'computeTokenToYt',
+ name: 'computeTokenToYT',
inputs: [
{ name: 'index', type: 'uint256', internalType: 'PYIndex' },
{ name: 'token', type: 'address', internalType: 'address' },
{ name: 'exactTokenIn', type: 'uint256', internalType: 'uint256' },
+ { name: 'max', type: 'uint256', internalType: 'uint256' },
{ name: 'blockTime', type: 'uint256', internalType: 'uint256' },
{ name: 'initialGuess', type: 'uint256', internalType: 'uint256' },
+ { name: 'epsilon', type: 'uint256', internalType: 'uint256' },
],
outputs: [
{
@@ -542,8 +546,15 @@ export const rmmABI = [
type: 'function',
name: 'swapExactSyForYt',
inputs: [
- { name: 'amountIn', type: 'uint256', internalType: 'uint256' },
+ { name: 'maxSyIn', type: 'uint256', internalType: 'uint256' },
+ {
+ name: 'amountPtToFlash',
+ type: 'uint256',
+ internalType: 'uint256',
+ },
{ name: 'minAmountOut', type: 'uint256', internalType: 'uint256' },
+ { name: 'upperBound', type: 'uint256', internalType: 'uint256' },
+ { name: 'epsilon', type: 'uint256', internalType: 'uint256' },
{ name: 'to', type: 'address', internalType: 'address' },
],
outputs: [
@@ -565,6 +576,8 @@ export const rmmABI = [
},
{ name: 'minSyMinted', type: 'uint256', internalType: 'uint256' },
{ name: 'minYtOut', type: 'uint256', internalType: 'uint256' },
+ { name: 'upperBound', type: 'uint256', internalType: 'uint256' },
+ { name: 'epsilon', type: 'uint256', internalType: 'uint256' },
{ name: 'to', type: 'address', internalType: 'address' },
],
outputs: [
@@ -637,13 +650,6 @@ export const rmmABI = [
outputs: [{ name: '', type: 'bool', internalType: 'bool' }],
stateMutability: 'nonpayable',
},
- {
- type: 'function',
- name: 'version',
- inputs: [],
- outputs: [{ name: '', type: 'string', internalType: 'string' }],
- stateMutability: 'pure',
- },
{
type: 'event',
name: 'Allocate',
diff --git a/src/lib/useLiquidityManagerArgs.ts b/src/lib/useLiquidityManagerArgs.ts
new file mode 100644
index 0000000..824ba63
--- /dev/null
+++ b/src/lib/useLiquidityManagerArgs.ts
@@ -0,0 +1,156 @@
+import { useEffect } from 'react'
+import { useAccount, useReadContract } from 'wagmi'
+import { getAddress } from 'viem'
+
+import { liquidityManagerABI } from './abis/liquidityManager'
+import { useTransactionStatus } from '@/components/TransactionButton/useTransactionStatus'
+import { toWad } from '@/utils/numbers'
+
+import useSlippagePreference from './useSlippagePreference'
+import { ArgsHookReturn } from './useSwapArgs'
+import { timestamp } from '@/utils/dates'
+import { rmmABI } from './abis/rmm'
+
+export function useLiquidityManagerArgs({
+ marketId,
+ liquidityManagerAddress,
+ pyIndexStored,
+ reserveX,
+ reserveY,
+ isZapSy,
+ amountIn,
+ enabled,
+}: {
+ marketId: string
+ liquidityManagerAddress: string
+ pyIndexStored: bigint
+ reserveX: bigint
+ reserveY: bigint
+ isZapSy: boolean
+ amountIn: string
+ enabled: boolean
+}): ArgsHookReturn {
+ const { address } = useAccount()
+ const { setTxHash, txHash, txReceipt } = useTransactionStatus({})
+ const [slippage] = useSlippagePreference()
+
+ const inputAmount = !isNaN(parseFloat(amountIn))
+ ? toWad(parseFloat(amountIn))
+ : 0n
+
+ let RMM = undefined
+ try {
+ RMM = getAddress(marketId)
+ } catch (e) {}
+
+ const prepareFunctionName = isZapSy
+ ? 'computeSyToPtToAddLiquidity'
+ : 'computePtToSyToAddLiquidity'
+ const functionName = isZapSy ? 'allocateFromSy' : 'allocateFromPt'
+
+ const { data, status, error, failureReason, fetchStatus } = useReadContract(
+ {
+ abi: liquidityManagerABI,
+ address: liquidityManagerAddress as `0x${string}`,
+ account: address as `0x${string}`,
+ functionName: prepareFunctionName,
+ args: [
+ {
+ rmm: RMM,
+ rX: reserveX,
+ rY: reserveY,
+ index: pyIndexStored,
+ maxIn: inputAmount,
+ blockTime: timestamp(),
+ initialGuess: 0n,
+ epsilon: 10_000n,
+ },
+ ],
+ query: {
+ enabled: enabled && !!RMM && !!liquidityManagerAddress,
+ },
+ }
+ )
+
+ console.log({ data, failureReason })
+
+ const swapInput = (data?.[0] as bigint) ?? 0n
+ const swapOutput = (data?.[1] as bigint) ?? 0n - 1000n
+
+ const {
+ data: prepareAllocateData,
+ status: prepareAllocateStatus,
+ error: prepareAllocateError,
+ failureReason: prepareAllocateFailureReason,
+ } = useReadContract({
+ abi: rmmABI,
+ address: RMM as `0x${string}`,
+ account: address as `0x${string}`,
+ functionName: 'prepareAllocate',
+ args: [inputAmount - swapInput, swapOutput, pyIndexStored],
+ query: {
+ enabled: enabled && !!RMM && !!data,
+ },
+ })
+
+ const minLiquidityDelta = (prepareAllocateData?.[2] as bigint) ?? 0n
+ const outputAmount = minLiquidityDelta
+ const minOutputAmount = outputAmount
+ ? (outputAmount * toWad(1 - slippage)) / toWad(1)
+ : 0n
+ const lptMinted = (prepareAllocateData?.[3] as bigint) ?? 0n
+
+ useEffect(() => {
+ if (error || failureReason) {
+ console.log('useLiquidityManagerArgs error: ', error, failureReason)
+ }
+
+ if (prepareAllocateError || prepareAllocateFailureReason) {
+ console.log(
+ 'useLiquidityManagerArgs prepareAllocateError: ',
+ prepareAllocateError,
+ prepareAllocateFailureReason
+ )
+ }
+ }, [
+ error,
+ failureReason,
+ prepareAllocateError,
+ prepareAllocateFailureReason,
+ ])
+
+ console.log({
+ rmm: RMM,
+ amountIn: inputAmount,
+ minOut: swapOutput,
+ minLiquidtyDelta: minOutputAmount,
+ initialGuess: swapInput,
+ epsilon: toWad(5) / 1000n,
+ })
+
+ return {
+ amountOut: lptMinted,
+ status,
+ fetchStatus,
+ payload: {
+ from: address as `0x${string}`,
+ to: liquidityManagerAddress as `0x${string}`,
+ contractName: 'liquidityManager',
+ functionName,
+ args: [
+ {
+ rmm: RMM,
+ amountIn: inputAmount,
+ minOut: swapOutput,
+ minLiquidityDelta: minOutputAmount,
+ initialGuess: swapInput,
+ epsilon: toWad(5) / 1000n,
+ } as const,
+ ],
+ value: 0n,
+ txHash,
+ txReceipt,
+ setTxHash,
+ },
+ }
+}
diff --git a/src/lib/useTokens.ts b/src/lib/useTokens.ts
index b180889..0c77139 100644
--- a/src/lib/useTokens.ts
+++ b/src/lib/useTokens.ts
@@ -32,6 +32,17 @@ export function useTokens({ id }: { id?: string }): {
market?.marketTokens?.items.map((item) => item.token) ?? []
)
+ // Add the markets themselves as tokens in the allTokens array
+ const marketsAsTokens = data.markets.items.map((market) => ({
+ id: market.id,
+ symbol: 'LP-' + market.name,
+ name: 'LP-' + market.name,
+ icon: market.icon,
+ decimals: 18,
+ }))
+
+ allTokens.push(...marketsAsTokens)
+
// Filter out duplicates based on a combination of 'id' and 'symbol' for uniqueness
const uniqueTokens = Array.from(
new Map(
diff --git a/src/pages/allocate/index.tsx b/src/pages/allocate/index.tsx
new file mode 100644
index 0000000..84b660c
--- /dev/null
+++ b/src/pages/allocate/index.tsx
@@ -0,0 +1,171 @@
+import React from 'react'
+import { useAccount } from 'wagmi'
+
+import { allMarketsQueryDocument } from '../../queries/markets'
+import { useGraphQL } from '../../useGraphQL'
+import { ImplYieldQueryDocument } from '../../queries/prices'
+import { PositionQueryDocument } from '../../queries/positions'
+
+import YieldPositionsTable from '@/components/YieldPositionsTable'
+import InfoCard from '@/components/InfoCard'
+import InfoHeader from '@/components/InfoHeader'
+import SectionHeader from '@/components/SectionHeader'
+import { useTradeRoute } from '@/lib/useTradeRoute'
+import { ETH_ADDRESS } from '@/lib/useTokens'
+import { useOutputAmount } from '@/lib/useOutputAmount'
+import { daysUntilDate, fromExpiryToDate } from '@/utils/dates'
+import { FALLBACK_MARKET_ADDRESS } from '@/utils/address'
+import { formatPercentage } from '@/utils/numbers'
+import AddLiquidityView from '@/components/AddLiquidityView'
+
+const EmptyPositionTable: React.FC = () => {
+ return (
+
+
+ Connect to View Positions
+
+
+ )
+}
+
+type AllocateCardProps = {
+ selectedMarket: string
+ setSelectedMarket: (marketId: string) => void
+ marketId: string
+ syTokenId: string
+ liquidityTokenId: string
+ expiry: number
+ avgEntryImpliedRate: number
+}
+
+const AllocateCard: React.FC
= ({
+ selectedMarket,
+ setSelectedMarket,
+ marketId,
+ syTokenId,
+ liquidityTokenId,
+ expiry,
+ avgEntryImpliedRate,
+}) => {
+ const { setTokenParams } = useTradeRoute()
+
+ const bg = marketId.comp(selectedMarket)
+ ? 'bg-secondary border-foreground/50'
+ : ''
+
+ return (
+ {
+ setSelectedMarket(marketId)
+ setTokenParams(syTokenId, liquidityTokenId)
+ }}
+ >
+
+
{fromExpiryToDate(expiry)}
+
+ ({daysUntilDate(expiry)}d)
+
+
+
+
+
+ {formatPercentage(avgEntryImpliedRate)}
+
+
+ Implied vAPR
+
+
+
+ )
+}
+
+const AllocatePage: React.FC = () => {
+ const { address } = useAccount()
+ const { getOutputAmount } = useOutputAmount()
+ const outputAmount = Number(getOutputAmount())
+ const [selectedMarket, setSelectedMarket] = React.useState<
+ string | undefined
+ >(undefined)
+
+ // market data
+ const { data, refetch, isFetching, isLoading } = useGraphQL(
+ allMarketsQueryDocument,
+ { limit: 10 }
+ )
+ // position data
+ const { data: positionData } = useGraphQL(PositionQueryDocument, {
+ marketId: selectedMarket as string,
+ })
+ // yield data
+ const { data: implied } = useGraphQL(ImplYieldQueryDocument, {
+ marketId: selectedMarket as string,
+ })
+
+ return (
+
+
+
+
+
+
+
+ {data?.markets?.items?.map((market) => (
+
+ market.id.comp(item?.marketId)
+ )?.[0]?.value
+ }
+ />
+ ))}
+
+
+
+
+ {address ? (
+
+
+
+
+
+ {data && (
+
+ )}
+
+
+
+
+
+ ) : (
+
+ )}
+
+
+ )
+}
+
+export default AllocatePage
diff --git a/src/pages/portfolio/index.tsx b/src/pages/portfolio/index.tsx
new file mode 100644
index 0000000..f8125d2
--- /dev/null
+++ b/src/pages/portfolio/index.tsx
@@ -0,0 +1,11 @@
+import AccountHoldings from '@/components/AccountHoldings'
+
+const Portfolio: React.FC = () => {
+ return (
+
+ )
+}
+
+export default Portfolio
diff --git a/src/pages/yield/index.tsx b/src/pages/yield/index.tsx
index db5bef0..2ea439e 100644
--- a/src/pages/yield/index.tsx
+++ b/src/pages/yield/index.tsx
@@ -16,6 +16,7 @@ import { useOutputAmount } from '@/lib/useOutputAmount'
import { daysUntilDate, fromExpiryToDate } from '@/utils/dates'
import { FALLBACK_MARKET_ADDRESS } from '@/utils/address'
import { formatPercentage } from '@/utils/numbers'
+import TradeView from '@/components/TradeView'
const EmptyPositionTable: React.FC = () => {
return (
@@ -84,7 +85,7 @@ const YieldPage: React.FC = () => {
const outputAmount = Number(getOutputAmount())
const [selectedMarket, setSelectedMarket] = React.useState<
string | undefined
- >(FALLBACK_MARKET_ADDRESS)
+ >(undefined)
// market data
const { data, refetch, isFetching, isLoading } = useGraphQL(
@@ -136,20 +137,31 @@ const YieldPage: React.FC = () => {
/>
+ {/* {address ? (
+