diff --git a/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/constants.ts b/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/constants.ts new file mode 100644 index 0000000000..5817c045a3 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/constants.ts @@ -0,0 +1,128 @@ +export const FACTORY_ABI = [ + { + type: 'function', + name: 'executeHooks', + inputs: [ + { + name: 'calls', + type: 'tuple[]', + internalType: 'struct Call[]', + components: [ + { + name: 'target', + type: 'address', + internalType: 'address', + }, + { + name: 'value', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'callData', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'allowFailure', + type: 'bool', + internalType: 'bool', + }, + { + name: 'isDelegateCall', + type: 'bool', + internalType: 'bool', + }, + ], + }, + { + name: 'nonce', + type: 'bytes32', + internalType: 'bytes32', + }, + { + name: 'deadline', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'user', + type: 'address', + internalType: 'address', + }, + { + name: 'signature', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +export const SHED_ABI = [ + { + type: 'function', + name: 'executeHooks', + inputs: [ + { + name: 'calls', + type: 'tuple[]', + internalType: 'struct Call[]', + components: [ + { + name: 'target', + type: 'address', + internalType: 'address', + }, + { + name: 'value', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'callData', + type: 'bytes', + internalType: 'bytes', + }, + { + name: 'allowFailure', + type: 'bool', + internalType: 'bool', + }, + { + name: 'isDelegateCall', + type: 'bool', + internalType: 'bool', + }, + ], + }, + { + name: 'nonce', + type: 'bytes32', + internalType: 'bytes32', + }, + { + name: 'deadline', + type: 'uint256', + internalType: 'uint256', + }, + { + name: 'signature', + type: 'bytes', + internalType: 'bytes', + }, + ], + outputs: [], + stateMutability: 'nonpayable', + }, +] as const + +export const PROXY_CREATION_CODE = '0x' + +// TODO: update this once the contract is deployed +export const COW_SHED_FACTORY = '0xBB64Eb2cE6C4Fecc3EE0b18A415c536b147d6727' +export const COW_SHED_IMPLEMENTATION = '0x0CCb8fDAA217943D52Db003703b75b66523295a1' +export const proxyInitCode = + '0x60a034608e57601f61037138819003918201601f19168301916001600160401b038311848410176093578084926040948552833981010312608e57604b602060458360a9565b920160a9565b6080527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc556040516102b490816100bd8239608051818181608f01526101720152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203608e5756fe60806040526004361015610018575b3661019457610194565b6000803560e01c908163025b22bc1461003b575063f851a4400361000e5761010d565b3461010a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261010a5773ffffffffffffffffffffffffffffffffffffffff60043581811691828203610106577f0000000000000000000000000000000000000000000000000000000000000000163314600014610101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b8280a280f35b61023d565b8380fd5b80fd5b346101645760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610164576020610146610169565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b600080fd5b333003610101577f000000000000000000000000000000000000000000000000000000000000000090565b60ff7f68df44b1011761f481358c0f49a711192727fb02c377d697bcb0ea8ff8393ac0541615806101ef575b1561023d5760046040517ff92ee8a9000000000000000000000000000000000000000000000000000000008152fd5b507f400ada75000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006000351614156101c0565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e1561027a573d90f35b3d90fdfea264697066735822122031e6c23049bed9e91b6914ec3a10b4ead2d855cd933d50e8e3635e4e999fe02e64736f6c63430008190033' diff --git a/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/index.ts b/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/index.ts new file mode 100644 index 0000000000..3849fad989 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/cow-shed/index.ts @@ -0,0 +1,118 @@ +import { ethers, getCreate2Address, solidityPacked, solidityPackedKeccak256, TypedDataEncoder } from 'ethers_v6' + +import { FACTORY_ABI, PROXY_CREATION_CODE, SHED_ABI } from './constants' + +export interface ISdkOptions { + factoryAddress: string + proxyCreationCode?: string + implementationAddress: string + chainId: number +} + +export interface ICall { + target: string + value: bigint + callData: string + allowFailure: boolean + isDelegateCall: boolean +} + +export interface IExecuteHooks { + calls: ICall[] + nonce: string + deadline: bigint +} + +const ABI_CODER = new ethers.AbiCoder() + +const DOMAIN_TYPE = { + EIP712Domain: [ + { type: 'string', name: 'name' }, + { type: 'string', name: 'version' }, + { type: 'uint256', name: 'chainId' }, + { type: 'address', name: 'verifyingContract' }, + ], +} + +export const COW_SHED_712_TYPES = { + ExecuteHooks: [ + { type: 'Call[]', name: 'calls' }, + { type: 'bytes32', name: 'nonce' }, + { type: 'uint256', name: 'deadline' }, + ], + Call: [ + { type: 'address', name: 'target' }, + { type: 'uint256', name: 'value' }, + { type: 'bytes', name: 'callData' }, + { type: 'bool', name: 'allowFailure' }, + { type: 'bool', name: 'isDelegateCall' }, + ], +} +const FACTORY_INTERFACE: ethers.Interface = new ethers.Interface(FACTORY_ABI) +const SHED_INTERFACE: ethers.Interface = new ethers.Interface(SHED_ABI) + +export class CowShedSdk { + constructor(private options: ISdkOptions) {} + + computeProxyAddress(user: string) { + const salt = ABI_CODER.encode(['address'], [user]) + const initCodeHash = solidityPackedKeccak256( + ['bytes', 'bytes'], + [this._proxyCreationCode(), ABI_CODER.encode(['address', 'address'], [this.options.implementationAddress, user])] + ) + return getCreate2Address(this.options.factoryAddress, salt, initCodeHash) + } + + computeDomainSeparator(proxy: string) { + return TypedDataEncoder.hashStruct('EIP712Domain', DOMAIN_TYPE, this._getDomain(proxy)) + } + + hashToSignWithProxy(calls: ICall[], nonce: string, deadline: bigint, proxy: string) { + return this._hashToSign(calls, nonce, deadline, proxy) + } + + hashToSignWithUser(calls: ICall[], nonce: string, deadline: bigint, user: string) { + return this._hashToSign(calls, nonce, deadline, this.computeProxyAddress(user)) + } + + static encodeExecuteHooksForFactory( + calls: ICall[], + nonce: string, + deadline: bigint, + user: string, + signature: string + ) { + return FACTORY_INTERFACE.encodeFunctionData('executeHooks', [calls, nonce, deadline, user, signature]) + } + + static encodeExecuteHooksForProxy(calls: ICall[], nonce: string, deadline: bigint, signature: string) { + return SHED_INTERFACE.encodeFunctionData('executeHooks', [calls, nonce, deadline, signature]) + } + + static encodeEOASignature(r: bigint, s: bigint, v: number) { + return solidityPacked(['uint', 'uint', 'uint8'], [r, s, v]) + } + + _hashToSign(calls: ICall[], nonce: string, deadline: bigint, proxy: string) { + const message: IExecuteHooks = { + calls, + nonce, + deadline, + } + return { domain: this._getDomain(proxy), types: COW_SHED_712_TYPES, value: message } + } + + private _getDomain(proxy: string) { + const domain = { + name: 'COWShed', + version: '1.0.0', + chainId: this.options.chainId, + verifyingContract: proxy, + } + return domain + } + + private _proxyCreationCode() { + return this.options.proxyCreationCode ?? PROXY_CREATION_CODE + } +} diff --git a/apps/cowswap-frontend/src/modules/hooksStore/dapps/BalV2HookApp/index.tsx b/apps/cowswap-frontend/src/modules/hooksStore/dapps/BalV2HookApp/index.tsx new file mode 100644 index 0000000000..f2e6c18215 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/dapps/BalV2HookApp/index.tsx @@ -0,0 +1,253 @@ +import { useCallback, useContext, useEffect, useState } from 'react' + +import { RPC_URLS } from '@cowprotocol/common-const' +import { HookDappInternal, HookDappType } from '@cowprotocol/types' +import { ButtonPrimary, UI } from '@cowprotocol/ui' + +import { RemoveLiquidity, RemoveLiquidityKind, Slippage } from '@balancer/sdk' +import { parseUnits } from 'ethers/lib/utils' +import styled from 'styled-components/macro' + +import { usePoolData, useUserBalancerPool } from 'modules/hooksStore/hooks/useBalancerPool' +import { PoolData, PoolsData } from 'modules/hooksStore/types/BalancerPool' + +import { HookDappContext } from '../../context' +import balancerLogo from '../../images/balancer.png' +import { ICall } from 'modules/hooksStore/cow-shed' +import { useUserTransactionTTL } from 'legacy/state/user/hooks' +import { CurrencyAmount, Token } from '@uniswap/sdk-core' +import { useTokenContract } from 'common/hooks/useContract' +import { useCowShed } from 'modules/hooksStore/hooks/useCowShed' + +const TITLE = 'Exit Balancer Pool' +const DESCRIPTION = 'Allows you to exit a Balancer pool' + +const Wrapper = styled.div` + display: flex; + flex-direction: row; + gap: 1.6rem; + padding: 1rem; + justify-content: start; +` + +const DropdownContainer = styled.div` + position: relative; + width: 50%; + margin: 1.4rem 0; +` + +const DropdownHeader = styled.div` + padding: 10px; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 1.3rem; + font-weight: 500; + border: 1px solid #e0e0e0; + border-radius: 8px; +` + +const DropdownBody = styled.div` + position: absolute; + top: calc(100% + 1rem); + left: 0; + width: 100%; + border-radius: 1.6rem; + padding: 0.6rem; + display: flex; + flex-flow: column wrap; + gap: 0.6rem; +` + +const DropdownOption = styled.div` + padding: 1rem; + cursor: pointer; + display: flex; + align-items: center; + font-size: 1.3rem; + font-weight: 500; + + &:hover { + background-color: black; + border-radius: 1rem; + } +` + +const ErrorLabel = styled.div` + color: var(${UI.COLOR_RED}); +` + +const LoadingLabel = styled.div` + color: var(${UI.COLOR_TEXT2}); +` + +export const PRE_EXIT_BAL_POOL: HookDappInternal = { + name: TITLE, + description: DESCRIPTION, + type: HookDappType.INTERNAL, + path: '/hooks-dapps/pre/claim-gno', + component: , + image: balancerLogo, + version: 'v0.1.1', +} + +export function ExitBalV2App() { + const hookDappContext = useContext(HookDappContext) + const { data: pools, isLoading: isLoadingPools } = useUserBalancerPool() + const [selectedPoolId, setSelectedPoolId] = useState() + const { data: poolData, isValidating: isValidatingPoolData } = usePoolData(selectedPoolId) + const [userDeadline] = useUserTransactionTTL() + const { signCalls, calculateProxyAddress } = useCowShed() + const bptContract = useTokenContract(poolData?.address) + const [hookCalls, setHookCalls] = useState() + const [outputTokens, setOutputTokens] = useState[]>() + + useEffect(() => { + const updateHookData = async () => { + if (!hookDappContext || !poolData || !hookDappContext.account) return + + const removeLiquidity = new RemoveLiquidity() + + const bptAmount = parseUnits(poolData.userBalance.totalBalance, poolData.decimals).toBigInt() + const proxyAddress = calculateProxyAddress(hookDappContext.account) as `0x${string}` + + const exitQuery = await removeLiquidity.query( + { + chainId: hookDappContext.chainId, + kind: RemoveLiquidityKind.Proportional, + rpcUrl: RPC_URLS[hookDappContext.chainId], + bptIn: { + address: poolData.address, + decimals: poolData.decimals, + rawAmount: bptAmount, + }, + }, + { + id: poolData.id, + address: poolData.address, + type: poolData.type.charAt(0).toUpperCase() + poolData.type.slice(1).toLowerCase(), + protocolVersion: poolData.protocolVersion, + tokens: poolData.poolTokens.map((token, index) => ({ + ...token, + index, + })), + } + ) + const exitCall = removeLiquidity.buildCall({ + ...exitQuery, + slippage: Slippage.fromPercentage('10'), + sender: proxyAddress, + recipient: hookDappContext.account as `0x${string}`, + }) + setHookCalls([ + { + target: poolData.address, + isDelegateCall: false, + value: BigInt(0), + allowFailure: false, + callData: bptContract?.interface.encodeFunctionData('transferFrom', [ + hookDappContext.account, + proxyAddress, + bptAmount, + ]) as string, + }, + { + target: exitCall.to, + isDelegateCall: false, + value: exitCall.value, + allowFailure: false, + callData: exitCall.callData, + }, + ]) + setOutputTokens( + exitQuery.amountsOut.map((amount) => + CurrencyAmount.fromRawAmount( + new Token(hookDappContext.chainId, amount.token.address, amount.token.decimals, amount.token.symbol), + amount.amount.toString() + ) + ) + ) + } + + updateHookData() + }, [poolData, hookDappContext]) + + const clickOnAddHook = useCallback(async () => { + if (!hookCalls || !hookDappContext) return + const validTo = BigInt(Date.now() + userDeadline * 2) + + const hook = await signCalls(hookCalls, validTo) + + hookDappContext.addHook( + { + hook, + dapp: PRE_EXIT_BAL_POOL, + outputTokens, + }, + true + ) + }, [hookCalls, userDeadline, hookDappContext, signCalls, outputTokens]) + + if (!hookDappContext?.account) { + return 'Connect your wallet first' + } + + if (!hookDappContext) { + return 'Loading...' + } + + return ( + + + + +Add Pre-hook + + + ) +} + +export function SelectPoolToExit(props: { + loading: boolean + pools?: PoolsData[] + setSelectedPoolId: (poolId: string) => void + poolData?: PoolData +}) { + const { loading, pools, setSelectedPoolId, poolData } = props + const [isOpen, setIsOpen] = useState(false) + + if (loading) { + return Loading... + } + + if (!pools) { + return None pool found + } + + const handleSelect = (pool: PoolsData) => { + setSelectedPoolId(pool.id) + setIsOpen(false) + } + + return ( + + setIsOpen(!isOpen)}> + {poolData ? poolData.symbol : 'Select the pool to exit'} + + {isOpen && ( + + {pools.map((pool) => ( + handleSelect(pool)} key={pool.id}> + {pool.symbol} + + ))} + + )} + + ) +} diff --git a/apps/cowswap-frontend/src/modules/hooksStore/hookRegistry.tsx b/apps/cowswap-frontend/src/modules/hooksStore/hookRegistry.tsx index 089ed89421..cff7d621f4 100644 --- a/apps/cowswap-frontend/src/modules/hooksStore/hookRegistry.tsx +++ b/apps/cowswap-frontend/src/modules/hooksStore/hookRegistry.tsx @@ -8,6 +8,7 @@ import buildImg from './images/build.png' import cowAMM from './images/cowAMM.png' import curveImg from './images/curve.svg' import daiImg from './images/dai.svg' +import { PRE_EXIT_BAL_POOL } from './dapps/BalV2HookApp' const FAKE_URL = 'https://google.com' @@ -86,10 +87,10 @@ const POST_BUILD: HookDappIframe = { const POST_HOOK_DAPPS_ALL = [POST_BRIDGE, POST_MAKER, POST_BUILD] export const PRE_HOOK_REGISTRY: Record = { - [SupportedChainId.MAINNET]: [PRE_CURVE, PRE_COWAMM, PRE_MAKER, PRE_BUILD], - [SupportedChainId.GNOSIS_CHAIN]: [PRE_CLAIM_GNO, PRE_CURVE, PRE_COWAMM, PRE_MAKER, PRE_BUILD], - [SupportedChainId.SEPOLIA]: [PRE_COWAMM, PRE_BUILD], - [SupportedChainId.ARBITRUM_ONE]: [PRE_COWAMM, PRE_BUILD], + [SupportedChainId.MAINNET]: [PRE_CURVE, PRE_COWAMM, PRE_MAKER, PRE_BUILD, PRE_EXIT_BAL_POOL], + [SupportedChainId.GNOSIS_CHAIN]: [PRE_CLAIM_GNO, PRE_CURVE, PRE_COWAMM, PRE_MAKER, PRE_BUILD, PRE_EXIT_BAL_POOL], + [SupportedChainId.SEPOLIA]: [PRE_COWAMM, PRE_BUILD, PRE_EXIT_BAL_POOL], + [SupportedChainId.ARBITRUM_ONE]: [PRE_COWAMM, PRE_BUILD, PRE_EXIT_BAL_POOL], } export const POST_HOOK_REGISTRY: Record = { diff --git a/apps/cowswap-frontend/src/modules/hooksStore/hooks/useBalancerPool.ts b/apps/cowswap-frontend/src/modules/hooksStore/hooks/useBalancerPool.ts new file mode 100644 index 0000000000..1cc52aca61 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/hooks/useBalancerPool.ts @@ -0,0 +1,121 @@ +import { SupportedChainId } from '@cowprotocol/cow-sdk' +import { useWalletInfo } from '@cowprotocol/wallet' + +import { gql, GraphQLClient } from 'graphql-request' +import useSWR from 'swr' + +import { PoolData, PoolsData } from '../types/BalancerPool' + +const BalancerChainName: Record = { + [SupportedChainId.MAINNET]: 'MAINNET', + [SupportedChainId.SEPOLIA]: 'SEPOLIA', + [SupportedChainId.ARBITRUM_ONE]: 'ARBITRUM', + [SupportedChainId.GNOSIS_CHAIN]: 'GNOSIS', +} + +const USER_POOLS_QUERY = gql` + query GetPools( + $first: Int + $skip: Int + $orderBy: GqlPoolOrderBy + $orderDirection: GqlPoolOrderDirection + $where: GqlPoolFilter + $textSearch: String + ) { + pools: poolGetPools( + first: $first + skip: $skip + orderBy: $orderBy + orderDirection: $orderDirection + where: $where + textSearch: $textSearch + ) { + address + chain + protocolVersion + id + name + symbol + type + decimals + userBalance { + totalBalance + totalBalanceUsd + } + displayTokens { + address + symbol + } + } + } +` + +const POOL_QUERY = gql` + query GetPool($id: String!, $chain: GqlChain!, $userAddress: String) { + pool: poolGetPool(id: $id, chain: $chain, userAddress: $userAddress) { + id + address + decimals + symbol + type + chain + protocolVersion + userBalance { + totalBalance + totalBalanceUsd + } + poolTokens { + id + address + name + decimals + symbol + balance + } + } + } +` + +const BASE_URL = `https://api-v3.balancer.fi/graphql` +const GQL_CLIENT = new GraphQLClient(BASE_URL) + +export function useUserBalancerPool() { + const { chainId, account } = useWalletInfo() + + return useSWR([chainId, account], async ([chainId, account]) => { + if (!account || !chainId) { + return [] + } + const chainName = BalancerChainName[chainId] + return await GQL_CLIENT.request<{ + pools: PoolsData[] + }>(USER_POOLS_QUERY, { + where: { + userAddress: account, + chainIn: [chainName], + }, + }).then((result) => { + return result.pools + }) + }) +} + +export function usePoolData(poolId?: string) { + const { chainId, account } = useWalletInfo() + + return useSWR(poolId, async (poolId) => { + if (!poolId) { + return undefined + } + + return await GQL_CLIENT.request<{ + pool: PoolData + }>(POOL_QUERY, { + id: poolId, + chain: BalancerChainName[chainId], + userAddress: account, + }).then((result) => { + return result.pool + }) + }) +} diff --git a/apps/cowswap-frontend/src/modules/hooksStore/hooks/useCowShed.ts b/apps/cowswap-frontend/src/modules/hooksStore/hooks/useCowShed.ts new file mode 100644 index 0000000000..5a4268bdf1 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/hooks/useCowShed.ts @@ -0,0 +1,66 @@ +import { useWalletInfo } from '@cowprotocol/wallet' +import { useWalletProvider } from '@cowprotocol/wallet-provider' +import { useRequestOrderCancellation } from 'legacy/state/orders/hooks' +import { useCallback } from 'react' +import { CowShedSdk, ICall } from '../cow-shed' +import { COW_SHED_FACTORY, COW_SHED_IMPLEMENTATION, proxyInitCode } from '../cow-shed/constants' +import { ethers } from 'ethers_v6' +import { CowHook } from '@cowprotocol/types' + +export function useCowShed() { + const provider = useWalletProvider() + const { account, chainId } = useWalletInfo() + const cancelPendingOrder = useRequestOrderCancellation() + const shedSdk = new CowShedSdk({ + factoryAddress: COW_SHED_FACTORY, + implementationAddress: COW_SHED_IMPLEMENTATION, + proxyCreationCode: proxyInitCode, + chainId, + }) + + const calculateProxyAddress = useCallback( + (user: string) => { + return shedSdk.computeProxyAddress(user) + }, + [shedSdk] + ) + + const signCalls = useCallback( + async (calls: ICall[], validTo: bigint): Promise => { + if (!account || !provider) { + throw new Error('No account or provider') + } + + const nonce = ethers.encodeBytes32String(Date.now().toString()) + + const infoToSign = shedSdk.hashToSignWithUser(calls, nonce, validTo, account) + + const signer = provider.getSigner() + + const signatureRaw = await signer._signTypedData(infoToSign.domain, infoToSign.types, infoToSign.value) + const r = BigInt(signatureRaw.slice(0, 66)) + const s = BigInt(`0x${signatureRaw.slice(66, 130)}`) + const v = parseInt(signatureRaw.slice(130, 132), 16) + + const encodedSignature = CowShedSdk.encodeEOASignature(r, s, v) + + const hooksCalldata = CowShedSdk.encodeExecuteHooksForFactory( + calls, + nonce, + BigInt(validTo), + account, + encodedSignature + ) + const estimateGas = await provider.estimateGas({ + to: COW_SHED_FACTORY, + value: '0', + data: hooksCalldata, + }) + + return { target: COW_SHED_FACTORY, callData: hooksCalldata, gasLimit: estimateGas.add(estimateGas).toString() } + }, + [account, cancelPendingOrder, chainId, provider] + ) + + return { calculateProxyAddress, signCalls } +} diff --git a/apps/cowswap-frontend/src/modules/hooksStore/images/balancer.png b/apps/cowswap-frontend/src/modules/hooksStore/images/balancer.png new file mode 100644 index 0000000000..fe1b51d0c3 Binary files /dev/null and b/apps/cowswap-frontend/src/modules/hooksStore/images/balancer.png differ diff --git a/apps/cowswap-frontend/src/modules/hooksStore/types/BalancerPool.ts b/apps/cowswap-frontend/src/modules/hooksStore/types/BalancerPool.ts new file mode 100644 index 0000000000..6ac33ab7a7 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/hooksStore/types/BalancerPool.ts @@ -0,0 +1,40 @@ +export interface PoolsData { + address: `0x${string}` + chain: string + protocolVersion: 1 | 2 | 3 + id: `0x${string}` + name: string + symbol: string + type: string + decimals: number + userBalance: { + totalBalance: `${number}` + totalBalanceUsd: number + } + displayTokens: { + address: `0x${string}` + symbol: string + }[] +} + +export interface PoolData { + id: `0x${string}` + address: `0x${string}` + decimals: number + symbol: string + type: string + chain: string + protocolVersion: 1 | 2 | 3 + userBalance: { + totalBalance: `${number}` + totalBalanceUsd: number + } + poolTokens: { + id: `0x${string}` + address: `0x${string}` + name: string + decimals: number + symbol: string + balance: number + }[] +} diff --git a/package.json b/package.json index 0c6b569eac..63f37d9519 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,8 @@ "@1inch/permit-signed-approvals-utils": "^1.4.10", "@apollo/client": "^3.1.5", "@babel/runtime": "^7.17.0", + "@balancer-labs/sdk": "^1.1.5", + "@balancer/sdk": "0.22.2", "@coinbase/wallet-sdk": "^3.3.0", "@cowprotocol/app-data": "^2.1.0", "@cowprotocol/cms": "^0.3.1", @@ -134,6 +136,7 @@ "@web3-react/url": "^8.2.3", "@web3-react/walletconnect-v2": "^8.5.1", "@web3modal/ethers5": "^4.1.9", + "add": "^2.0.6", "bnc-sdk": "^4.6.0", "buffer": "^6.0.3", "cids": "^1.0.0", @@ -152,6 +155,7 @@ "date-fns": "^2.29.3", "dotenv": "^16.4.5", "ethers": "5.7.2", + "ethers_v6": "npm:ethers@^6.12.1", "eventemitter3": "^4.0.0", "exponential-backoff": "^3.1.1", "fast-deep-equal": "^3.1.3", @@ -229,7 +233,8 @@ "viem": "^1.16.6", "wagmi": "^1.2", "web-vitals": "^2.1.4", - "web3modal": "1.9.0" + "web3modal": "1.9.0", + "yarn": "^1.22.22" }, "devDependencies": { "@babel/preset-react": "^7.14.5", diff --git a/yarn.lock b/yarn.lock index d2459f1599..0577c34558 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,6 +26,11 @@ resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + "@alloc/quick-lru@^5.2.0": version "5.2.0" resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" @@ -2146,6 +2151,43 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@balancer-labs/sdk@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@balancer-labs/sdk/-/sdk-1.1.5.tgz#29e70d15d7e98899831b18d8b909b6569e062758" + integrity sha512-Hxmo1u8qJureQxdbVAMAkN9qceeZxcKx4QjoevTDMrSGY5H9jc1hX18p9TTZXwlGAkw8n4rdErydUgsdWjWuLA== + dependencies: + "@balancer-labs/sor" "^4.1.1-beta.16" + "@ethersproject/abi" "^5.4.0" + "@ethersproject/abstract-signer" "^5.4.0" + "@ethersproject/address" "^5.4.0" + "@ethersproject/base64" "5.5.0" + "@ethersproject/bignumber" "^5.4.0" + "@ethersproject/bytes" "^5.4.0" + "@ethersproject/constants" "^5.4.0" + "@ethersproject/contracts" "^5.4.0" + "@ethersproject/providers" "^5.4.5" + axios "^0.24.0" + graphql "^15.6.1" + graphql-request "^3.5.0" + json-to-graphql-query "^2.2.4" + lodash "^4.17.21" + +"@balancer-labs/sor@^4.1.1-beta.16": + version "4.1.1-beta.17" + resolved "https://registry.yarnpkg.com/@balancer-labs/sor/-/sor-4.1.1-beta.17.tgz#8c404a86174003cccf2bb87d49221cfdcf083246" + integrity sha512-JcX/HeppyoIs+Sa3Z/pdZhqMOBAGajOwVkBkFA8rehd1K2qaU/k/a3OkbIidXjs4lQI9sJE1WO8RauCLtuLQfg== + dependencies: + isomorphic-fetch "^2.2.1" + +"@balancer/sdk@0.22.2": + version "0.22.2" + resolved "https://registry.yarnpkg.com/@balancer/sdk/-/sdk-0.22.2.tgz#d725cf8301948a5e28e4f4e4304e983d160ab8eb" + integrity sha512-IF/2Ar10/XSCQ7noGGLlGM8KLp1qx/y8IvnbVB7KpbW1SR2zDsQkxEWRTQiPqcj5e0s40ihHrklcDp8vlspDtA== + dependencies: + decimal.js-light "^2.5.1" + lodash.clonedeep "^4.5.0" + viem "^2.12.1" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -3279,7 +3321,7 @@ ethereum-cryptography "^2.0.0" micro-ftch "^0.3.1" -"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.4.0", "@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== @@ -3307,7 +3349,7 @@ "@ethersproject/transactions" "^5.7.0" "@ethersproject/web" "^5.7.0" -"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.7.0": +"@ethersproject/abstract-signer@5.7.0", "@ethersproject/abstract-signer@^5.4.0", "@ethersproject/abstract-signer@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== @@ -3318,7 +3360,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@^5", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -3329,6 +3371,13 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/rlp" "^5.7.0" +"@ethersproject/base64@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" + integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/base64@5.7.0", "@ethersproject/base64@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" @@ -3344,7 +3393,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@^5.4.0", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -3353,21 +3402,21 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.5.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.7.0": +"@ethersproject/constants@5.7.0", "@ethersproject/constants@^5.4.0", "@ethersproject/constants@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== dependencies: "@ethersproject/bignumber" "^5.7.0" -"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.4.1", "@ethersproject/contracts@^5.7.0": +"@ethersproject/contracts@5.7.0", "@ethersproject/contracts@^5.4.0", "@ethersproject/contracts@^5.4.1", "@ethersproject/contracts@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== @@ -5115,6 +5164,20 @@ dependencies: "@noble/hashes" "1.3.2" +"@noble/curves@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.0.tgz#f05771ef64da724997f69ee1261b2417a49522d6" + integrity sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@^1.4.0", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" @@ -5130,7 +5193,7 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== -"@noble/hashes@^1.3.1": +"@noble/hashes@1.4.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@~1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== @@ -6248,6 +6311,11 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== +"@scure/base@~1.1.6": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.7.tgz#fe973311a5c6267846aa131bc72e96c5d40d2b30" + integrity sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g== + "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" @@ -6275,6 +6343,15 @@ "@noble/hashes" "~1.3.2" "@scure/base" "~1.1.2" +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -6291,6 +6368,14 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@sentry-internal/tracing@7.64.0": version "7.64.0" resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.64.0.tgz#3e110473b8edf805b799cc91d6ee592830237bb4" @@ -8187,6 +8272,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.5.tgz#9dc0a5cb1ccce4f7a731660935ab70b9c00a5d69" integrity sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/node@18.16.9": version "18.16.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.9.tgz#e79416d778a8714597342bb87efb5a6e914f7a73" @@ -10313,6 +10403,11 @@ abitype@1.0.0: resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== +abitype@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" + integrity sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -10389,6 +10484,11 @@ acorn@^8.11.3: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +add@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235" + integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q== + address@^1.0.1, address@^1.1.2: version "1.2.2" resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" @@ -10407,6 +10507,11 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + aes-js@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" @@ -11003,6 +11108,13 @@ axios@^0.19.2: dependencies: follow-redirects "1.5.10" +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + axios@^1.6.0: version "1.6.8" resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" @@ -13086,7 +13198,7 @@ cross-env@^7.0.3: dependencies: cross-spawn "^7.0.1" -cross-fetch@^3.0.4, cross-fetch@^3.1.4, cross-fetch@^3.1.5, cross-fetch@^3.1.6: +cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.4, cross-fetch@^3.1.5, cross-fetch@^3.1.6: version "3.1.8" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== @@ -14022,7 +14134,7 @@ decamelize@^1.1.0, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decimal.js-light@^2.5.0: +decimal.js-light@^2.5.0, decimal.js-light@^2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934" integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg== @@ -15912,6 +16024,19 @@ ethers@5.7.2, ethers@^5.7.0: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +"ethers_v6@npm:ethers@^6.12.1": + version "6.13.2" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.2.tgz#4b67d4b49e69b59893931a032560999e5e4419fe" + integrity sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.17.1" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -16539,7 +16664,7 @@ follow-redirects@^1.0.0, follow-redirects@^1.15.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -follow-redirects@^1.15.6: +follow-redirects@^1.14.4, follow-redirects@^1.15.6: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== @@ -17201,6 +17326,15 @@ graphql-request@4.3.0, graphql-request@^4.3.0: extract-files "^9.0.0" form-data "^3.0.0" +graphql-request@^3.5.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.7.0.tgz#c7406e537084f8b9788541e3e6704340ca13055b" + integrity sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ== + dependencies: + cross-fetch "^3.0.6" + extract-files "^9.0.0" + form-data "^3.0.0" + graphql-tag@^2.12.6: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" @@ -17208,6 +17342,11 @@ graphql-tag@^2.12.6: dependencies: tslib "^2.1.0" +graphql@^15.6.1: + version "15.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.9.0.tgz#4e8ca830cfd30b03d44d3edd9cac2b0690304b53" + integrity sha512-GCOQdvm7XxV1S4U4CGrsdlEN37245eC8P9zaYCMr6K1BG0IPGy5lUwmJsEOGyl1GD6HXjOtl2keCP9asRBwNvA== + graphql@^16.3.0: version "16.8.1" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" @@ -20739,6 +20878,11 @@ json-text-sequence@~0.1.0: dependencies: delimit-stream "0.1.0" +json-to-graphql-query@^2.2.4: + version "2.2.5" + resolved "https://registry.yarnpkg.com/json-to-graphql-query/-/json-to-graphql-query-2.2.5.tgz#56b072a693b50fd4dc981367b60d52e3dc78f426" + integrity sha512-5Nom9inkIMrtY992LMBBG1Zaekrc10JaRhyZgprwHBVMDtRgllTvzl0oBbg13wJsVZoSoFNNMaeIVQs0P04vsA== + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -21318,6 +21462,11 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -28746,6 +28895,11 @@ tslib@1.14.1, tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" @@ -29627,6 +29781,21 @@ viem@^2.1.1: isows "1.0.4" ws "8.13.0" +viem@^2.12.1: + version "2.19.1" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.19.1.tgz#38ccffbacf69d8a2f940ff35be8ea3ac42ea5d61" + integrity sha512-a0ca/ACEz3FRZB3OmiSfRUogWZGQh700wu7Pg3GmAWiGD+0PS9bVaWG67JQ+9azFZLq0BU/m0t2CeWd3xi8IzQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.4.0" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + abitype "1.0.5" + isows "1.0.4" + webauthn-p256 "0.0.5" + ws "8.17.1" + vite-node@0.32.4: version "0.32.4" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.32.4.tgz#7b3f94af5a87c631fbc380ba662914bafbd04d80" @@ -30342,6 +30511,14 @@ web3modal@1.9.0: styled-components "^5.1.1" tslib "^1.10.0" +webauthn-p256@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/webauthn-p256/-/webauthn-p256-0.0.5.tgz#0baebd2ba8a414b21cc09c0d40f9dd0be96a06bd" + integrity sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg== + dependencies: + "@noble/curves" "^1.4.0" + "@noble/hashes" "^1.4.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -31194,6 +31371,11 @@ ws@8.16.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -31366,6 +31548,11 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yarn@^1.22.22: + version "1.22.22" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.22.tgz#ac34549e6aa8e7ead463a7407e1c7390f61a6610" + integrity sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg== + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"