diff --git a/next.config.js b/next.config.js index 213931d83..38daaf394 100644 --- a/next.config.js +++ b/next.config.js @@ -3,6 +3,7 @@ const nextConfig = { reactStrictMode: true, env: { NEXT_PUBLIC_ENV_TAG: process.env.NEXT_PUBLIC_ENV_TAG, + ARBITRUM_FORK_URL: process.env.ARBITRUM_FORK_URL, NEXT_PUBLIC_TENDERLY_FORK_ID: process.env.NEXT_PUBLIC_TENDERLY_FORK_ID, }, images: { diff --git a/package.json b/package.json index d58434d12..621ad6aed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chatweb3-frontend", - "version": "0.2.0", + "version": "0.2.1", "private": true, "scripts": { "dev": "next dev", @@ -21,6 +21,7 @@ "test-storybook": "test-storybook" }, "dependencies": { + "@arbitrum/sdk": "^3.1.6", "@center-inc/react": "^1.1.13", "@headlessui/react": "^1.7.15", "@heroicons/react": "^2.0.14", diff --git a/src/components/cactiComponents/ActionResponse.tsx b/src/components/cactiComponents/ActionResponse.tsx index 074139737..a337f6da7 100644 --- a/src/components/cactiComponents/ActionResponse.tsx +++ b/src/components/cactiComponents/ActionResponse.tsx @@ -5,9 +5,9 @@ import { AddressZero } from '@ethersproject/constants'; import { CheckCircleIcon, ExclamationTriangleIcon } from '@heroicons/react/24/outline'; import { ConnectButton } from '@rainbow-me/rainbowkit'; import { BigNumber, UnsignedTransaction } from 'ethers'; -import { formatUnits } from 'ethers/lib/utils.js'; +import { formatEther, formatUnits } from 'ethers/lib/utils.js'; import tw from 'tailwind-styled-components'; -import { useAccount } from 'wagmi'; +import { useAccount, useNetwork, useSwitchNetwork } from 'wagmi'; import useToken from '@/hooks/useToken'; import { cleanValue } from '@/utils'; import { ActionStepper } from './ActionStepper'; @@ -60,6 +60,7 @@ export type ActionResponseProps = { stepper?: boolean; onSuccess?: (receipt?: TransactionReceipt) => void; onError?: (receipt?: TransactionReceipt) => void; + chainId?: number; }; /** @@ -77,8 +78,13 @@ export const ActionResponse = ({ skipBalanceCheck, onSuccess, onError, + chainId = 1, }: ActionResponseProps) => { const { address } = useAccount(); + const { chain } = useNetwork(); + const { chains, switchNetworkAsync } = useSwitchNetwork(); + const wrongChain = !!chainId && chain?.id !== chainId; + const _approvalParams = useMemo( () => approvalParams || { @@ -138,17 +144,17 @@ export const ActionResponse = ({ // explicitly showing approvalParams === undefined for clarity - as oppposed to !approvalParams if (_approvalParams === undefined) return setHasEnoughBalance(true); - if (sendParams?.value! >= ethBal!) { + if (BigNumber.from(sendParams?.value || '0').gt(BigNumber.from(ethBal || '0'))) return setHasEnoughBalance(false); - } // check approval token balance - if (balance && _approvalParams?.approvalAmount) + if (balance && _approvalParams?.approvalAmount) { setHasEnoughBalance(balance.gte(_approvalParams.approvalAmount)); + } }, [_approvalParams, balance, ethBal, sendParams?.value, skipBalanceCheck]); /** - * BUTTON FLOW: + * BUTTON FLOW for approvals and transactions: * Update all the local states on tx/approval status changes. **/ useEffect(() => { @@ -251,8 +257,26 @@ export const ActionResponse = ({ submitTx, token?.symbol, disabled, + wrongChain, + chains, + switchNetworkAsync, + chainId, ]); + // handle chain changes if on the wrong chain + useEffect(() => { + if (!wrongChain) return; + + const correctChainName = chains.find((c) => c.id === chainId)?.name; + setButtonLabel( + correctChainName && switchNetworkAsync ? `Switch to ${correctChainName}` : `Unsupported Chain` + ); + return ( + switchNetworkAsync && + setAction({ name: 'switch', fn: async () => await switchNetworkAsync(chainId) }) + ); + }, [chainId, chains, state, switchNetworkAsync, wrongChain]); + /* Set the styling based on the state (Note: always diasbled if 'disabled' from props) */ const extraStyle = stylingByState[disabled ? ActionResponseState.DISABLED : state]; diff --git a/src/components/current/CactiImages/Cacti_alt.png b/src/components/current/CactiImages/Cacti_alt.png index 3f97c661a..05bdb6e76 100644 Binary files a/src/components/current/CactiImages/Cacti_alt.png and b/src/components/current/CactiImages/Cacti_alt.png differ diff --git a/src/components/current/CactiImages/Cactus1.tsx b/src/components/current/CactiImages/Cactus1.tsx index 34b7167c0..fdbb69b09 100644 --- a/src/components/current/CactiImages/Cactus1.tsx +++ b/src/components/current/CactiImages/Cactus1.tsx @@ -2,86 +2,90 @@ import * as React from 'react'; const Cactus1 = (props: any) => ( - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + diff --git a/src/components/current/CactiImages/Cactus2.tsx b/src/components/current/CactiImages/Cactus2.tsx index 6036ddcf3..b5345fbde 100644 --- a/src/components/current/CactiImages/Cactus2.tsx +++ b/src/components/current/CactiImages/Cactus2.tsx @@ -2,85 +2,90 @@ import * as React from 'react'; const Cactus2 = (props: any) => ( - + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + diff --git a/src/components/current/CactiImages/Cactus3.tsx b/src/components/current/CactiImages/Cactus3.tsx index 43b6a3bc0..bf3337c7c 100644 --- a/src/components/current/CactiImages/Cactus3.tsx +++ b/src/components/current/CactiImages/Cactus3.tsx @@ -2,84 +2,126 @@ import * as React from 'react'; const Cactus3 = (props: any) => ( - - - - + + + + + + + + + + + - + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + diff --git a/src/components/current/MessageTranslator.tsx b/src/components/current/MessageTranslator.tsx index bc8772bda..4e0eb14e4 100644 --- a/src/components/current/MessageTranslator.tsx +++ b/src/components/current/MessageTranslator.tsx @@ -5,6 +5,8 @@ import { parseMessage } from '@/utils/parse-message'; import { ErrorResponse, TextResponse } from '../cactiComponents'; import { ImageVariant } from '../cactiComponents/ImageResponse'; import { TableResponse } from '../cactiComponents/TableResponse'; +import ArbitrumDeposit from '../experimental_/widgets/arbitrum/ArbitrumDeposit'; +import ArbitrumWithdraw from '../experimental_/widgets/arbitrum/ArbitrumWithdraw'; import { Widgetize } from '../legacy/legacyComponents/MessageTranslator'; import Avatar from '../shared/Avatar'; import { FeedbackButton } from './FeedbackButton'; @@ -186,6 +188,8 @@ export const Widget = (props: WidgetProps) => { tokenInSymbol={parsedArgs[0]} tokenOutSymbol={parsedArgs[1]} inputAmount={parsedArgs[3]} + transactionKeyword={parsedArgs[2]} // BUYAMOUNT or SELLAMOUNT + slippage={parsedArgs[4]} /> ); @@ -228,7 +232,6 @@ export const Widget = (props: WidgetProps) => { assetsToShow={6} /> ); - widgets.set( 'yield-protocol-lend', { 'zksync-deposit', ); - widgets.set( 'zksync-withdraw', ); - widgets.set('stake-sfrxeth', ); widgets.set( 'liquity-borrow', ); widgets.set('liquity-close', ); - widgets.set('deposit-eth-lido', ); widgets.set('withdraw-eth-lido', ); - widgets.set('deposit-eth-reth', ); widgets.set('withdraw-eth-reth', ); + widgets.set('stake-sfrxeth', ); widgets.set('savings-dai-deposit', ); @@ -323,6 +323,15 @@ export const Widget = (props: WidgetProps) => { /> ); + widgets.set( + 'arbitrum-deposit', + + ); + widgets.set( + 'arbitrum-withdraw', + + ); + /* If available, return the widget in the widgets map */ if (widgets.has(fnName)) { return widgets.get(fnName)!; diff --git a/src/components/current/WelcomeMessage.tsx b/src/components/current/WelcomeMessage.tsx index 4d089894b..df6e7ae6c 100644 --- a/src/components/current/WelcomeMessage.tsx +++ b/src/components/current/WelcomeMessage.tsx @@ -35,11 +35,17 @@ const WelcomeMessage = () => { return (
- CactiChat +
+
+ CactiChat +
+
- +
+ +
Explore NFTs sendMessage('Browse some cheetah nft collections')}> Browse some [cheetah] NFT collections @@ -53,7 +59,9 @@ const WelcomeMessage = () => {
- +
+ +
Interact with protocols sendMessage('Swap 0.1 ETH for DAI on Uniswap')}> Swap 0.1 ETH for DAI on Uniswap @@ -69,7 +77,9 @@ const WelcomeMessage = () => {
- +
+ +
{/* */} Query the Network sendMessage('What is the price of ETH in terms of USD')}> diff --git a/src/components/current/widgets/hop/HopBridge.tsx b/src/components/current/widgets/hop/HopBridge.tsx index 03a673445..80d67cc43 100644 --- a/src/components/current/widgets/hop/HopBridge.tsx +++ b/src/components/current/widgets/hop/HopBridge.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import { Hop } from '@hop-protocol/sdk'; +import { config } from '@hop-protocol/sdk/dist/src/config'; import { CanonicalToken, ChainSlug } from '@hop-protocol/sdk/dist/src/constants'; import { Interface, UnsignedTransaction } from 'ethers/lib/utils'; import { erc20ABI } from 'wagmi'; @@ -100,6 +101,10 @@ const HopBridge = ({ inputString, tokenSymbol, toChain, fromChain }: HopBridgePr })(); }, [_fromChain, input?.value, _toChain, tokenIn?.address, tokenSymbol]); // TODO signer is causing infinite loop + // find the chain id of the from chain using the hop sdk config + // using the `fromSlug`(returns the Chain) property of Chain doesn't return the chain id, so using the below methodology instead + const fromChainId = config.chains.mainnet[_fromChain].chainId as number | undefined; + return ( <> ); diff --git a/src/components/current/widgets/uniswap/Uniswap.tsx b/src/components/current/widgets/uniswap/Uniswap.tsx index 698d2fc15..40232b841 100644 --- a/src/components/current/widgets/uniswap/Uniswap.tsx +++ b/src/components/current/widgets/uniswap/Uniswap.tsx @@ -25,10 +25,13 @@ interface UniswapProps { tokenInSymbol: string; tokenOutSymbol: string; inputAmount: string; + slippage: string; + transactionKeyword: 'BUYAMOUNT' | 'SELLAMOUNT'; } -const Uniswap = ({ tokenInSymbol, tokenOutSymbol, inputAmount }: UniswapProps) => { +const Uniswap = ({ tokenInSymbol, tokenOutSymbol, inputAmount, slippage, transactionKeyword }: UniswapProps) => { const chainId = useChainId(); + const isBuying = transactionKeyword === 'BUYAMOUNT'; const { address: recipient } = useAccount(); const { data: tokenIn, isETH: tokenInIsETH } = useToken(tokenInSymbol); @@ -36,10 +39,12 @@ const Uniswap = ({ tokenInSymbol, tokenOutSymbol, inputAmount }: UniswapProps) = const { data: tokenInChecked } = useToken(tokenInIsETH ? 'WETH' : tokenInSymbol); const { data: tokenOutChecked } = useToken(tokenOutIsETH ? 'WETH' : tokenOutSymbol); const input = useInput(inputAmount, tokenInChecked?.symbol!); - const slippage = 2.0; // in percentage terms + + const slippage_ = +slippage || 0.5; // in percentage terms + const getSlippageAdjustedAmount = (amount: BigNumber) => BigNumber.from(amount) - .mul(10000 - slippage * 100) + .mul(10000 - slippage_ * 100) .div(10000); // token out quote for amount in @@ -250,7 +255,7 @@ const Uniswap = ({ tokenInSymbol, tokenOutSymbol, inputAmount }: UniswapProps) = { + const l1Provider = useProvider({ chainId: 1 }); + const l2Provider = useProvider({ chainId: L2_CHAIN_ID }); + const { data: token, isETH } = useToken(tokenSymbol.toUpperCase()); + const { address: account } = useAccount(); + const amount = useInput(amtString, token?.symbol!); + + const [erc20ApprovalParams, setErc20ApprovalParams] = useState(); + const [erc20SendParams, setErc20SendParams] = useState(); + const [error, setError] = useState(''); + + const { data: depositEth } = usePrepareContractWrite({ + address: INBOX_CONTRACT_ADDRESS, + abi: Inbox, + functionName: 'depositEth', + overrides: { value: amount?.value }, + enabled: isETH, + }); + + // handle erc20 (wip) + useEffect(() => { + (async () => { + if (isETH) return; + if (!l1Provider) return setError('No L1 provider detected'); + if (!l2Provider) return setError('No L2 provider detected'); + if (!token?.address) return setError('No token address detected'); + if (!amount?.value) return setError('No amount detected'); + if (!account) return setError('No account detected'); + + const arbitrumOne = await getL2Network( + L2_CHAIN_ID /** <-- chain id of target Arbitrum chain */ + ); + + const erc20Bridger = new Erc20Bridger(arbitrumOne); + + // get approval params + try { + const { data } = await erc20Bridger.getApproveTokenRequest({ + l1Provider, + erc20L1Address: token.address, + amount: amount.value, + }); + + // get the spender address + const iface = new Interface(erc20ABI); + const parsed = iface.parseTransaction({ data: data.toString() }); + const spender = parsed.args[0]; + + setErc20ApprovalParams({ + approvalAmount: amount.value, + tokenAddress: token.address, + spender, + skipApproval: false, + }); + } catch (error) { + console.error(error); + setError('There was an error initiating the transaction'); + } + + try { + // get the send params + const req = await erc20Bridger.getDepositRequest({ + l1Provider, + l2Provider, + erc20L1Address: token.address, + amount: amount.value, + from: account, + }); + + setErc20SendParams(req.txRequest); + } catch (error) { + console.error(error); + setError('There was an error initiating the transaction'); + } + })(); + }, [account, amount?.value, isETH, l1Provider, l2Provider, token?.address]); + + const sendParams = useMemo( + () => (isETH ? depositEth?.request : erc20SendParams), + [depositEth?.request, erc20SendParams, isETH] + ); + + return ( + <> + + + + ); +}; + +export default ArbitrumDeposit; diff --git a/src/components/experimental_/widgets/arbitrum/ArbitrumWithdraw.tsx b/src/components/experimental_/widgets/arbitrum/ArbitrumWithdraw.tsx new file mode 100644 index 000000000..7a8167218 --- /dev/null +++ b/src/components/experimental_/widgets/arbitrum/ArbitrumWithdraw.tsx @@ -0,0 +1,88 @@ +import { useEffect, useMemo, useState } from 'react'; +import { Erc20Bridger, getL1Network, getL2Network } from '@arbitrum/sdk'; +import { UnsignedTransaction } from 'ethers'; +import { useAccount, usePrepareContractWrite, useProvider } from 'wagmi'; +import { ActionResponse, HeaderResponse } from '@/components/cactiComponents'; +import { ApprovalBasicParams } from '@/components/cactiComponents/hooks/useApproval'; +import useInput from '@/hooks/useInput'; +import useToken from '@/hooks/useToken'; +import { L2_CHAIN_ID } from './ArbitrumDeposit'; +import ArbSys from './abi/ArbSys'; + +interface ArbitrumWithdrawProps { + tokenSymbol: string; + amtString: string; +} + +const ARBSYS_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000064'; + +const ArbitrumWithdraw = ({ tokenSymbol, amtString }: ArbitrumWithdrawProps) => { + const l1Provider = useProvider({ chainId: 1 }); + const l2Provider = useProvider({ chainId: L2_CHAIN_ID }); + const { data: token, isETH } = useToken(tokenSymbol); + const amount = useInput(amtString, token?.symbol!); + const { address: account } = useAccount(); + const [erc20ApprovalParams, setErc20ApprovalParams] = useState(); + const [erc20SendParams, setErc20SendParams] = useState(); + + const { data: withdrawEth } = usePrepareContractWrite({ + address: ARBSYS_CONTRACT_ADDRESS, + abi: ArbSys, + functionName: 'withdrawEth', + args: [account!], + overrides: { value: amount?.value }, + }); + + // handle erc20 withdraw + useEffect(() => { + (async () => { + if (isETH) return; + if (!token?.address) return; + if (!amount?.value) return; + if (!account) return; + + const arbitrumOne = await getL2Network(L2_CHAIN_ID /** <-- chain id of Arbitrum chain */); + + const erc20Bridger = new Erc20Bridger(arbitrumOne); + + try { + const req = await erc20Bridger.getWithdrawalRequest({ + erc20l1Address: token.address, + amount: amount.value, + destinationAddress: account, + from: account, + }); + + setErc20SendParams(req.txRequest); + } catch (e) { + console.error(e); + console.error('Error initiating transaction'); + } + })(); + }, [account, amount?.value, isETH, token?.address]); + + if (!token) <>token not supported; + if (!amount?.value) <>amount specified is invalid; + + const sendParams = useMemo( + () => (isETH ? withdrawEth?.request : erc20SendParams), + [erc20SendParams, isETH, withdrawEth?.request] + ); + + return ( + <> + + + + ); +}; + +export default ArbitrumWithdraw; diff --git a/src/components/experimental_/widgets/arbitrum/abi/ArbSys.ts b/src/components/experimental_/widgets/arbitrum/abi/ArbSys.ts new file mode 100644 index 000000000..b55417ab1 --- /dev/null +++ b/src/components/experimental_/widgets/arbitrum/abi/ArbSys.ts @@ -0,0 +1,249 @@ +export default [ + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: 'caller', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'destination', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'uniqueId', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint256', + name: 'batchNumber', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'indexInBatch', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'arbBlockNum', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'ethBlockNum', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'timestamp', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'callvalue', + type: 'uint256', + }, + { + indexed: false, + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + ], + name: 'L2ToL1Transaction', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: 'caller', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'destination', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: 'hash', + type: 'uint256', + }, + { + indexed: true, + internalType: 'uint256', + name: 'position', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'arbBlockNum', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'ethBlockNum', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'timestamp', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: 'callvalue', + type: 'uint256', + }, + { + indexed: false, + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + ], + name: 'L2ToL1Tx', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'uint256', + name: 'reserved', + type: 'uint256', + }, + { + indexed: true, + internalType: 'bytes32', + name: 'hash', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'uint256', + name: 'position', + type: 'uint256', + }, + ], + name: 'SendMerkleUpdate', + type: 'event', + }, + { + inputs: [{ internalType: 'uint256', name: 'arbBlockNum', type: 'uint256' }], + name: 'arbBlockHash', + outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'arbBlockNumber', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'arbChainID', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'arbOSVersion', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getStorageGasAvailable', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'isTopLevelCall', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'unused', type: 'address' }, + ], + name: 'mapL1SenderContractAddressToL2Alias', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'pure', + type: 'function', + }, + { + inputs: [], + name: 'myCallersAddressWithoutAliasing', + outputs: [{ internalType: 'address', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'sendMerkleTreeState', + outputs: [ + { internalType: 'uint256', name: 'size', type: 'uint256' }, + { internalType: 'bytes32', name: 'root', type: 'bytes32' }, + { internalType: 'bytes32[]', name: 'partials', type: 'bytes32[]' }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'destination', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendTxToL1', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'wasMyCallersAddressAliased', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: 'destination', type: 'address' }], + name: 'withdrawEth', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/src/components/experimental_/widgets/arbitrum/abi/Inbox.ts b/src/components/experimental_/widgets/arbitrum/abi/Inbox.ts new file mode 100644 index 000000000..3180aa672 --- /dev/null +++ b/src/components/experimental_/widgets/arbitrum/abi/Inbox.ts @@ -0,0 +1,375 @@ +export default [ + { + inputs: [ + { internalType: 'uint256', name: 'dataLength', type: 'uint256' }, + { internalType: 'uint256', name: 'maxDataLength', type: 'uint256' }, + ], + name: 'DataTooLarge', + type: 'error', + }, + { inputs: [], name: 'GasLimitTooLarge', type: 'error' }, + { + inputs: [ + { internalType: 'uint256', name: 'expected', type: 'uint256' }, + { internalType: 'uint256', name: 'actual', type: 'uint256' }, + ], + name: 'InsufficientSubmissionCost', + type: 'error', + }, + { + inputs: [ + { internalType: 'uint256', name: 'expected', type: 'uint256' }, + { internalType: 'uint256', name: 'actual', type: 'uint256' }, + ], + name: 'InsufficientValue', + type: 'error', + }, + { inputs: [], name: 'L1Forked', type: 'error' }, + { + inputs: [{ internalType: 'address', name: 'origin', type: 'address' }], + name: 'NotAllowedOrigin', + type: 'error', + }, + { inputs: [], name: 'NotForked', type: 'error' }, + { inputs: [], name: 'NotOrigin', type: 'error' }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'NotOwner', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'sender', type: 'address' }, + { internalType: 'address', name: 'rollup', type: 'address' }, + { internalType: 'address', name: 'owner', type: 'address' }, + ], + name: 'NotRollupOrOwner', + type: 'error', + }, + { + inputs: [ + { internalType: 'address', name: 'from', type: 'address' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'l2CallValue', type: 'uint256' }, + { internalType: 'uint256', name: 'deposit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxSubmissionCost', type: 'uint256' }, + { internalType: 'address', name: 'excessFeeRefundAddress', type: 'address' }, + { internalType: 'address', name: 'callValueRefundAddress', type: 'address' }, + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'RetryableData', + type: 'error', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'address', name: 'user', type: 'address' }, + { indexed: false, internalType: 'bool', name: 'val', type: 'bool' }, + ], + name: 'AllowListAddressSet', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'bool', name: 'isEnabled', type: 'bool' }], + name: 'AllowListEnabledUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: 'uint256', name: 'messageNum', type: 'uint256' }, + { indexed: false, internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'InboxMessageDelivered', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: true, internalType: 'uint256', name: 'messageNum', type: 'uint256' }], + name: 'InboxMessageDeliveredFromOrigin', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Paused', + type: 'event', + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: 'address', name: 'account', type: 'address' }], + name: 'Unpaused', + type: 'event', + }, + { + inputs: [], + name: 'allowListEnabled', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'bridge', + outputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'dataLength', type: 'uint256' }, + { internalType: 'uint256', name: 'baseFee', type: 'uint256' }, + ], + name: 'calculateRetryableSubmissionFee', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'l2CallValue', type: 'uint256' }, + { internalType: 'uint256', name: 'maxSubmissionCost', type: 'uint256' }, + { internalType: 'address', name: 'excessFeeRefundAddress', type: 'address' }, + { internalType: 'address', name: 'callValueRefundAddress', type: 'address' }, + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'createRetryableTicket', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'l2CallValue', type: 'uint256' }, + { internalType: 'uint256', name: 'maxSubmissionCost', type: 'uint256' }, + { internalType: 'address', name: 'excessFeeRefundAddress', type: 'address' }, + { internalType: 'address', name: 'callValueRefundAddress', type: 'address' }, + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'createRetryableTicketNoRefundAliasRewrite', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'depositEth', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [], + name: 'depositEth', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { internalType: 'contract IBridge', name: '_bridge', type: 'address' }, + { internalType: 'contract ISequencerInbox', name: '_sequencerInbox', type: 'address' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'isAllowed', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { inputs: [], name: 'pause', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [], + name: 'paused', + outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [{ internalType: 'contract IBridge', name: '', type: 'address' }], + name: 'postUpgradeInit', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendContractTransaction', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendL1FundedContractTransaction', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendL1FundedUnsignedTransaction', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendL1FundedUnsignedTransactionToFork', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes', name: 'messageData', type: 'bytes' }], + name: 'sendL2Message', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bytes', name: 'messageData', type: 'bytes' }], + name: 'sendL2MessageFromOrigin', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendUnsignedTransaction', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'sendUnsignedTransactionToFork', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'uint256', name: 'nonce', type: 'uint256' }, + { internalType: 'uint256', name: 'value', type: 'uint256' }, + { internalType: 'address', name: 'withdrawTo', type: 'address' }, + ], + name: 'sendWithdrawEthToFork', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'sequencerInbox', + outputs: [{ internalType: 'contract ISequencerInbox', name: '', type: 'address' }], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { internalType: 'address[]', name: 'user', type: 'address[]' }, + { internalType: 'bool[]', name: 'val', type: 'bool[]' }, + ], + name: 'setAllowList', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [{ internalType: 'bool', name: '_allowListEnabled', type: 'bool' }], + name: 'setAllowListEnabled', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'l2CallValue', type: 'uint256' }, + { internalType: 'uint256', name: 'maxSubmissionCost', type: 'uint256' }, + { internalType: 'address', name: 'excessFeeRefundAddress', type: 'address' }, + { internalType: 'address', name: 'callValueRefundAddress', type: 'address' }, + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'uniswapCreateRetryableTicket', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, + { inputs: [], name: 'unpause', outputs: [], stateMutability: 'nonpayable', type: 'function' }, + { + inputs: [ + { internalType: 'address', name: 'to', type: 'address' }, + { internalType: 'uint256', name: 'l2CallValue', type: 'uint256' }, + { internalType: 'uint256', name: 'maxSubmissionCost', type: 'uint256' }, + { internalType: 'address', name: 'excessFeeRefundAddress', type: 'address' }, + { internalType: 'address', name: 'callValueRefundAddress', type: 'address' }, + { internalType: 'uint256', name: 'gasLimit', type: 'uint256' }, + { internalType: 'uint256', name: 'maxFeePerGas', type: 'uint256' }, + { internalType: 'bytes', name: 'data', type: 'bytes' }, + ], + name: 'unsafeCreateRetryableTicket', + outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + stateMutability: 'payable', + type: 'function', + }, +] as const; diff --git a/src/contexts/ConnectionWrapper.tsx b/src/contexts/ConnectionWrapper.tsx index 4f4948b10..4b0ef5254 100644 --- a/src/contexts/ConnectionWrapper.tsx +++ b/src/contexts/ConnectionWrapper.tsx @@ -11,8 +11,9 @@ import { lightTheme, } from '@rainbow-me/rainbowkit'; import axios from 'axios'; -import { Chain, WagmiConfig, configureChains, createClient, mainnet, useEnsAvatar } from 'wagmi'; -import { goerli, zkSyncTestnet } from 'wagmi/chains'; + +import { Chain, WagmiConfig, configureChains, createClient, useEnsAvatar } from 'wagmi'; +import { arbitrum, goerli, zkSyncTestnet } from 'wagmi/chains'; import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'; import { publicProvider } from 'wagmi/providers/public'; import useCachedState from '@/hooks/useCachedState'; @@ -49,8 +50,17 @@ const ConnectionWrapper = ({ children, useSiwe = true }: any) => { }, } as Chain; + const arbitrumFork = { + ...arbitrum, + name: 'Arbitrum One Fork', + rpcUrls: { + public: { http: [arbitrum.rpcUrls.public.http[0]] }, + default: { http: [process.env.ARBITRUM_FORK_URL] }, + }, + } as Chain; + const { chains, provider } = configureChains( - [mainnet], + [mainnetFork, goerli, zkSyncTestnet, arbitrumFork], [publicProvider()] ); diff --git a/src/hooks/useInput.ts b/src/hooks/useInput.ts index 9c7200192..91a8d267f 100644 --- a/src/hooks/useInput.ts +++ b/src/hooks/useInput.ts @@ -16,7 +16,7 @@ type Input = { * @param input * @param tokenSymbol * @param transform - * @returns {Input} + * @returns {Input | undefined} */ const useInput = ( input: string, diff --git a/src/hooks/useToken.tsx b/src/hooks/useToken.tsx index 9c0e083e6..574f4f99a 100644 --- a/src/hooks/useToken.tsx +++ b/src/hooks/useToken.tsx @@ -20,13 +20,13 @@ const useToken = (tokenSymbol?: string, tokenAddress?: Address) => { return { address: ethers.constants.AddressZero, symbol: 'ETH', + name: 'Ether', decimals: 18, logoURI: 'https://storage.googleapis.com/zapper-fi-assets/tokens/ethereum/0x0000000000000000000000000000000000000000.png', - name: 'Ether', } as Token; - if (tokenSymbol) return findTokenBySymbol(tokenSymbol, chainId) as Token; - if (tokenAddress) return findTokenByAddress(tokenAddress, chainId) as Token; + if (tokenSymbol) return findTokenBySymbol(tokenSymbol, chainId); + if (tokenAddress) return findTokenByAddress(tokenAddress, chainId); return undefined; }, [chainId, getTokenIsETH] diff --git a/src/utils/index.tsx b/src/utils/index.tsx index b1c307296..ae6b14bac 100644 --- a/src/utils/index.tsx +++ b/src/utils/index.tsx @@ -1,18 +1,18 @@ import { utils } from 'ethers'; import projectListJson from '@/utils/ProjectList.json'; import tokenListJson from '@/utils/TokenList.json'; -import { Project } from '../types'; +import { Project, Token } from '../types'; export const shortenAddress = (address: string) => address.slice(0, 6) + '...' + address.slice(-4); export const findTokenBySymbol = (symbol: string, chainId: number) => tokenListJson.tokens.find( (token) => token.symbol.toUpperCase() === symbol.toUpperCase() && token.chainId === chainId - ); + ) as Token | undefined; export const findTokenByAddress = (address: string, chainId: number) => tokenListJson.tokens.find( (token) => token.address.toLowerCase() === address.toLowerCase() && token.chainId === chainId - ); + ) as Token | undefined; export const formatToEther = (amount: string) => utils.formatEther(amount); export const formatToWei = (amount: string) => utils.parseEther(amount).toString(); diff --git a/yarn.lock b/yarn.lock index e349a3b98..945ee2829 100644 --- a/yarn.lock +++ b/yarn.lock @@ -36,6 +36,18 @@ __metadata: languageName: node linkType: hard +"@arbitrum/sdk@npm:^3.1.6": + version: 3.1.10 + resolution: "@arbitrum/sdk@npm:3.1.10" + dependencies: + "@ethersproject/address": ^5.0.8 + "@ethersproject/bignumber": ^5.1.1 + "@ethersproject/bytes": ^5.0.8 + ethers: ^5.1.0 + checksum: 3a96289cd1a91be6be1233ae91f2cfb739a15d9ac399a478522dcc3184166699ded7ff8c28428e355f9e51deb1ebcf2f20f2999d80a055f841ce55826408f3e5 + languageName: node + linkType: hard + "@aw-web-design/x-default-browser@npm:1.4.126": version: 1.4.126 resolution: "@aw-web-design/x-default-browser@npm:1.4.126" @@ -1909,9 +1921,9 @@ __metadata: linkType: hard "@eslint-community/regexpp@npm:^4.6.1": - version: 4.8.0 - resolution: "@eslint-community/regexpp@npm:4.8.0" - checksum: 601e6d033d556e98e8c929905bef335f20d7389762812df4d0f709d9b4d2631610dda975fb272e23b5b68e24a163b3851b114c8080a0a19fb4c141a1eff6305b + version: 4.8.1 + resolution: "@eslint-community/regexpp@npm:4.8.1" + checksum: 82d62c845ef42b810f268cfdc84d803a2da01735fb52e902fd34bdc09f92464a094fd8e4802839874b000b2f73f67c972859e813ba705233515d3e954f234bf2 languageName: node linkType: hard @@ -2082,7 +2094,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:^5.0.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.0.8, @ethersproject/address@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -2125,7 +2137,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:^5.1.1, @ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -2136,7 +2148,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.0.9, @ethersproject/bytes@npm:^5.5.0, @ethersproject/bytes@npm:^5.7.0": +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:^5.0.8, @ethersproject/bytes@npm:^5.0.9, @ethersproject/bytes@npm:^5.5.0, @ethersproject/bytes@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bytes@npm:5.7.0" dependencies: @@ -2709,17 +2721,17 @@ __metadata: languageName: node linkType: hard -"@jest/console@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/console@npm:29.6.4" +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/node": "*" chalk: ^4.0.0 - jest-message-util: ^29.6.3 - jest-util: ^29.6.3 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 slash: ^3.0.0 - checksum: 1caf061a39266b86e96ca13358401839e4d930742cbaa9e87e79d7ce170a83195e52e5b2d22eb5aa9a949219b61a163a81e337ec98b8323d88d79853051df96c + checksum: 0e3624e32c5a8e7361e889db70b170876401b7d70f509a2538c31d5cd50deb0c1ae4b92dc63fe18a0902e0a48c590c21d53787a0df41a52b34fa7cab96c384d6 languageName: node linkType: hard @@ -2900,15 +2912,15 @@ __metadata: languageName: node linkType: hard -"@jest/test-result@npm:^29.6.4": - version: 29.6.4 - resolution: "@jest/test-result@npm:29.6.4" +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" dependencies: - "@jest/console": ^29.6.4 + "@jest/console": ^29.7.0 "@jest/types": ^29.6.3 "@types/istanbul-lib-coverage": ^2.0.0 collect-v8-coverage: ^1.0.0 - checksum: a13c82d29038e80059191a1a443240678c6934ea832fdabaec12b3ece397b6303022a064494a6bbd167a024f04e6b4d9ace1001300927ff70405ec9d854f1193 + checksum: 67b6317d526e335212e5da0e768e3b8ab8a53df110361b80761353ad23b6aea4432b7c5665bdeb87658ea373b90fb1afe02ed3611ef6c858c7fba377505057fa languageName: node linkType: hard @@ -2948,8 +2960,8 @@ __metadata: linkType: hard "@jest/transform@npm:^29.3.1": - version: 29.6.4 - resolution: "@jest/transform@npm:29.6.4" + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" dependencies: "@babel/core": ^7.11.6 "@jest/types": ^29.6.3 @@ -2959,14 +2971,14 @@ __metadata: convert-source-map: ^2.0.0 fast-json-stable-stringify: ^2.1.0 graceful-fs: ^4.2.9 - jest-haste-map: ^29.6.4 + jest-haste-map: ^29.7.0 jest-regex-util: ^29.6.3 - jest-util: ^29.6.3 + jest-util: ^29.7.0 micromatch: ^4.0.4 pirates: ^4.0.4 slash: ^3.0.0 write-file-atomic: ^4.0.2 - checksum: 0341a200a0bb926fc67ab9aede91c7b4009458206495e92057e72a115c55da5fed117457e68c6ea821e24c58b55da75c6a7b0f272ed63c2693db583d689a3383 + checksum: 0f8ac9f413903b3cb6d240102db848f2a354f63971ab885833799a9964999dd51c388162106a807f810071f864302cdd8e3f0c241c29ce02d85a36f18f3f40ab languageName: node linkType: hard @@ -4367,8 +4379,8 @@ __metadata: linkType: hard "@solana/web3.js@npm:^1.70.1": - version: 1.78.4 - resolution: "@solana/web3.js@npm:1.78.4" + version: 1.78.5 + resolution: "@solana/web3.js@npm:1.78.5" dependencies: "@babel/runtime": ^7.22.6 "@noble/curves": ^1.0.0 @@ -4385,7 +4397,7 @@ __metadata: node-fetch: ^2.6.12 rpc-websockets: ^7.5.1 superstruct: ^0.14.2 - checksum: e1c44c6cbec87cdfd4d6d23b4241b746e14ed3a9ca73d596693758d91ac825cecf579345da3b0b7bb5e54b6794791bc0eac02cadf11f1ec79e859b6536f26f11 + checksum: 66fe4ddcc073d0c539e23a2aae3ba23c081a11f5ebc8216dd18e0c6770f20e419c635a50529faa59baeec9722cd521a3502abc7cdf3b3d5f31b32066e0415c24 languageName: node linkType: hard @@ -6579,9 +6591,9 @@ __metadata: linkType: hard "@types/trusted-types@npm:^2.0.2": - version: 2.0.3 - resolution: "@types/trusted-types@npm:2.0.3" - checksum: 4794804bc4a4a173d589841b6d26cf455ff5dc4f3e704e847de7d65d215f2e7043d8757e4741ce3a823af3f08260a8d04a1a6e9c5ec9b20b7b04586956a6b005 + version: 2.0.4 + resolution: "@types/trusted-types@npm:2.0.4" + checksum: 5256c4576cd1c90d33ddd9cc9cbd4f202b39c98cbe8b7f74963298f9eb2159c285ea5c25a6181b4c594d8d75641765bff85d72c2d251ad076e6529ce0eeedd1c languageName: node linkType: hard @@ -6761,7 +6773,7 @@ __metadata: languageName: node linkType: hard -"@uniswap/sdk-core@npm:<=4.0.3 || >4.0.6, @uniswap/sdk-core@npm:^4, @uniswap/sdk-core@npm:^4.0.0, @uniswap/sdk-core@npm:^4.0.2, @uniswap/sdk-core@npm:^4.0.6": +"@uniswap/sdk-core@npm:<=4.0.3 || >4.0.6, @uniswap/sdk-core@npm:^4, @uniswap/sdk-core@npm:^4.0.0, @uniswap/sdk-core@npm:^4.0.6, @uniswap/sdk-core@npm:^4.0.7": version: 4.0.7 resolution: "@uniswap/sdk-core@npm:4.0.7" dependencies: @@ -6776,8 +6788,8 @@ __metadata: linkType: hard "@uniswap/smart-order-router@npm:^3.11.0": - version: 3.16.21 - resolution: "@uniswap/smart-order-router@npm:3.16.21" + version: 3.16.22 + resolution: "@uniswap/smart-order-router@npm:3.16.22" dependencies: "@uniswap/default-token-list": ^11.2.0 "@uniswap/permit2-sdk": ^1.2.0 @@ -6803,7 +6815,7 @@ __metadata: stats-lite: ^2.2.0 peerDependencies: jsbi: ^3.2.0 - checksum: 651486c5095efff6d7b284aabbd8372cd22566b28f671f1761dc6984ea69c7bf7321b1cec2b43c707c549e768ca428875362f9eaaefff4a8642ff232616bbf4c + checksum: 7abb06046a4e906ac17e638a065d0b0082792f1f5f88537d56138bf11a4d67bc8acce918a7efe82167b8c951be577ffe85fbe8af115a20f1fbc30838f42789d6 languageName: node linkType: hard @@ -6876,15 +6888,15 @@ __metadata: linkType: hard "@uniswap/v2-sdk@npm:^3.2.0": - version: 3.2.0 - resolution: "@uniswap/v2-sdk@npm:3.2.0" + version: 3.2.1 + resolution: "@uniswap/v2-sdk@npm:3.2.1" dependencies: "@ethersproject/address": ^5.0.0 "@ethersproject/solidity": ^5.0.0 - "@uniswap/sdk-core": ^4.0.2 + "@uniswap/sdk-core": ^4.0.7 tiny-invariant: ^1.1.0 tiny-warning: ^1.0.3 - checksum: d4445af16bc203364074d2ded02231dd2ceff798b723ced760c19cfd171dafb71603efc42ac11c88cc9528de8e5439c1ac57d11671cf9eae6006fea158d02077 + checksum: 519c01e840878d03b99f0220da3a686afa097287b1c10fc65aaabd0555bab0fbcb013ac6d991453f70161e2e804b0e0797fb853d635acf56eae133671fdcb515 languageName: node linkType: hard @@ -9327,9 +9339,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001517, caniuse-lite@npm:^1.0.30001520": - version: 1.0.30001532 - resolution: "caniuse-lite@npm:1.0.30001532" - checksum: 613abeb15e03dde307d543195a7860f7ba7450c9c9262d45642b2c8fbe097914fa060d68c8647f9d443947b1f62b09d891858bde7d2cac94fae8133a0b518b28 + version: 1.0.30001533 + resolution: "caniuse-lite@npm:1.0.30001533" + checksum: 1ffb2d69f817ee5f13351cb01c26a98ac61515809a6ce355305df3fbc6de6391a58466c1dcad1f322231b1ddc59bdda9bc52b9480cac100c3ff2f5782e859eb1 languageName: node linkType: hard @@ -9422,6 +9434,7 @@ __metadata: version: 0.0.0-use.local resolution: "chatweb3-frontend@workspace:." dependencies: + "@arbitrum/sdk": ^3.1.6 "@center-inc/react": ^1.1.13 "@headlessui/react": ^1.7.15 "@heroicons/react": ^2.0.14 @@ -10917,9 +10930,9 @@ __metadata: linkType: hard "electron-to-chromium@npm:^1.4.477": - version: 1.4.514 - resolution: "electron-to-chromium@npm:1.4.514" - checksum: 571a78404ee986e99eb0f53390dee9b231d317fb1857a2b0745e6d05f4038115b026012e356eb55fef1808160f8cacbc6796d0b731b2372c4fd9b133ccc30af5 + version: 1.4.516 + resolution: "electron-to-chromium@npm:1.4.516" + checksum: e95b1d1d19bcc14f9985a1e76ff06977272a67dd73ab48322cb2828af3d07f7b81c9f796f2ef5d6ccd9b708efba94d2ac5ad60b8c56f4898faf813d6aec1b41c languageName: node linkType: hard @@ -12015,7 +12028,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.3.1, ethers@npm:^5.4.5, ethers@npm:^5.7.0, ethers@npm:^5.7.2": +"ethers@npm:^5.1.0, ethers@npm:^5.3.1, ethers@npm:^5.4.5, ethers@npm:^5.7.0, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: @@ -14699,9 +14712,9 @@ __metadata: languageName: node linkType: hard -"jest-haste-map@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-haste-map@npm:29.6.4" +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/graceful-fs": ^4.1.3 @@ -14711,14 +14724,14 @@ __metadata: fsevents: ^2.3.2 graceful-fs: ^4.2.9 jest-regex-util: ^29.6.3 - jest-util: ^29.6.3 - jest-worker: ^29.6.4 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 micromatch: ^4.0.4 walker: ^1.0.8 dependenciesMeta: fsevents: optional: true - checksum: 4f720fd3813bb38400b7a9a094e55664cbddd907ba1769457ed746f6c870c615167647a5b697a788183d832b1dcb1b66143e52990a6f4403283f6686077fa868 + checksum: c2c8f2d3e792a963940fbdfa563ce14ef9e14d4d86da645b96d3cd346b8d35c5ce0b992ee08593939b5f718cf0a1f5a90011a056548a1dbf58397d4356786f01 languageName: node linkType: hard @@ -14773,9 +14786,9 @@ __metadata: languageName: node linkType: hard -"jest-message-util@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-message-util@npm:29.6.3" +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" dependencies: "@babel/code-frame": ^7.12.13 "@jest/types": ^29.6.3 @@ -14783,10 +14796,10 @@ __metadata: chalk: ^4.0.0 graceful-fs: ^4.2.9 micromatch: ^4.0.4 - pretty-format: ^29.6.3 + pretty-format: ^29.7.0 slash: ^3.0.0 stack-utils: ^2.0.3 - checksum: 59f5229a06c073a8877ba4d2e304cc07d63b0062bf5764d4bed14364403889e77f1825d1bd9017c19a840847d17dffd414dc06f1fcb537b5f9e03dbc65b84ada + checksum: a9d025b1c6726a2ff17d54cc694de088b0489456c69106be6b615db7a51b7beb66788bea7a59991a019d924fbf20f67d085a445aedb9a4d6760363f4d7d09930 languageName: node linkType: hard @@ -15013,9 +15026,9 @@ __metadata: languageName: node linkType: hard -"jest-util@npm:^29.6.3": - version: 29.6.3 - resolution: "jest-util@npm:29.6.3" +"jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" dependencies: "@jest/types": ^29.6.3 "@types/node": "*" @@ -15023,7 +15036,7 @@ __metadata: ci-info: ^3.2.0 graceful-fs: ^4.2.9 picomatch: ^2.2.3 - checksum: 7bf3ba3ac67ac6ceff7d8fdd23a86768e23ddd9133ecd9140ef87cc0c28708effabaf67a6cd45cd9d90a63d645a522ed0825d09ee59ac4c03b9c473b1fef4c7c + checksum: 042ab4980f4ccd4d50226e01e5c7376a8556b472442ca6091a8f102488c0f22e6e8b89ea874111d2328a2080083bf3225c86f3788c52af0bd0345a00eb57a3ca languageName: node linkType: hard @@ -15075,18 +15088,18 @@ __metadata: linkType: hard "jest-watcher@npm:^29.0.0": - version: 29.6.4 - resolution: "jest-watcher@npm:29.6.4" + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" dependencies: - "@jest/test-result": ^29.6.4 + "@jest/test-result": ^29.7.0 "@jest/types": ^29.6.3 "@types/node": "*" ansi-escapes: ^4.2.1 chalk: ^4.0.0 emittery: ^0.13.1 - jest-util: ^29.6.3 + jest-util: ^29.7.0 string-length: ^4.0.1 - checksum: 13c0f96f7e9212e4f3ef2daf3e787045bdcec414061bf286eca934c7f4083fb04d38df9ced9c0edfbe15f3521ca581eb2ed6108c338a0db1f3e1def65687992f + checksum: 67e6e7fe695416deff96b93a14a561a6db69389a0667e9489f24485bb85e5b54e12f3b2ba511ec0b777eca1e727235b073e3ebcdd473d68888650489f88df92f languageName: node linkType: hard @@ -15112,15 +15125,15 @@ __metadata: languageName: node linkType: hard -"jest-worker@npm:^29.6.4": - version: 29.6.4 - resolution: "jest-worker@npm:29.6.4" +"jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" dependencies: "@types/node": "*" - jest-util: ^29.6.3 + jest-util: ^29.7.0 merge-stream: ^2.0.0 supports-color: ^8.0.0 - checksum: 05d19a5759ebfeb964036065be55ad8d8e8ddffa85d9b3a4c0b95765695efb1d8226ec824a4d8e660c38cda3389bfeb98d819f47232acf9fb0e79f553b7c0a76 + checksum: 30fff60af49675273644d408b650fc2eb4b5dcafc5a0a455f238322a8f9d8a98d847baca9d51ff197b6747f54c7901daa2287799230b856a0f48287d131f8c13 languageName: node linkType: hard @@ -17078,11 +17091,11 @@ __metadata: linkType: hard "nan@npm:^2.14.0": - version: 2.17.0 - resolution: "nan@npm:2.17.0" + version: 2.18.0 + resolution: "nan@npm:2.18.0" dependencies: node-gyp: latest - checksum: ec609aeaf7e68b76592a3ba96b372aa7f5df5b056c1e37410b0f1deefbab5a57a922061e2c5b369bae9c7c6b5e6eecf4ad2dac8833a1a7d3a751e0a7c7f849ed + checksum: 4fe42f58456504eab3105c04a5cffb72066b5f22bd45decf33523cb17e7d6abc33cca2a19829407b9000539c5cb25f410312d4dc5b30220167a3594896ea6a0a languageName: node linkType: hard @@ -18698,14 +18711,14 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^29.6.3": - version: 29.6.3 - resolution: "pretty-format@npm:29.6.3" +"pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" dependencies: "@jest/schemas": ^29.6.3 ansi-styles: ^5.0.0 react-is: ^18.0.0 - checksum: 4e1c0db48e65571c22e80ff92123925ff8b3a2a89b71c3a1683cfde711004d492de32fe60c6bc10eea8bf6c678e5cbe544ac6c56cb8096e1eb7caf856928b1c4 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 languageName: node linkType: hard @@ -22333,11 +22346,11 @@ __metadata: linkType: hard "uuid@npm:^9.0.0": - version: 9.0.0 - resolution: "uuid@npm:9.0.0" + version: 9.0.1 + resolution: "uuid@npm:9.0.1" bin: uuid: dist/bin/uuid - checksum: 8dd2c83c43ddc7e1c71e36b60aea40030a6505139af6bee0f382ebcd1a56f6cd3028f7f06ffb07f8cf6ced320b76aea275284b224b002b289f89fe89c389b028 + checksum: 39931f6da74e307f51c0fb463dc2462807531dc80760a9bff1e35af4316131b4fc3203d16da60ae33f07fdca5b56f3f1dd662da0c99fea9aaeab2004780cc5f4 languageName: node linkType: hard