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

fix: token check bug #286

Merged
merged 2 commits into from
Dec 3, 2024
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
39 changes: 39 additions & 0 deletions .github/workflows/core.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Core

on:
push:
paths: [packages/core/**]
pull_request:
paths: [packages/core/**]

permissions: read-all

jobs:
check:
defaults:
run:
working-directory: packages/core

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies
run: yarn install
working-directory: ./

- name: Lint
run: yarn lint

- name: Test
run: yarn test

- name: Build
run: yarn build
44 changes: 44 additions & 0 deletions .github/workflows/hooks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Hooks

on:
push:
paths: [packages/hooks/**]
pull_request:
paths: [packages/hooks/**]

permissions: read-all

jobs:
check:
defaults:
run:
working-directory: packages/hooks

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'

- name: Install dependencies
run: yarn install
working-directory: ./

# Core package is required for hooks to test and build
- name: Build Core
run: yarn build
working-directory: ./packages/core

- name: Lint
run: yarn lint

- name: Test
run: yarn test

- name: Build Hooks
run: yarn build
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"moment": "^2.30.1"
},
"peerDependencies": {
"starknet": ">=5.0.0"
"starknet": ">=6.8.0"
},
"devDependencies": {
"@uniswap/eslint-config": "^1.2.0",
Expand Down
19 changes: 10 additions & 9 deletions packages/core/src/constants/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
import { MultichainAddress } from 'src/types'
import { constants, json } from 'starknet'

import EkuboPositions from '../abis/EkuboPositions.json'
import JediswapPair from '../abis/JediswapPair.json'
import Multicall from '../abis/Multicall.json'

export const TOKEN_CLASS_HASH = {
export const TOKEN_CLASS_HASH: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x063ee878d3559583ceae80372c6088140e1180d9893aa65fbefc81f45ddaaa17',
[constants.StarknetChainId.SN_MAIN]: '0x063ee878d3559583ceae80372c6088140e1180d9893aa65fbefc81f45ddaaa17',
}

export const FACTORY_ADDRESSES = {
export const FACTORY_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x06b5096ba5a3c30e231e7b74ca565594d167a0a22d71cce0ebf9ae2b06584097',
[constants.StarknetChainId.SN_MAIN]: '0x01a46467a9246f45c8c340f1f155266a26a71c07bd55d36e8d1c7d0d438a2dbc',
}

export const EKUBO_POSITIONS_ADDRESSES = {
export const EKUBO_POSITIONS_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x06a2aee84bb0ed5dded4384ddd0e40e9c1372b818668375ab8e3ec08807417e5',
[constants.StarknetChainId.SN_MAIN]: '0x02e0af29598b407c8716b17f6d2795eca1b471413fa03fb145a5e33722184067',
}

export const ETH_ADDRESSES = {
export const ETH_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
[constants.StarknetChainId.SN_MAIN]: '0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7',
}
export const STRK_ADDRESSES = {
export const STRK_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',
[constants.StarknetChainId.SN_MAIN]: '0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d',
}

export const USDC_ADDRESSES = {
export const USDC_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x5a643907b9a4bc6a55e9069c4fd5fd1f5c79a22470690f75556c4736e34426',
[constants.StarknetChainId.SN_MAIN]: '0x53c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8',
}

export const MULTICALL_ADDRESSES = {
export const MULTICALL_ADDRESSES: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x01a33330996310a1e3fa1df5b16c1e07f0491fdd20c441126e02613b948f0225',
[constants.StarknetChainId.SN_MAIN]: '0x01a33330996310a1e3fa1df5b16c1e07f0491fdd20c441126e02613b948f0225',
}

export const JEDISWAP_ETH_USDC = {
export const JEDISWAP_ETH_USDC: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x05a2b2b37f66157f767ea711cb4e034c40d41f2f5acf9ff4a19049fa11c1a884',
[constants.StarknetChainId.SN_MAIN]: '0x04d0390b777b424e43839cd1e744799f3de6c176c7e32c1812a41dbd9c19db6a',
}

export const JEDISWAP_STRK_USDC = {
export const JEDISWAP_STRK_USDC: MultichainAddress = {
[constants.StarknetChainId.SN_SEPOLIA]: '0x018b129b1a372b3288077521ad8749f5a2b2ddfb67ef5a37e2d02190fa11c40f',
[constants.StarknetChainId.SN_MAIN]: '0x5726725e9507c3586cc0516449e2c74d9b201ab2747752bb0251aaa263c9a26',
}
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/types/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export type Token = {
}

export type MultichainToken = { [chainId in constants.StarknetChainId]: Token }

export type MultichainAddress = { [chainId in constants.StarknetChainId]: `0x${string}` }
7 changes: 4 additions & 3 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
"dependencies": {
"@avnu/avnu-sdk": "^2.0.0",
"@hookform/resolvers": "^3.3.2",
"@starknet-react/chains": "^0.1.0",
"@starknet-react/core": "^2.2.4",
"@tanstack/react-query": "^5.0.1",
"@starknet-io/types-js": "^0.7.10",
"@starknet-react/chains": "^3.1.0",
"@starknet-react/core": "^3.6.2",
"@tanstack/react-query": "^5.25.0",
"@types/react-dom": "^18.2.1",
"@uniswap/sdk-core": "^4.0.9",
"@vanilla-extract/css": "^1.11.0",
Expand Down
26 changes: 13 additions & 13 deletions packages/frontend/src/components/TransactionModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useContractWrite, useWaitForTransaction } from '@starknet-react/core'
import { useSendTransaction, useTransactionReceipt } from '@starknet-react/core'
import { useEffect, useMemo, useState } from 'react'
import { STARKNET_POLLING } from 'src/constants/misc'
import { useCloseModal, useTransactionModal } from 'src/hooks/useModal'
Expand All @@ -15,8 +15,8 @@ import Overlay from '../Modal/Overlay'
import Spinner from '../Spinner'
import * as styles from './style.css'

type UseWaitForTransactionResponse = Omit<ReturnType<typeof useWaitForTransaction>, 'data'> & {
data?: { finality_status?: TransactionStatus }
type UseWaitForTransactionResponse = Omit<ReturnType<typeof useTransactionReceipt>, 'data'> & {
data?: { value?: { finality_status?: TransactionStatus } }
}

export function TransactionModal() {
Expand All @@ -31,21 +31,21 @@ export function TransactionModal() {
const close = useCloseModal()

// starknet
const { writeAsync } = useContractWrite({})
const { sendAsync } = useSendTransaction({})

// calls
const [invokeTransactionDetails, resetTransaction] = useTransaction()

// transaction status
const { data, refetch } = useWaitForTransaction({
const { data, refetch } = useTransactionReceipt({
retry: true,
retryDelay: STARKNET_POLLING,
refetchInterval: STARKNET_POLLING,
hash: isOpen ? transactionHash ?? undefined : undefined,
}) as UseWaitForTransactionResponse

const statusComponent = useMemo(() => {
switch (data?.finality_status) {
switch (data?.value?.finality_status) {
// Success
case TransactionStatus.ACCEPTED_ON_L1:
case TransactionStatus.ACCEPTED_ON_L2:
Expand All @@ -69,11 +69,11 @@ export function TransactionModal() {
}

return
}, [data?.finality_status])
}, [data?.value?.finality_status])

// refetch
useEffect(() => {
if (!isOpen || (data?.finality_status && data.finality_status !== TransactionStatus.RECEIVED)) return
if (!isOpen || (data?.value?.finality_status && data.value.finality_status !== TransactionStatus.RECEIVED)) return

const intervalId = setInterval(() => {
setTransactionHash((state) => {
Expand All @@ -86,21 +86,21 @@ export function TransactionModal() {
}, STARKNET_POLLING)

return () => clearInterval(intervalId)
}, [data?.finality_status, isOpen, refetch])
}, [data?.value?.finality_status, isOpen, refetch])

// onSuccess callback
useEffect(() => {
if (accepted || !currentInvokeTransactionDetails?.onSuccess) return

switch (data?.finality_status) {
switch (data?.value?.finality_status) {
// Success
case TransactionStatus.ACCEPTED_ON_L1:
case TransactionStatus.ACCEPTED_ON_L2:
setAccepted(true)
currentInvokeTransactionDetails.onSuccess()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [accepted, data?.finality_status, currentInvokeTransactionDetails?.onSuccess])
}, [accepted, data?.value?.finality_status, currentInvokeTransactionDetails?.onSuccess])

// error component
const errorComponent = useMemo(() => {
Expand All @@ -123,7 +123,7 @@ export function TransactionModal() {
useEffect(() => {
if (!currentInvokeTransactionDetails) return

writeAsync({ calls: currentInvokeTransactionDetails.calls })
sendAsync(currentInvokeTransactionDetails.calls)
.then((res) => {
setTransactionHash(res.transaction_hash)
})
Expand All @@ -134,7 +134,7 @@ export function TransactionModal() {
})

resetTransaction()
}, [resetTransaction, currentInvokeTransactionDetails, writeAsync])
}, [resetTransaction, currentInvokeTransactionDetails, sendAsync])

// updating current invoke transaction details
useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/WalletModal/Option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ interface OptionProps {
}

function Option({ connection, activate }: OptionProps) {
const icon = connection.icon.dark
const icon = typeof connection.icon === 'string' ? connection.icon : connection.icon.dark
const isSvg = icon?.startsWith('<svg')

return (
<Row gap="12" className={styles.option} onClick={activate}>
{isSvg ? (
<Box width="32" height="32" dangerouslySetInnerHTML={{ __html: icon ?? '' }} /> /* display svg */
) : (
<Box as="img" width="32" height="32" src={connection.icon.dark} />
<Box as="img" width="32" height="32" src={icon} />
)}
<Text.Body>{connection.name}</Text.Body>
</Row>
Expand Down
12 changes: 10 additions & 2 deletions packages/frontend/src/components/Web3Provider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { argent, braavos, StarknetConfig, starkscan, useInjectedConnectors, useNetwork } from '@starknet-react/core'
import {
argent,
braavos,
Connector,
StarknetConfig,
starkscan,
useInjectedConnectors,
useNetwork,
} from '@starknet-react/core'
import { QueryClient } from '@tanstack/react-query'
import { Provider as HooksProvider } from 'hooks'
import { useMemo } from 'react'
Expand All @@ -22,7 +30,7 @@ export function StarknetProvider({ children }: React.PropsWithChildren) {
...injected,
new WebWalletConnector({ url: 'https://web.argent.xyz' }),
new ArgentMobileConnector(),
]
] as Connector[]

