Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zapper improvements #224

Merged
merged 2 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,306 changes: 1,053 additions & 253 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/components/rtoken-selector/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const availableTokensAtom = atom((get) => {
}

for (const token of owned) {
if (!tokenList[token.address]) {
if (tokenList[token.address] == null) {
tokenList[token.address] = {
address: token.address,
symbol: token.symbol,
Expand Down
1 change: 0 additions & 1 deletion src/state/chain/atoms/chainAtoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { blockDuration } from 'utils/constants'
import { formatEther } from 'viem'
import { Address, PublicClient, WalletClient } from 'wagmi'
import rtokens from '@lc-labs/rtokens'

/**
* #########################
* Chain state related atoms
Expand Down
44 changes: 34 additions & 10 deletions src/state/updater.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
import { Component } from 'react'
import RpayFeed from './rpay/RpayFeed'
import RTokenUpdater from './rtoken/updater'
import CollateralYieldUpdater from './updaters/CollateralYieldUpdater'
import PricesUpdater from './updaters/PriceUpdater'
import AccountUpdater from './wallet/updaters/AccountUpdater'
import { TokenBalancesUpdater } from './wallet/updaters/TokenBalancesUpdater'
import { useChainId } from 'wagmi'

class CatchErrors extends Component<{ children: any }> {
state = {
hasError: false,
}
constructor(props: any) {
super(props)
}
componentDidCatch() {
this.setState({ hasError: true })
}

render() {
if (this.state.hasError) {
return null
}
return <>{this.props.children}</>
}
}
/**
* Updater
*/
const Updater = () => (
<>
<PricesUpdater />
<AccountUpdater />
<RpayFeed />
<RTokenUpdater />
<CollateralYieldUpdater />
<TokenBalancesUpdater />
</>
)
const Updater = () => {
const id = useChainId()

return (
<CatchErrors key={id}>
<PricesUpdater />
<AccountUpdater />
<RpayFeed />
<RTokenUpdater />
<CollateralYieldUpdater />
<TokenBalancesUpdater />
</CatchErrors>
)
}

export default Updater
8 changes: 4 additions & 4 deletions src/state/wallet/updaters/TokenBalancesUpdater.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,23 @@ const balancesCallAtom = atom((get) => {
return undefined
}


const tokens: [Address, number][] = [
[rToken.address, rToken.decimals],
[RSR_ADDRESS[chainId], 18],
...rToken.collaterals.map((token): [Address, number] => [
token.address,
token.decimals,
]),
...zapTokens.map(i => ([i.address.address as Address, i.decimals] as [Address, number]))
...(zapTokens?.map(i => ([i.address.address as Address, i.decimals] as [Address, number]))??[])
];

if (rToken.stToken) {
tokens.push([rToken.stToken.address, rToken.stToken.decimals])
}

return {
tokens,
calls: tokens.map(([address]) => ({
tokens: tokens??[],
calls: (tokens??[]).map(([address]) => ({
address,
abi: ERC20,
functionName: 'balanceOf',
Expand All @@ -51,6 +50,7 @@ const balancesCallAtom = atom((get) => {
}
})


export const TokenBalancesUpdater = () => {
const { tokens, calls } = useAtomValue(balancesCallAtom) ?? {}
const setBalances = useSetAtom(balancesAtom)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { Divider } from 'theme-ui'
import {
approvalPending,
selectedZapTokenAtom,
zapInputString,
zapTxHash,
} from '../state/atoms'
import { approvalTxFeeAtom, ui, zapTxFeeAtom } from '../state/ui-atoms'
Expand Down
1 change: 0 additions & 1 deletion src/views/issuance/components/zap/components/ZapButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const ZapButton = (props: Partial<LoadingButtonProps>) => {
useEffect(() => {

if (ttx != null) {
console.log("Setting previous")
setPrevious(ttx)
}

Expand Down
1 change: 0 additions & 1 deletion src/views/issuance/components/zap/components/ZapInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const ZapDust = () => {
if (total.amount < 10000n) {
str = '*'
}
console.log(total.amount)

return (
<span
Expand Down
25 changes: 22 additions & 3 deletions src/views/issuance/components/zap/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import useRToken from 'hooks/useRToken'
import { useAtomValue } from 'jotai'
import mixpanel from 'mixpanel-browser'
import { Suspense, useEffect, useState } from 'react'
import { Component, Suspense, useEffect, useState } from 'react'
import { blockAtom, gasFeeAtom } from 'state/atoms'
import { Card } from 'theme-ui'
import ConfirmZap from './components/ConfirmZap'
Expand All @@ -23,6 +23,25 @@ const UpdateBlockAndGas = () => {
return null
}

class CatchErrors extends Component<{children: any}> {
state = {
hasError: false
}
constructor(props: any) {
super(props)
}
componentDidCatch() {
this.setState({ hasError: true })
}

render() {
if (this.state.hasError) {
return null
}
return <>{this.props.children}</>
}
}

/**
* Zap widget
*/
Expand All @@ -40,7 +59,7 @@ const Zap = () => {


return (
<>
<CatchErrors>
<Suspense fallback={<></>}>
<UpdateBlockAndGas />
</Suspense>
Expand All @@ -49,7 +68,7 @@ const Zap = () => {
<ZapButton onClick={handleClick} />
</Card>
{isZapping && <ConfirmZap onClose={() => setZapping(false)} />}
</>
</CatchErrors>
)
}

Expand Down
61 changes: 50 additions & 11 deletions src/views/issuance/components/zap/state/atoms.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Address, Token, Searcher } from '@reserve-protocol/token-zapper'
import { Address, Searcher, Token } from '@reserve-protocol/token-zapper'
import {
PERMIT2_ADDRESS,
PermitTransferFrom,
PermitTransferFromData,
SignatureTransfer,
} from '@uniswap/permit2-sdk'
import { atom, Getter } from 'jotai'
import { Getter, atom } from 'jotai'
import { loadable } from 'jotai/utils'
import {
balancesAtom,
Expand All @@ -16,19 +16,19 @@ import {
} from 'state/atoms'

import { defaultAbiCoder } from '@ethersproject/abi'
import { id } from '@ethersproject/hash'
import { MaxUint256 } from '@ethersproject/constants'
import { id } from '@ethersproject/hash'
import atomWithDebounce from 'utils/atoms/atomWithDebounce'
import {
atomWithOnWrite,
onlyNonNullAtom,
simplifyLoadable,
} from 'utils/atoms/utils'

import { resolvedZapState, zappableTokens } from './zapper'
import { type SearcherResult } from '@reserve-protocol/token-zapper/types/searcher/SearcherResult'
import { type ZapTransaction } from '@reserve-protocol/token-zapper/types/searcher/ZapTransaction'
import mixpanel from 'mixpanel-browser'
import { resolvedZapState, zappableTokens } from './zapper'

/**
* I've tried to keep react effects to a minimum so most async code is triggered via some signal
Expand Down Expand Up @@ -180,19 +180,58 @@ export const zapQuotePromise = loadable(
a.catch((e) => console.log(e.message))

const out = await a
console.log(out)
return out
})
)

export const zapQuote = simplifyLoadable(zapQuotePromise)

export const selectedZapTokenBalance = onlyNonNullAtom((get) => {

const approximateGasUsage: Record<string, bigint> = {
'0xa0d69e286b938e21cbf7e51d71f6a4c8918f482f': 3_000_000n,
'0xe72b141df173b999ae7c1adcbf60cc9833ce56a8': 3_000_000n,
'0xacdf0dba4b9839b96221a8487e9ca660a48212be': 6_000_000n,
'0xf2098092a5b9d25a3cc7ddc76a0553c9922eea9e': 3_000_000n,
'0x9b451beb49a03586e6995e5a93b9c745d068581e': 3_000_000n,
'0xfc0b1eef20e4c68b3dcf36c4537cfa7ce46ca70b': 3_000_000n,
'0x50249c768a6d3cb4b6565c0a2bfbdb62be94915c': 3_000_000n,
'0xcc7ff230365bd730ee4b352cc2492cedac49383e': 6_000_000n
}
export const selectedZapTokenBalance = atom((get) => {
const token = get(selectedZapTokenAtom)
if (token == null) {
return null
}
const zapState = get(resolvedZapState)
if (zapState == null) {
return null
}
const quantities = get(balancesAtom) ?? {}
const bal = quantities[token.address.address as any]?.balance ?? 0n
const fr = quantities[token.address.address as any]?.balance ?? "0"
let bal = token.from(fr)
return bal
})

return token.from(bal)
export const maxSelectedZapTokenBalance = atom((get) => {
const token = get(selectedZapTokenAtom)
if (token == null) {
return null
}
const zapState = get(resolvedZapState)
if (zapState == null) {
return null
}
const rtoken = get(rTokenAtom)
const zapTransaction = get(resolvedZapTransaction)
const quantities = get(balancesAtom) ?? {}
const fr = quantities[token.address.address as any]?.balance ?? "0"
let bal = token.from(fr)
if (token.address.address === '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') {
const a = zapState.gasPrice * (zapTransaction?.transaction.gasEstimate ?? approximateGasUsage[rtoken?.address.toLowerCase() ?? ""] ?? 2_500_000n);
bal = bal.sub(token.from(a))
bal = bal.amount < 0n ? token.zero : bal
}
return bal
})

export const approvalNeededAtom = loadable(
Expand Down Expand Up @@ -308,9 +347,9 @@ const zapTxAtom = atom(async (get) => {
permit2 =
signature != null && permit != null
? {
permit: permit.permit,
signature,
}
permit: permit.permit,
signature,
}
: undefined
}
const tx = await result.toTransaction({
Expand Down
Loading