Skip to content

Commit

Permalink
Add hooks for gnosis sexy dai interactions (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
oskarvu authored Jun 18, 2024
1 parent 9132e58 commit 94fea25
Show file tree
Hide file tree
Showing 7 changed files with 368 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { BaseUnitNumber } from '@/domain/types/NumericValues'
import { testAddresses } from '@/test/integration/constants'
import { handlers } from '@/test/integration/mockTransport'
import { setupHookRenderer } from '@/test/integration/setupHookRenderer'
import { toBigInt } from '@/utils/bigNumber'
import { waitFor } from '@testing-library/react'
import { gnosis } from 'viem/chains'
import { useSexyDaiDeposit } from './useSexyDaiDeposit'

const account = testAddresses.alice
const value = BaseUnitNumber(1)

const hookRenderer = setupHookRenderer({
hook: useSexyDaiDeposit,
account,
chain: gnosis,
handlers: [handlers.chainIdCall({ chainId: gnosis.id }), handlers.balanceCall({ balance: 0n, address: account })],
args: {
value,
},
})

describe(useSexyDaiDeposit.name, () => {
it('is not enabled for guest ', async () => {
const { result } = hookRenderer({ account: undefined })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('is not enabled for 0 value', async () => {
const { result } = hookRenderer({ args: { value: BaseUnitNumber(0) } })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('is not enabled when explicitly disabled', async () => {
const { result } = hookRenderer({ args: { enabled: false, value } })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('deposits xDAI', async () => {
const { result } = hookRenderer({
args: {
value,
},
extraHandlers: [
handlers.contractCall({
to: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'depositXDAI',
args: [account],
value: toBigInt(value),
from: account,
result: 1n,
}),
handlers.mineTransaction(),
],
})

await waitFor(() => {
expect(result.current.status.kind).toBe('ready')
})
expect((result.current as any).error).toBeUndefined()

result.current.write()

await waitFor(() => {
expect(result.current.status.kind).toBe('success')
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { toBigInt } from '@/utils/bigNumber'
import { useQueryClient } from '@tanstack/react-query'
import { gnosis } from 'viem/chains'
import { useAccount, useConfig } from 'wagmi'
import { ensureConfigTypes, useWrite } from '../hooks/useWrite'
import { BaseUnitNumber } from '../types/NumericValues'
import { balances } from '../wallet/balances'

export interface UseSexyDaiDepositArgs {
value: BaseUnitNumber
onTransactionSettled?: () => void
enabled?: boolean
}

export function useSexyDaiDeposit({
value: _value,
onTransactionSettled,
enabled: _enabled = true,
}: UseSexyDaiDepositArgs): ReturnType<typeof useWrite> {
const client = useQueryClient()
const wagmiConfig = useConfig()

const { address: receiver } = useAccount()
const value = toBigInt(_value)

const config = ensureConfigTypes({
address: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'depositXDAI',
args: [receiver!],
value,
})
const enabled = _enabled && value > 0 && !!receiver

return useWrite(
{
...config,
enabled,
},
{
onTransactionSettled: async () => {
void client.invalidateQueries({
queryKey: balances({ wagmiConfig, chainId: gnosis.id, account: receiver }).queryKey,
})

onTransactionSettled?.()
},
},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { testAddresses } from '@/test/integration/constants'
import { handlers } from '@/test/integration/mockTransport'
import { setupHookRenderer } from '@/test/integration/setupHookRenderer'
import { waitFor } from '@testing-library/react'
import { gnosis } from 'viem/chains'
import { useSexyDaiRedeemAll } from './useSexyDaiRedeemAll'

const account = testAddresses.alice

const hookRenderer = setupHookRenderer({
hook: useSexyDaiRedeemAll,
account,
chain: gnosis,
handlers: [handlers.chainIdCall({ chainId: gnosis.id }), handlers.balanceCall({ balance: 0n, address: account })],
args: {},
})

describe(useSexyDaiRedeemAll.name, () => {
it('is not enabled for guest ', async () => {
const { result } = hookRenderer({ account: undefined })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('is not enabled when explicitly disabled', async () => {
const { result } = hookRenderer({ args: { enabled: false } })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('redeems all xDAI', async () => {
const { result } = hookRenderer({
extraHandlers: [
handlers.contractCall({
to: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'redeemAllXDAI',
args: [account],
from: account,
result: 1n,
}),
handlers.mineTransaction(),
],
})

await waitFor(() => {
expect(result.current.status.kind).toBe('ready')
})
expect((result.current as any).error).toBeUndefined()

result.current.write()

await waitFor(() => {
expect(result.current.status.kind).toBe('success')
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { useQueryClient } from '@tanstack/react-query'
import { gnosis } from 'viem/chains'
import { useAccount, useConfig } from 'wagmi'
import { ensureConfigTypes, useWrite } from '../hooks/useWrite'
import { balances } from '../wallet/balances'

export interface UseSexyDaiRedeemAllArgs {
onTransactionSettled?: () => void
enabled?: boolean
}

// @note: 'redeemAllXDAI' function allows user to redeem all xDAI in exchange for all sDAI.
export function useSexyDaiRedeemAll({
onTransactionSettled,
enabled: _enabled = true,
}: UseSexyDaiRedeemAllArgs): ReturnType<typeof useWrite> {
const client = useQueryClient()
const wagmiConfig = useConfig()

const { address: receiver } = useAccount()

const config = ensureConfigTypes({
address: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'redeemAllXDAI',
args: [receiver!],
})
const enabled = _enabled && !!receiver

return useWrite(
{
...config,
enabled,
},
{
onTransactionSettled: async () => {
void client.invalidateQueries({
queryKey: balances({ wagmiConfig, chainId: gnosis.id, account: receiver }).queryKey,
})

onTransactionSettled?.()
},
},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { BaseUnitNumber } from '@/domain/types/NumericValues'
import { testAddresses } from '@/test/integration/constants'
import { handlers } from '@/test/integration/mockTransport'
import { setupHookRenderer } from '@/test/integration/setupHookRenderer'
import { toBigInt } from '@/utils/bigNumber'
import { waitFor } from '@testing-library/react'
import { gnosis } from 'viem/chains'
import { useSexyDaiWithdraw } from './useSexyDaiWithdraw'

const account = testAddresses.alice
const assetsAmount = BaseUnitNumber(1)

const hookRenderer = setupHookRenderer({
hook: useSexyDaiWithdraw,
account,
chain: gnosis,
handlers: [handlers.chainIdCall({ chainId: gnosis.id }), handlers.balanceCall({ balance: 0n, address: account })],
args: {
assetsAmount,
},
})

describe(useSexyDaiWithdraw.name, () => {
it('is not enabled for guest ', async () => {
const { result } = hookRenderer({ account: undefined })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('is not enabled for 0 assets amount', async () => {
const { result } = hookRenderer({ args: { assetsAmount: BaseUnitNumber(0) } })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('is not enabled when explicitly disabled', async () => {
const { result } = hookRenderer({ args: { enabled: false, assetsAmount } })

await waitFor(() => {
expect(result.current.status.kind).toBe('disabled')
})
})

it('withdraws xDAI', async () => {
const { result } = hookRenderer({
args: {
assetsAmount,
},
extraHandlers: [
handlers.contractCall({
to: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'withdrawXDAI',
args: [toBigInt(assetsAmount), account],
from: account,
result: 1n,
}),
handlers.mineTransaction(),
],
})

await waitFor(() => {
expect(result.current.status.kind).toBe('ready')
})
expect((result.current as any).error).toBeUndefined()

result.current.write()

await waitFor(() => {
expect(result.current.status.kind).toBe('success')
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { savingsXDaiAdapterAbi, savingsXDaiAdapterAddress } from '@/config/contracts-generated'
import { toBigInt } from '@/utils/bigNumber'
import { useQueryClient } from '@tanstack/react-query'
import { gnosis } from 'viem/chains'
import { useAccount, useConfig } from 'wagmi'
import { ensureConfigTypes, useWrite } from '../hooks/useWrite'
import { BaseUnitNumber } from '../types/NumericValues'
import { balances } from '../wallet/balances'

interface UseSexyDaiWithdrawArgs {
assetsAmount: BaseUnitNumber
onTransactionSettled?: () => void
enabled?: boolean
}

// @note: 'withdrawXDAI' function allows user to withdraw a specified amount
// of xDAI from the vault by burning the corresponding sDAI amount.
// Example: Withdraw X xDAI by burning Y sDAI (useful is one wants to withdraw exact number of xDAI)
export function useSexyDaiWithdraw({
assetsAmount,
onTransactionSettled,
enabled = true,
}: UseSexyDaiWithdrawArgs): ReturnType<typeof useWrite> {
const client = useQueryClient()
const wagmiConfig = useConfig()

const { address: receiver } = useAccount()

const config = ensureConfigTypes({
address: savingsXDaiAdapterAddress[gnosis.id],
abi: savingsXDaiAdapterAbi,
functionName: 'withdrawXDAI',
args: [toBigInt(assetsAmount), receiver!],
})

return useWrite(
{
...config,
enabled: enabled && assetsAmount.gt(0) && !!receiver,
},
{
onTransactionSettled: async () => {
void client.invalidateQueries({
queryKey: balances({ wagmiConfig, chainId: gnosis.id, account: receiver }).queryKey,
})

onTransactionSettled?.()
},
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface UseVaultRedeemArgs {

// @note: 'redeem' vault function allows user to redeem a specified
// amount of shares in exchange for the underlying asset.
// Example: Redeem X sDAI to get Y DAI (useful if one want to withdraw all DAI)
// Example: Redeem X sDAI to get Y DAI (useful if one wants to withdraw all DAI)
export function useVaultRedeem({
vault,
sharesAmount,
Expand Down

0 comments on commit 94fea25

Please sign in to comment.