return (
<StarknetConfig
Expand Down
8 changes: 4 additions & 4 deletions packages/frontend/src/constants/networks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Chain, goerli, mainnet } from '@starknet-react/chains'
import { Chain, mainnet, sepolia } from '@starknet-react/chains'
import { ChainProviderFactory } from '@starknet-react/core'
import { RpcProvider } from 'starknet'

export const SUPPORTED_STARKNET_NETWORKS = [mainnet, goerli]
export const SUPPORTED_STARKNET_NETWORKS = [mainnet, sepolia]

const NETHERMIND_KEY = process.env.REACT_APP_NETHERMIND_KEY as string
if (typeof NETHERMIND_KEY === 'undefined') {
Expand All @@ -18,9 +18,9 @@ if (typeof DEFAULT_NETWORK_NAME === 'undefined') {

export const nethermindRpcProviders: ChainProviderFactory = (chain: Chain) => {
switch (chain.id) {
case goerli.id:
case sepolia.id:
return new RpcProvider({
nodeUrl: `https://rpc.nethermind.io/goerli-juno/?apikey=${NETHERMIND_KEY}`,
nodeUrl: `https://rpc.nethermind.io/sepolia-juno/?apikey=${NETHERMIND_KEY}`,
})

case mainnet.id:
Expand Down
16 changes: 9 additions & 7 deletions packages/frontend/src/hooks/useBalances.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useAccount, useContractRead, UseContractReadResult } from '@starknet-react/core'
import { useAccount, useReadContract, UseReadContractResult } from '@starknet-react/core'
import { Fraction } from '@uniswap/sdk-core'
import { Token } from 'core'
import { compiledMulticall, Entrypoint, MULTICALL_ADDRESSES } from 'core/constants'
Expand All @@ -11,7 +11,7 @@ import useChainId from './useChainId'
type Balance = Fraction
type Balances = Record<string, Balance>

interface UseBalancesResult extends Pick<UseContractReadResult, 'error' | 'refetch'> {
interface UseBalancesResult extends Pick<UseReadContractResult<any, any>, 'error' | 'refetch'> {
data?: Balances
loading: boolean
}
Expand All @@ -23,7 +23,7 @@ export default function useBalances(tokens: UseBalancesToken[]): UseBalancesResu
const { address: accountAddress } = useAccount()
const chainId = useChainId()

const res = useContractRead({
const res = useReadContract({
abi: compiledMulticall, // call is not send if abi is undefined
address: accountAddress && chainId ? MULTICALL_ADDRESSES[chainId] : undefined,
functionName: 'aggregate',
Expand All @@ -37,12 +37,14 @@ export default function useBalances(tokens: UseBalancesToken[]): UseBalancesResu
}),
),
],
}) as UseContractReadResult & { data?: [bigint, [bigint, bigint][]] }
})

const resData: [bigint, [bigint, bigint][]] | undefined = res.data

const data = useMemo(() => {
if (!res.data) return undefined
if (!resData) return undefined

return res.data[1].reduce<Record<string, Fraction>>((acc, balance, index) => {
return resData[1].reduce<Record<string, Fraction>>((acc, balance, index) => {
const token = tokens[index]
acc[token.address] = new Fraction(
uint256.uint256ToBN({ low: balance[0], high: balance[1] }).toString(),
Expand All @@ -52,7 +54,7 @@ export default function useBalances(tokens: UseBalancesToken[]): UseBalancesResu
return acc
}, {})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [res.data?.[0].toString()])
}, [resData?.[0].toString()])

return { data, loading: res.fetchStatus === 'fetching', error: res.error, refetch: res.refetch }
}
Expand Down
3 changes: 2 additions & 1 deletion packages/frontend/src/hooks/useChainId.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { starknetChainId, useNetwork } from '@starknet-react/core'
import { useMemo } from 'react'
import { constants } from 'starknet'

export default function useChainId() {
export default function useChainId(): constants.StarknetChainId | undefined {
const { chain } = useNetwork()
return useMemo(() => (chain.id ? starknetChainId(chain.id) : undefined), [chain.id])
}
Loading
Loading