From 7536f779b09f06aa63a5730b07a77ffb36b42310 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:42:34 +0100 Subject: [PATCH 01/60] [skip ci] wip: bump ethers to v6 feat: migrate AddressZero -> ZeroAddress wip: wip fix: types feat: hexValue -> toQuantity wip: wip wip: wip wip: wip wip: wip --- __mocks__/ethers.ts | 25 +-------- package.json | 2 +- packages/caip/src/adapters/yearn/utils.ts | 4 +- .../chain-adapters/src/evm/EvmBaseAdapter.ts | 6 +-- .../src/evm/gnosis/GnosisChainAdapter.test.ts | 8 +-- packages/chain-adapters/src/utils/index.ts | 3 -- .../src/evm/bnbsmartchain/parser/bep20.ts | 13 +++-- .../src/evm/ethereum/parser/foxy.ts | 10 ++-- .../src/evm/ethereum/parser/uniV2.ts | 22 ++++---- .../src/evm/ethereum/parser/weth.ts | 10 ++-- .../unchained-client/src/evm/parser/erc20.ts | 15 +++--- .../unchained-client/src/evm/parser/index.ts | 6 +-- .../unchained-client/src/evm/parser/nft.ts | 4 +- .../src/evm/parser/thorchain.ts | 15 +++--- .../generateAssetData/ethereum/yearnVaults.ts | 2 +- src/contracts/contractManager.ts | 4 +- .../FoxyManager/Deposit/FoxyDeposit.tsx | 2 +- .../FoxyManager/Withdraw/FoxyWithdraw.tsx | 2 +- .../Withdraw/components/Confirm.tsx | 4 +- .../Withdraw/components/Withdraw.tsx | 4 +- .../Deposit/components/Approve.tsx | 4 +- .../Deposit/components/Deposit.tsx | 4 +- .../Withdraw/components/Approve.tsx | 2 +- .../Withdraw/components/Withdraw.tsx | 7 ++- .../univ2/hooks/useUniV2LiquidityPool.ts | 18 +++---- src/lib/address/yat.ts | 2 +- src/lib/ethersProviderSingleton.ts | 8 +-- src/lib/investor/investor-foxy/api/api.ts | 16 +++--- src/lib/investor/investor-foxy/foxycli.ts | 4 +- src/lib/market-service/foxy/foxy.test.ts | 2 +- src/lib/market-service/foxy/foxy.ts | 4 +- .../market-service/market-service-manager.ts | 2 +- src/lib/market-service/market-service.test.ts | 2 +- .../swapper/swappers/CowSwapper/CowSwapper.ts | 5 +- .../swappers/CowSwapper/utils/constants.ts | 4 +- .../CowSwapper/utils/helpers/helpers.ts | 7 ++- .../getNetworkFeeCryptoBaseUnit.ts | 3 +- src/lib/utils/evm.ts | 2 +- .../Pool/components/Borrow/BorrowConfirm.tsx | 4 +- .../Pool/components/Repay/RepayConfirm.tsx | 6 +-- .../ReusableLpStatus/TransactionRow.tsx | 8 +-- .../modals/ContractInteractionBreakdown.tsx | 9 ++-- .../walletConnectToDapps/hooks/useGetAbi.tsx | 23 ++++---- src/plugins/walletConnectToDapps/utils.ts | 8 +-- .../hooks/useQuoteEstimatedFeesQuery.ts | 4 +- .../resolvers/uniV2/index.ts | 8 +-- .../resolvers/uniV2/utils.ts | 4 +- src/test/mocks/txs.ts | 10 ++-- yarn.lock | 53 ++++++++++++++++++- 49 files changed, 206 insertions(+), 188 deletions(-) diff --git a/__mocks__/ethers.ts b/__mocks__/ethers.ts index 1f2617e84dd..e0a67eda388 100644 --- a/__mocks__/ethers.ts +++ b/__mocks__/ethers.ts @@ -1,21 +1,10 @@ -import { - BigNumber, - Bytes, - BytesLike, - ethers, - providers, - Signature, - Signer, - UnsignedTransaction, - utils, -} from 'ethers' +import ethers from 'ethers' import { vi } from 'vitest' const ethersMock = { ...ethers, providers: { JsonRpcProvider: vi.fn(), - StaticJsonRpcProvider: vi.fn(), }, Contract: vi.fn().mockImplementation(address => ({ decimals: () => { @@ -59,14 +48,4 @@ const ethersMock = { })), } -export { - ethersMock as ethers, - BigNumber, - Bytes, - BytesLike, - Signature, - Signer, - UnsignedTransaction, - providers, - utils, -} +export { ethersMock as ethers } diff --git a/package.json b/package.json index 8b2133e9f40..78b54de5422 100644 --- a/package.json +++ b/package.json @@ -139,7 +139,7 @@ "envalid": "^7.3.1", "eslint-plugin-react-memo": "^0.0.3", "eth-url-parser": "^1.0.4", - "ethers": "^5.7.2", + "ethers": "^6.11.1", "framer-motion": "^11.0.3", "friendly-challenge": "0.9.2", "grapheme-splitter": "^1.0.4", diff --git a/packages/caip/src/adapters/yearn/utils.ts b/packages/caip/src/adapters/yearn/utils.ts index 65dd160c843..4549c1e779a 100644 --- a/packages/caip/src/adapters/yearn/utils.ts +++ b/packages/caip/src/adapters/yearn/utils.ts @@ -10,7 +10,9 @@ import { toChainId } from '../../chainId/chainId' import { CHAIN_NAMESPACE, CHAIN_REFERENCE } from '../../constants' const network = 1 // 1 for mainnet -const provider = new ethers.providers.StaticJsonRpcProvider(process.env.REACT_APP_ETHEREUM_NODE_URL) +const provider = new ethers.JsonRpcProvider(process.env.REACT_APP_ETHEREUM_NODE_URL) +// @ts-ignore types are drunk here as yearn expects the v5 flavor of ethers JsonRpcProvider, +// but yearn usage is nuked from the codebase so meh const yearnSdk = new Yearn(network, { provider }) export const writeFiles = async (data: Record>) => { diff --git a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts index a554c34613e..8e5b549e118 100644 --- a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts +++ b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts @@ -21,7 +21,7 @@ import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' import BigNumber from 'bignumber.js' -import { utils } from 'ethers' +import { isAddress, toQuantity } from 'ethers' import { numberToHex } from 'web3-utils' import type { ChainAdapter as IChainAdapter } from '../api' @@ -247,7 +247,7 @@ export abstract class EvmBaseAdapter implements IChainAdap }[this.chainId] await wallet.ethSwitchChain({ - chainId: utils.hexValue(adapterChainReference), + chainId: toQuantity(adapterChainReference), chainName: this.getDisplayName(), nativeCurrency: { name: targetNetwork.name, @@ -538,7 +538,7 @@ export abstract class EvmBaseAdapter implements IChainAdap // eslint-disable-next-line require-await async validateAddress(address: string): Promise { - const isValidAddress = utils.isAddress(address) + const isValidAddress = isAddress(address) if (isValidAddress) return { valid: true, result: ValidAddressResultType.Valid } return { valid: false, result: ValidAddressResultType.Invalid } } diff --git a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts index 8452523f3bb..e2216c04028 100644 --- a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts @@ -4,7 +4,6 @@ * Test GnosisChainAdapter * @group unit */ -import { AddressZero } from '@ethersproject/constants' import { ASSET_REFERENCE, fromChainId, gnosisAssetId, gnosisChainId } from '@shapeshiftoss/caip' import type { ETHSignMessage, ETHSignTx, ETHWallet } from '@shapeshiftoss/hdwallet-core' import type { NativeAdapterArgs } from '@shapeshiftoss/hdwallet-native' @@ -12,6 +11,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import { ZeroAddress } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -134,7 +134,7 @@ describe('GnosisChainAdapter', () => { to: '0x642F4Bda144C63f6DC47EE0fDfbac0a193e2eDb7', value: '123', chainSpecific: { - from: AddressZero, + from: ZeroAddress, data: '0x', }, } @@ -460,7 +460,7 @@ describe('GnosisChainAdapter', () => { const adapter = new gnosis.ChainAdapter(args) const wallet = await getWallet() - wallet.ethGetAddress = async () => await Promise.resolve(AddressZero) + wallet.ethGetAddress = async () => await Promise.resolve(ZeroAddress) const tx = { wallet, @@ -563,7 +563,7 @@ describe('GnosisChainAdapter', () => { const tx = { wallet: await getWallet(), accountNumber, - to: AddressZero, + to: ZeroAddress, value, chainSpecific: makeChainSpecific({ contractAddress }), } as unknown as BuildSendTxInput diff --git a/packages/chain-adapters/src/utils/index.ts b/packages/chain-adapters/src/utils/index.ts index bf124950f89..203af283297 100644 --- a/packages/chain-adapters/src/utils/index.ts +++ b/packages/chain-adapters/src/utils/index.ts @@ -1,6 +1,5 @@ import type { AssetNamespace, ChainId } from '@shapeshiftoss/caip' import { CHAIN_NAMESPACE, CHAIN_REFERENCE, fromChainId } from '@shapeshiftoss/caip' -import { BigNumber } from 'ethers' export * from './bignumber' export * from './bip44' @@ -70,5 +69,3 @@ export const chainIdToChainLabel = (chainId: ChainId): string => { throw new Error(`chainNamespace ${chainNamespace} not supported.`) } } - -export const convertNumberToHex = (value: string): string => BigNumber.from(value).toHexString() diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts index 75dd0009853..f4813153eac 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts @@ -1,6 +1,5 @@ import type { ChainId } from '@shapeshiftoss/caip' import { toAssetId } from '@shapeshiftoss/caip' -import type { BigNumber } from 'ethers' import { ethers } from 'ethers' import type { BaseTxMetadata } from '../../../types' @@ -16,17 +15,17 @@ export interface TxMetadata extends BaseTxMetadata { interface ParserArgs { chainId: ChainId - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } export class Parser implements SubParser { - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider readonly chainId: ChainId - readonly abiInterface = new ethers.utils.Interface(bep20) + readonly abiInterface = new ethers.Interface(bep20) readonly supportedFunctions = { - approveSigHash: this.abiInterface.getSighash('approve'), + approveSigHash: this.abiInterface.getFunction('approve')?.selector, } constructor(args: ParserArgs) { @@ -58,9 +57,9 @@ export class Parser implements SubParser { switch (txSigHash) { case this.supportedFunctions.approveSigHash: { - const amount = decoded.args.amount as BigNumber + const amount = decoded.args.amount as BigInt const value = amount.toString() - if (amount.isZero()) { + if (amount === BigInt(0)) { return await Promise.resolve({ data: { ...data, method: 'revoke', value } }) } return await Promise.resolve({ data: { ...data, value } }) diff --git a/packages/unchained-client/src/evm/ethereum/parser/foxy.ts b/packages/unchained-client/src/evm/ethereum/parser/foxy.ts index 8e1bb38087f..3751a3f5cb6 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/foxy.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/foxy.ts @@ -12,13 +12,13 @@ export interface TxMetadata extends BaseTxMetadata { } export class Parser implements SubParser { - readonly abiInterface = new ethers.utils.Interface(FOXY_STAKING_ABI) + readonly abiInterface = new ethers.Interface(FOXY_STAKING_ABI) readonly supportedFunctions = { - stakeSigHash: this.abiInterface.getSighash('stake(uint256,address)'), - unstakeSigHash: this.abiInterface.getSighash('unstake'), - instantUnstakeSigHash: this.abiInterface.getSighash('instantUnstake'), - claimWithdrawSigHash: this.abiInterface.getSighash('claimWithdraw'), + stakeSigHash: this.abiInterface.getFunction('stake(uint256,address)')?.selector, + unstakeSigHash: this.abiInterface.getFunction('unstake')?.selector, + instantUnstakeSigHash: this.abiInterface.getFunction('instantUnstake')?.selector, + claimWithdrawSigHash: this.abiInterface.getFunction('claimWithdraw')?.selector, } async parse(tx: Tx): Promise { diff --git a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts index 2ced225eb75..bced105109a 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts @@ -23,24 +23,24 @@ export interface TxMetadata extends BaseTxMetadata { export interface ParserArgs { chainId: ChainId - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } export class Parser implements SubParser { - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider readonly chainId: ChainId readonly wethContract: string - readonly abiInterface = new ethers.utils.Interface(UNIV2_ABI) - readonly stakingRewardsInterface = new ethers.utils.Interface(UNIV2_STAKING_REWARDS_ABI) + readonly abiInterface = new ethers.Interface(UNIV2_ABI) + readonly stakingRewardsInterface = new ethers.Interface(UNIV2_STAKING_REWARDS_ABI) readonly supportedFunctions = { - addLiquidityEthSigHash: this.abiInterface.getSighash('addLiquidityETH'), - removeLiquidityEthSigHash: this.abiInterface.getSighash('removeLiquidityETH'), + addLiquidityEthSigHash: this.abiInterface.getFunction('addLiquidityETH')?.selector, + removeLiquidityEthSigHash: this.abiInterface.getFunction('removeLiquidityETH')?.selector, } readonly supportedStakingRewardsFunctions = { - stakeSigHash: this.stakingRewardsInterface.getSighash('stake'), - exitSigHash: this.stakingRewardsInterface.getSighash('exit'), + stakeSigHash: this.stakingRewardsInterface.getFunction('stake')?.selector, + exitSigHash: this.stakingRewardsInterface.getFunction('exit')?.selector, } constructor(args: ParserArgs) { @@ -81,7 +81,7 @@ export class Parser implements SubParser { }, } - const tokenAddress = ethers.utils.getAddress(decoded.args.token.toLowerCase()) + const tokenAddress = ethers.getAddress(decoded.args.token.toLowerCase()) const lpTokenAddress = Parser.pairFor(tokenAddress, this.wethContract) const transfers = await (async () => { @@ -188,8 +188,8 @@ export class Parser implements SubParser { private static pairFor(tokenA: string, tokenB: string): string { const [token0, token1] = tokenA < tokenB ? [tokenA, tokenB] : [tokenB, tokenA] const factoryContract = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f' - const salt = ethers.utils.solidityKeccak256(['address', 'address'], [token0, token1]) + const salt = ethers.solidityPackedKeccak256(['address', 'address'], [token0, token1]) const initCodeHash = '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // https://github.com/Uniswap/v2-periphery/blob/dda62473e2da448bc9cb8f4514dadda4aeede5f4/contracts/libraries/UniswapV2Library.sol#L24 - return ethers.utils.getCreate2Address(factoryContract, salt, initCodeHash) + return ethers.getCreate2Address(factoryContract, salt, initCodeHash) } } diff --git a/packages/unchained-client/src/evm/ethereum/parser/weth.ts b/packages/unchained-client/src/evm/ethereum/parser/weth.ts index cbb9458bf15..5fda25f2121 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/weth.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/weth.ts @@ -16,18 +16,18 @@ export interface TxMetadata extends BaseTxMetadata { export interface ParserArgs { chainId: ChainId - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } export class Parser implements SubParser { - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider readonly chainId: ChainId readonly wethContract: string - readonly abiInterface = new ethers.utils.Interface(WETH_ABI) + readonly abiInterface = new ethers.Interface(WETH_ABI) readonly supportedFunctions = { - depositSigHash: this.abiInterface.getSighash('deposit'), - withdrawalSigHash: this.abiInterface.getSighash('withdraw'), + depositSigHash: this.abiInterface.getFunction('deposit')?.selector, + withdrawalSigHash: this.abiInterface.getFunction('withdraw')?.selector, } constructor(args: ParserArgs) { diff --git a/packages/unchained-client/src/evm/parser/erc20.ts b/packages/unchained-client/src/evm/parser/erc20.ts index 99f15b9885e..47f3e867e64 100644 --- a/packages/unchained-client/src/evm/parser/erc20.ts +++ b/packages/unchained-client/src/evm/parser/erc20.ts @@ -1,6 +1,5 @@ import type { ChainId } from '@shapeshiftoss/caip' import { toAssetId } from '@shapeshiftoss/caip' -import type { BigNumber } from 'ethers' import { ethers } from 'ethers' import type { BaseTxMetadata } from '../../types' @@ -16,17 +15,17 @@ export interface TxMetadata extends BaseTxMetadata { interface ParserArgs { chainId: ChainId - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } export class Parser implements SubParser { - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider readonly chainId: ChainId - readonly abiInterface = new ethers.utils.Interface(ERC20_ABI) + readonly abiInterface = new ethers.Interface(ERC20_ABI) readonly supportedFunctions = { - approveSigHash: this.abiInterface.getSighash('approve'), + approveSigHash: this.abiInterface.getFunction('approve')?.selector ?? '', } constructor(args: ParserArgs) { @@ -58,9 +57,11 @@ export class Parser implements SubParser { switch (txSigHash) { case this.supportedFunctions.approveSigHash: { - const amount = decoded.args.amount as BigNumber + const amount = decoded.args.amount as BigInt const value = amount.toString() - if (amount.isZero()) { + // For paranoia's sake, remove me before opening the PR + console.log({ amount }) + if (amount === BigInt(0)) { return await Promise.resolve({ data: { ...data, method: 'revoke', value } }) } return await Promise.resolve({ data: { ...data, value: value.toString() } }) diff --git a/packages/unchained-client/src/evm/parser/index.ts b/packages/unchained-client/src/evm/parser/index.ts index ada84ef49d1..f6b3131d121 100644 --- a/packages/unchained-client/src/evm/parser/index.ts +++ b/packages/unchained-client/src/evm/parser/index.ts @@ -26,7 +26,7 @@ export class BaseTransactionParser { assetId: AssetId protected readonly api: Api - protected readonly provider: ethers.providers.StaticJsonRpcProvider + protected readonly provider: ethers.JsonRpcProvider private parsers: SubParser[] = [] @@ -34,7 +34,7 @@ export class BaseTransactionParser { this.chainId = args.chainId this.assetId = args.assetId this.api = args.api - this.provider = new ethers.providers.StaticJsonRpcProvider(args.rpcUrl) + this.provider = new ethers.JsonRpcProvider(args.rpcUrl) } /** @@ -51,7 +51,7 @@ export class BaseTransactionParser { } async parse(tx: T, address: string): Promise { - address = ethers.utils.getAddress(address) + address = ethers.getAddress(address) // We expect only one Parser to return a result. If multiple do, we take the first and early exit. const contractParserResult = await findAsyncSequential, TxSpecific>( diff --git a/packages/unchained-client/src/evm/parser/nft.ts b/packages/unchained-client/src/evm/parser/nft.ts index 8acc5997db9..eb54c8ac47f 100644 --- a/packages/unchained-client/src/evm/parser/nft.ts +++ b/packages/unchained-client/src/evm/parser/nft.ts @@ -18,13 +18,13 @@ export interface TxMetadata extends BaseTxMetadata { interface ParserArgs { chainId: ChainId api: Api - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } const supportedTokenTypes = ['ERC721', 'ERC1155', 'BEP721', 'BEP1155'] export class Parser implements SubParser { - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider readonly chainId: ChainId readonly api: Api diff --git a/packages/unchained-client/src/evm/parser/thorchain.ts b/packages/unchained-client/src/evm/parser/thorchain.ts index 2e0b766bd8e..6632e175c0d 100644 --- a/packages/unchained-client/src/evm/parser/thorchain.ts +++ b/packages/unchained-client/src/evm/parser/thorchain.ts @@ -34,17 +34,18 @@ interface SupportedFunctions { export class Parser implements SubParser { private readonly chainId: ChainId private readonly thorchainParser: ThorchainParser - private readonly abiInterface: ethers.utils.Interface + private readonly abiInterface: ethers.Interface private readonly supportedFunctions: SupportedFunctions constructor(args: ParserArgs) { - this.abiInterface = new ethers.utils.Interface(routerAbi) + this.abiInterface = new ethers.Interface(routerAbi) this.supportedFunctions = { - depositSigHash: this.abiInterface.getSighash('deposit'), - depositWithExpirySigHash: this.abiInterface.getSighash('depositWithExpiry'), - transferOutSigHash: this.abiInterface.getSighash('transferOut'), - transferOutAndCallSigHash: this.abiInterface.getSighash('transferOutAndCall'), - swapInSigHash: this.abiInterface.getSighash('swapIn'), + depositSigHash: this.abiInterface.getFunction('deposit')?.selector ?? '', + depositWithExpirySigHash: this.abiInterface.getFunction('depositWithExpiry')?.selector ?? '', + transferOutSigHash: this.abiInterface.getFunction('transferOut')?.selector ?? '', + transferOutAndCallSigHash: + this.abiInterface.getFunction('transferOutAndCall')?.selector ?? '', + swapInSigHash: this.abiInterface.getFunction('swapIn')?.selector ?? '', } this.thorchainParser = new ThorchainParser({ midgardUrl: args.midgardUrl }) this.chainId = args.chainId diff --git a/scripts/generateAssetData/ethereum/yearnVaults.ts b/scripts/generateAssetData/ethereum/yearnVaults.ts index 65ebf5ea880..e93412e3065 100644 --- a/scripts/generateAssetData/ethereum/yearnVaults.ts +++ b/scripts/generateAssetData/ethereum/yearnVaults.ts @@ -9,7 +9,7 @@ import { ethereum } from '../baseAssets' import { colorMap } from '../colorMap' const network = 1 // 1 for mainnet -const provider = new ethers.providers.StaticJsonRpcProvider(process.env.ETHEREUM_NODE_URL) +const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NODE_URL) export const yearnSdk = new Yearn(network, { provider }) const explorerData = { diff --git a/src/contracts/contractManager.ts b/src/contracts/contractManager.ts index 3730cd3191b..e968ba9e27f 100644 --- a/src/contracts/contractManager.ts +++ b/src/contracts/contractManager.ts @@ -104,7 +104,7 @@ export const getOrCreateContractByType = ({ }) definedContracts.push({ contract, - address: ethers.utils.getAddress(address), + address: ethers.getAddress(address), } as unknown as DefinedContract) return contract as KnownContractByType } @@ -112,7 +112,7 @@ export const getOrCreateContractByType = ({ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { const { assetReference, chainId } = fromAssetId(pairAssetId) // Checksum - const contractAddress = ethers.utils.getAddress(assetReference) + const contractAddress = ethers.getAddress(assetReference) const pair = getOrCreateContractByType({ address: contractAddress, type: ContractType.UniV2Pair, diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx index 995f72aaf7a..69289bdfb53 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx @@ -93,7 +93,7 @@ export const FoxyDeposit: React.FC<{ ) return const foxyOpportunity = await foxyApi.getFoxyOpportunityByStakingAddress( - ethers.utils.getAddress(foxyStakingContractAddress), + ethers.getAddress(foxyStakingContractAddress), ) dispatch({ type: FoxyDepositActionType.SET_OPPORTUNITY, diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx index bee9912c550..391b489ac89 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx @@ -75,7 +75,7 @@ export const FoxyWithdraw: React.FC<{ ) return const foxyOpportunity = await foxyApi.getFoxyOpportunityByStakingAddress( - ethers.utils.getAddress(foxyStakingContractAddress), + ethers.getAddress(foxyStakingContractAddress), ) // Get foxy fee for instant sends const foxyFeePercentage = await foxyApi.instantUnstakeFee({ diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx index d2f1bfcb4d2..d73b1763fe1 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx @@ -9,7 +9,6 @@ import { Stack, useToast, } from '@chakra-ui/react' -import { AddressZero } from '@ethersproject/constants' import type { AccountId } from '@shapeshiftoss/caip' import { bchChainId, fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' @@ -20,6 +19,7 @@ import { getConfig } from 'config' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' import dayjs from 'dayjs' +import { ZeroAddress } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import type { @@ -415,7 +415,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - AddressZero, + ZeroAddress, BigInt(amount), quote.memo, BigInt(quote.expiry), diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx index e8f9c8388f8..4259b910034 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx @@ -1,5 +1,4 @@ import { Alert, AlertIcon, Skeleton, useToast } from '@chakra-ui/react' -import { AddressZero } from '@ethersproject/constants' import type { AccountId } from '@shapeshiftoss/caip' import { fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import type { Asset, KnownChainIds } from '@shapeshiftoss/types' @@ -7,6 +6,7 @@ import { Err, Ok, type Result } from '@sniptt/monads' import { useQueryClient } from '@tanstack/react-query' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' +import { ZeroAddress } from 'ethers' import type { WithdrawValues } from 'features/defi/components/Withdraw/Withdraw' import { Field, Withdraw as ReusableWithdraw } from 'features/defi/components/Withdraw/Withdraw' import type { @@ -274,7 +274,7 @@ export const Withdraw: React.FC = ({ accountId, fromAddress, onNe getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - AddressZero, + getAddress(ZeroAddress), BigInt(amountCryptoBaseUnit), quote.memo, BigInt(quote.expiry), diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx index b9f64cb38ac..618e91b741c 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx @@ -101,11 +101,11 @@ export const Approve: React.FC = ({ accountId, onNext }) => { const asset0ContractAddress = useMemo(() => { if (assetId0 === ethAssetId) return undefined - return ethers.utils.getAddress(fromAssetId(assetId0).assetReference) + return ethersgetAddress(fromAssetId(assetId0).assetReference) }, [assetId0]) const asset1ContractAddress = useMemo(() => { if (assetId1 === ethAssetId) return undefined - return ethers.utils.getAddress(fromAssetId(assetId1).assetReference) + return ethers.getAddress(fromAssetId(assetId1).assetReference) }, [assetId1]) const neededApprovals = [ isApprove0Needed && asset0ContractAddress, diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx index c80c0ab8fc2..fbaf6eb7090 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx @@ -187,11 +187,11 @@ export const Deposit: React.FC = ({ } else { const asset0ContractAddress = assetId0 !== ethAssetId - ? ethers.utils.getAddress(fromAssetId(assetId0).assetReference) + ? ethers.getAddress(fromAssetId(assetId0).assetReference) : undefined const asset1ContractAddress = assetId1 !== ethAssetId - ? ethers.utils.getAddress(fromAssetId(assetId1).assetReference) + ? ethers.getAddress(fromAssetId(assetId1).assetReference) : undefined // While the naive approach would be to think both assets approve() calls are going to result in the same gas estimation, diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx index ca25192744a..3e11fb5e90b 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx @@ -112,7 +112,7 @@ export const Approve: React.FC = ({ accountId, onNext }) => { try { dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: true }) - const lpAssetContractAddress = ethers.utils.getAddress(fromAssetId(lpAssetId).assetReference) + const lpAssetContractAddress = ethers.getAddress(fromAssetId(lpAssetId).assetReference) await approveAsset(lpAssetContractAddress) await poll({ fn: () => lpAllowance(), diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx index 699ed2444f9..6eb6bd65018 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx @@ -11,6 +11,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useUniV2LiquidityPool } from 'features/defi/providers/univ2/hooks/useUniV2LiquidityPool' import { useCallback, useContext, useMemo, useState } from 'react' import { FormProvider, useForm } from 'react-hook-form' +import { getAddress } from 'viem' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import { AssetInput } from 'components/DeFi/components/AssetInput' import type { StepComponentProps } from 'components/DeFi/components/Steps' @@ -200,11 +201,9 @@ export const Withdraw: React.FC = ({ onNext(DefiStep.Confirm) dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: false }) } else { - const lpAssetContractAddress = ethers.utils.getAddress( - fromAssetId(lpAssetId).assetReference, - ) + const lpAssetContractAddress = ethers.getAddress(fromAssetId(lpAssetId).assetReference) - const fees = await getApproveFees(lpAssetContractAddress) + const fees = await getApproveFees(getAddress(lpAssetContractAddress)) if (!fees) return dispatch({ diff --git a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts index e029178b160..54a3306b008 100644 --- a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts +++ b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts @@ -81,16 +81,16 @@ export const useUniV2LiquidityPool = ({ // Checksummed addresses const asset0ContractAddress = useMemo( - () => ethers.utils.getAddress(fromAssetId(assetId0OrWeth).assetReference), + () => ethers.getAddress(fromAssetId(assetId0OrWeth).assetReference), [assetId0OrWeth], ) const asset1ContractAddress = useMemo( - () => ethers.utils.getAddress(fromAssetId(assetId1OrWeth).assetReference), + () => ethers.getAddress(fromAssetId(assetId1OrWeth).assetReference), [assetId1OrWeth], ) const lpContractAddress = useMemo( - () => ethers.utils.getAddress(fromAssetId(lpAssetId).assetReference), + () => ethers.getAddress(fromAssetId(lpAssetId).assetReference), [lpAssetId], ) @@ -149,7 +149,7 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidityETH', args: [ - otherAssetContractAddress, + getAddress(otherAssetContractAddress), BigInt(toBaseUnit(otherAssetAmount, otherAsset.precision)), BigInt(amountOtherAssetMin), BigInt(amountEthMin), @@ -166,8 +166,8 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidity', args: [ - asset0ContractAddress, - asset1ContractAddress, + getAddress(asset0ContractAddress), + getAddress(asset1ContractAddress), BigInt(toBaseUnit(token0Amount, asset0.precision)), BigInt(toBaseUnit(token1Amount, asset1.precision)), BigInt(amountAsset0Min), @@ -494,7 +494,7 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidityETH', args: [ - otherAssetContractAddress, + getAddress(otherAssetContractAddress), BigInt(toBaseUnit(otherAssetAmount, otherAsset.precision)), BigInt(amountOtherAssetMin), BigInt(amountEthMin), @@ -519,8 +519,8 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidity', args: [ - asset0ContractAddress, - asset1ContractAddress, + getAddress(asset0ContractAddress), + getAddress(asset1ContractAddress), BigInt(toBaseUnit(token0Amount, asset0.precision)), BigInt(toBaseUnit(token1Amount, asset1.precision)), BigInt(amountAsset0Min), diff --git a/src/lib/address/yat.ts b/src/lib/address/yat.ts index 4458ed2137e..005c63ddf11 100644 --- a/src/lib/address/yat.ts +++ b/src/lib/address/yat.ts @@ -77,7 +77,7 @@ export const resolveYat: ResolveYat = async args => { })() if (!maybeAddress) return '' - return ethers.utils.getAddress(maybeAddress) + return ethers.getAddress(maybeAddress) } catch (e) { return '' } diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index a66c8686dd8..a7534ece35d 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -2,7 +2,7 @@ import type { ChainId } from '@shapeshiftoss/caip' import type { EvmChainId } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' -import { providers } from 'ethers' +import { JsonRpcProvider, providers } from 'ethers' import { assertUnreachable } from './utils' @@ -29,13 +29,13 @@ export const rpcUrlByChainId = (chainId: EvmChainId): string => { } } -const ethersProviders: Map = new Map() +const ethersProviders: Map = new Map() export const getEthersProvider = ( chainId: EvmChainId = KnownChainIds.EthereumMainnet, -): providers.StaticJsonRpcProvider => { +): JsonRpcProvider => { if (!ethersProviders.has(chainId)) { - const provider = new providers.StaticJsonRpcProvider(rpcUrlByChainId(chainId)) + const provider = new JsonRpcProvider(rpcUrlByChainId(chainId)) ethersProviders.set(chainId, provider) return provider } else { diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index c74d047279c..143b09c0ffa 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -60,7 +60,7 @@ type EthereumChainReference = export type ConstructorArgs = { adapter: EvmBaseAdapter providerUrl: string - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider foxyAddresses: FoxyAddressesType chainReference?: EthereumChainReference } @@ -84,7 +84,7 @@ const TOKE_IPFS_URL = 'https://ipfs.tokemaklabs.xyz/ipfs' export class FoxyApi { public adapter: EvmBaseAdapter - public provider: ethers.providers.StaticJsonRpcProvider + public provider: ethers.JsonRpcProvider private providerUrl: string private foxyStakingContracts: ethers.Contract[] private liquidityReserveContracts: ethers.Contract[] @@ -117,8 +117,8 @@ export class FoxyApi { * to exponential notation ('1.6e+21') in javascript. * @param amount */ - private normalizeAmount(amount: BigNumber): ethers.BigNumber { - return ethers.BigNumber.from(amount.toFixed()) + private normalizeAmount(amount: BigNumber): BigInt { + return BigInt(amount.toFixed()) } // TODO(gomes): This is rank and should really belong in web for sanity sake. @@ -154,7 +154,7 @@ export class FoxyApi { if (dryRun) return signedTx try { if (this.providerUrl.includes('localhost') || this.providerUrl.includes('127.0.0.1')) { - const sendSignedTx = await this.provider.sendTransaction(signedTx) + const sendSignedTx = await this.provider.broadcastTransaction(signedTx) return sendSignedTx?.blockHash ?? '' } return this.adapter.broadcastTransaction({ @@ -181,7 +181,7 @@ export class FoxyApi { checksumAddress(address: string): string { // ethers always returns checksum addresses from getAddress() calls - return ethers.utils.getAddress(address) + return ethers.getAddress(address) } private verifyAddresses(addresses: string[]) { @@ -998,8 +998,6 @@ export class FoxyApi { } const liquidityReserveContract = this.getLiquidityReserveContract(liquidityReserveAddress) try { - // ethers BigNumber doesn't support floats, so we have to convert it to a regular bn first - // to be able to get a float bignumber.js as an output const feeInBasisPoints = bnOrZero((await liquidityReserveContract.fee()).toString()) return feeInBasisPoints.div(10000) // convert from basis points to decimal percentage } catch (e) { @@ -1048,7 +1046,7 @@ export class FoxyApi { const coolDownInfo: [amount: string, gons: string, expiry: string] = ( await stakingContract.coolDownInfo(userAddress) - ).map((info: ethers.BigNumber) => info.toString()) + ).map((info: BigInt) => info.toString()) const releaseTime = await this.getTimeUntilClaimable(input) const [amount, gons, expiry] = coolDownInfo diff --git a/src/lib/investor/investor-foxy/foxycli.ts b/src/lib/investor/investor-foxy/foxycli.ts index 4c717810d98..c69ee6c96e6 100644 --- a/src/lib/investor/investor-foxy/foxycli.ts +++ b/src/lib/investor/investor-foxy/foxycli.ts @@ -55,9 +55,7 @@ const main = async (): Promise => { adapter: ethChainAdapter, providerUrl: process.env.ARCHIVE_NODE || 'http://127.0.0.1:8545/', foxyAddresses, - provider: new ethers.providers.StaticJsonRpcProvider( - process.env.ARCHIVE_NODE || 'http://127.0.0.1:8545/', - ), + provider: new ethers.JsonRpcProvider(process.env.ARCHIVE_NODE || 'http://127.0.0.1:8545/'), }) const accountNumber = 0 diff --git a/src/lib/market-service/foxy/foxy.test.ts b/src/lib/market-service/foxy/foxy.test.ts index d4a006b1950..b5f721092e2 100644 --- a/src/lib/market-service/foxy/foxy.test.ts +++ b/src/lib/market-service/foxy/foxy.test.ts @@ -8,7 +8,7 @@ import { FOXY_ASSET_ID, FoxyMarketService } from './foxy' import { fox, mockFoxyMarketData } from './foxyMockData' const foxyMarketService = new FoxyMarketService({ - provider: new ethers.providers.StaticJsonRpcProvider(''), + provider: new ethers.JsonRpcProvider(''), providerUrls: { jsonRpcProviderUrl: 'dummy', unchainedEthereumHttpUrl: '', diff --git a/src/lib/market-service/foxy/foxy.ts b/src/lib/market-service/foxy/foxy.ts index 712cc074629..f4087fa3d5c 100644 --- a/src/lib/market-service/foxy/foxy.ts +++ b/src/lib/market-service/foxy/foxy.ts @@ -20,14 +20,14 @@ const FOXY_ASSET_PRECISION = '18' export class FoxyMarketService extends CoinGeckoMarketService implements MarketService { providerUrls: ProviderUrls - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider constructor({ providerUrls, provider, }: { providerUrls: ProviderUrls - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider }) { super() diff --git a/src/lib/market-service/market-service-manager.ts b/src/lib/market-service/market-service-manager.ts index 736f706a075..39af57f3d47 100644 --- a/src/lib/market-service/market-service-manager.ts +++ b/src/lib/market-service/market-service-manager.ts @@ -26,7 +26,7 @@ export type ProviderUrls = { export type MarketServiceManagerArgs = { yearnChainReference: 1 | 250 | 1337 | 42161 // from @yfi/sdk providerUrls: ProviderUrls - provider: ethers.providers.StaticJsonRpcProvider + provider: ethers.JsonRpcProvider } export class MarketServiceManager { diff --git a/src/lib/market-service/market-service.test.ts b/src/lib/market-service/market-service.test.ts index 93560c39bb1..e84066c220c 100644 --- a/src/lib/market-service/market-service.test.ts +++ b/src/lib/market-service/market-service.test.ts @@ -100,7 +100,7 @@ describe('market service', () => { const marketServiceManagerArgs = { coinGeckoAPIKey: 'dummyCoingeckoApiKey', yearnChainReference: 1 as const, - provider: new ethers.providers.StaticJsonRpcProvider(''), + provider: new ethers.JsonRpcProvider(''), providerUrls: { jsonRpcProviderUrl: '', unchainedEthereumWsUrl: '', diff --git a/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts b/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts index f71ec3729d5..ae251b1e93a 100644 --- a/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts +++ b/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts @@ -7,8 +7,7 @@ import type { } from '@shapeshiftoss/swapper' import type { Asset } from '@shapeshiftoss/types' import { getConfig } from 'config' -import { ethers } from 'ethers' -import { isHexString } from 'ethers/lib/utils.js' +import { ethers, isHexString } from 'ethers' import { filterAssetIdsBySellable } from './filterAssetIdsBySellable/filterAssetIdsBySellable' import { filterBuyAssetsBySellAssetId } from './filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId' @@ -45,7 +44,7 @@ export const cowSwapper: Swapper = { // Passing the signature through split/join to normalize the `v` byte. // Some wallets do not pad it with `27`, which causes a signature failure // `splitSignature` pads it if needed, and `joinSignature` simply puts it back together - const signature = ethers.utils.joinSignature(ethers.utils.splitSignature(signatureOrderDigest)) + const signature = ethers.Signature.from(ethers.Signature.from(signatureOrderDigest)).serialized const maybeNetwork = getCowswapNetwork(chainId) if (maybeNetwork.isErr()) throw maybeNetwork.unwrapErr() diff --git a/src/lib/swapper/swappers/CowSwapper/utils/constants.ts b/src/lib/swapper/swappers/CowSwapper/utils/constants.ts index d5e04bf9b4d..6e1afaec3e5 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/constants.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/constants.ts @@ -1,5 +1,5 @@ -import { AddressZero } from '@ethersproject/constants' import { KnownChainIds } from '@shapeshiftoss/types' +import { ZeroAddress } from 'ethers' import type { CowChainId } from '../types' @@ -8,7 +8,7 @@ export const MIN_COWSWAP_USD_TRADE_VALUES_BY_CHAIN_ID: Record, ): string => { - return ethers.utils._TypedDataEncoder.hash(domain, types, data) + return TypedDataEncoder.hash(domain, types, data) } /** diff --git a/src/lib/swapper/swappers/LifiSwapper/utils/getNetworkFeeCryptoBaseUnit/getNetworkFeeCryptoBaseUnit.ts b/src/lib/swapper/swappers/LifiSwapper/utils/getNetworkFeeCryptoBaseUnit/getNetworkFeeCryptoBaseUnit.ts index e92020c10b9..17ad2b93340 100644 --- a/src/lib/swapper/swappers/LifiSwapper/utils/getNetworkFeeCryptoBaseUnit/getNetworkFeeCryptoBaseUnit.ts +++ b/src/lib/swapper/swappers/LifiSwapper/utils/getNetworkFeeCryptoBaseUnit/getNetworkFeeCryptoBaseUnit.ts @@ -2,7 +2,6 @@ import type { LifiStep } from '@lifi/types' import type { ChainId } from '@shapeshiftoss/caip' import type { EvmChainId } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' -import type { BigNumber } from 'ethers' import { ethers } from 'ethers' import { getEthersProvider } from 'lib/ethersProviderSingleton' import { assertGetEvmChainAdapter, calcNetworkFeeCryptoBaseUnit } from 'lib/utils/evm' @@ -50,7 +49,7 @@ export const getNetworkFeeCryptoBaseUnit = async ({ const contract = new ethers.Contract(OPTIMISM_GAS_ORACLE_ADDRESS, abi, provider) - const l1GasUsed = (await contract.getL1GasUsed(data)) as BigNumber + const l1GasUsed = (await contract.getL1GasUsed(data)) as BigInt return l1GasUsed.toString() })() diff --git a/src/lib/utils/evm.ts b/src/lib/utils/evm.ts index 726b6719e92..8f9c1ba3537 100644 --- a/src/lib/utils/evm.ts +++ b/src/lib/utils/evm.ts @@ -220,7 +220,7 @@ export const getApproveContractData = ({ spender, chainId, }: GetApproveContractDataArgs): string => { - const address = ethers.utils.getAddress(to) + const address = ethers.getAddress(to) const contract = getOrCreateContractByType({ address, type: ContractType.ERC20, diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx index c629dddafa0..d55b7f8a02b 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx @@ -21,7 +21,7 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { utils } from 'ethers' +import { hexlify, toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' @@ -299,7 +299,7 @@ export const BorrowConfirm = ({ sendMax: false, accountId: collateralAccountId, memo: supportedEvmChainIds.includes(fromAssetId(collateralAssetId).chainId as KnownChainIds) - ? utils.hexlify(utils.toUtf8Bytes(confirmedQuote.quoteMemo)) + ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index e1206704bfc..d9dd9c1a964 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -23,7 +23,7 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { utils } from 'ethers' +import { hexlify, toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' @@ -290,7 +290,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset.assetId).chainId as KnownChainIds, ) - ? utils.hexlify(utils.toUtf8Bytes(confirmedQuote.quoteMemo)) + ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, to: confirmedQuote.quoteInboundAddress, sendMax: false, @@ -342,7 +342,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset?.assetId).chainId as KnownChainIds, ) - ? utils.hexlify(utils.toUtf8Bytes(confirmedQuote.quoteMemo)) + ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx index b8c460db866..394efab874e 100644 --- a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx +++ b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx @@ -9,7 +9,6 @@ import { Link, Skeleton, } from '@chakra-ui/react' -import { AddressZero } from '@ethersproject/constants' import type { AccountId, ChainId } from '@shapeshiftoss/caip' import { type AssetId, @@ -28,6 +27,7 @@ import type { KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import dayjs from 'dayjs' +import { ZeroAddress } from 'ethers' import { useCallback, useEffect, useMemo, useState } from 'react' import { FaCheck } from 'react-icons/fa' import { useTranslate } from 'react-polyglot' @@ -287,7 +287,7 @@ export const TransactionRow: React.FC = ({ if (!inboundAddressData?.router) return undefined const assetAddress = isToken(fromAssetId(assetId).assetReference) ? getAddress(fromAssetId(assetId).assetReference) - : AddressZero + : ZeroAddress const amount = BigInt(toBaseUnit(amountCryptoPrecision, asset.precision).toString()) const args = (() => { @@ -297,7 +297,7 @@ export const TransactionRow: React.FC = ({ ? getAddress(fromAssetId(assetId).assetReference) : // Native EVM assets use the 0 address as the asset address // https://dev.thorchain.org/concepts/sending-transactions.html#admonition-info-1 - AddressZero + ZeroAddress const memo = `+:${thorchainNotationAssetId}:${otherAssetAddress ?? ''}:ss:${ confirmedQuote.feeBps @@ -472,7 +472,7 @@ export const TransactionRow: React.FC = ({ ? getAddress(fromAssetId(assetId).assetReference) : // Native EVM assets use the 0 address as the asset address // https://dev.thorchain.org/concepts/sending-transactions.html#admonition-info-1 - AddressZero + ZeroAddress const memo = `+:${thorchainNotationAssetId}:${otherAssetAddress ?? ''}:ss:${ confirmedQuote.feeBps diff --git a/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx b/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx index 23d8f422f56..893ca7f3ad8 100644 --- a/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx +++ b/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx @@ -1,6 +1,7 @@ import { Box, Divider, Flex, HStack, useColorModeValue } from '@chakra-ui/react' -import type { ParamType, TransactionDescription } from '@ethersproject/abi' +import type { ParamType } from '@ethersproject/abi' import type { Asset } from '@shapeshiftoss/types' +import type { TransactionDescription } from 'ethers' import startCase from 'lodash/startCase' import { CopyButton } from 'plugins/walletConnectToDapps/components/modals/CopyButton' import { ExternalLinkButton } from 'plugins/walletConnectToDapps/components/modals/ExternalLinkButtons' @@ -35,13 +36,13 @@ export const ContractInteractionBreakdown: FC }) => { const contractInterface = useGetAbi(request) - const transaction: TransactionDescription | undefined = useMemo(() => { - if (!contractInterface) return undefined + const transaction: TransactionDescription | null = useMemo(() => { + if (!contractInterface) return null try { return contractInterface?.parseTransaction({ data: request.data, value: request.value }) } catch (e) { console.error(e) - return undefined + return null } }, [contractInterface, request.data, request.value]) diff --git a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx index c41df7d08b0..d2a11542bfc 100644 --- a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx +++ b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx @@ -1,8 +1,9 @@ import { skipToken } from '@reduxjs/toolkit/query' -import { getConfig } from 'config' +import { KnownChainIds } from '@shapeshiftoss/types' import { ethers } from 'ethers' import type { TransactionParams } from 'plugins/walletConnectToDapps/types' import { useEffect, useMemo, useState } from 'react' +import { getEthersProvider } from 'lib/ethersProviderSingleton' import { useGetContractAbiQuery } from 'state/apis/abi/abiApi' /* @@ -19,22 +20,17 @@ enum PROXY_CONTRACT_METHOD_NAME { const EIP1967_IMPLEMENTATION_SLOT = '0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc' -export const useGetAbi = ( - transactionParams: TransactionParams, -): ethers.utils.Interface | undefined => { +export const useGetAbi = (transactionParams: TransactionParams): ethers.Interface | undefined => { const [proxyContractImplementation, setProxyContractImplementation] = useState( null, ) const { to: contractAddress, data } = transactionParams - const provider = useMemo( - () => new ethers.providers.StaticJsonRpcProvider(getConfig().REACT_APP_ETHEREUM_NODE_URL), - [], - ) + const provider = useMemo(() => getEthersProvider(KnownChainIds.EthereumMainnet), []) const { data: rootContractRawAbiData } = useGetContractAbiQuery(contractAddress) const rootContractInterface = useMemo( - () => (rootContractRawAbiData ? new ethers.utils.Interface(rootContractRawAbiData) : undefined), + () => (rootContractRawAbiData ? new ethers.Interface(rootContractRawAbiData) : undefined), [rootContractRawAbiData], ) @@ -52,6 +48,7 @@ export const useGetAbi = ( // check for proxy methods on the root interface let proxyFunctionNameIfExists: string | undefined if (rootContractInterface) { + // TODO(gomes): how to do this with v6? looks like we should probably map over fragments, and then map over functions const rootFunctions = Object.values(rootContractInterface.functions) proxyFunctionNameIfExists = Object.values(PROXY_CONTRACT_METHOD_NAME).find(x => rootFunctions.find(y => y.name === x), @@ -67,14 +64,12 @@ export const useGetAbi = ( await rootContractWithProvider?.getFunctionImplementation(sighash) break case PROXY_CONTRACT_METHOD_NAME.EIP1967: - const paddedImplementationAddress = await provider.getStorageAt( + const paddedImplementationAddress = await provider.getStorage( contractAddress, EIP1967_IMPLEMENTATION_SLOT, ) // Remove the first 26 chars (64 hex digits) - implementationAddress = ethers.utils.getAddress( - paddedImplementationAddress.substring(26), - ) + implementationAddress = ethers.getAddress(paddedImplementationAddress.substring(26)) break default: implementationAddress = null @@ -96,7 +91,7 @@ export const useGetAbi = ( const implementationContractInterface = useMemo( () => contractImplementationRawAbiData - ? new ethers.utils.Interface(contractImplementationRawAbiData) + ? new ethers.Interface(contractImplementationRawAbiData) : undefined, [contractImplementationRawAbiData], ) diff --git a/src/plugins/walletConnectToDapps/utils.ts b/src/plugins/walletConnectToDapps/utils.ts index 3521c683f94..160e9535539 100644 --- a/src/plugins/walletConnectToDapps/utils.ts +++ b/src/plugins/walletConnectToDapps/utils.ts @@ -8,7 +8,7 @@ import type { GetFeeDataInput, } from '@shapeshiftoss/chain-adapters' import type { SessionTypes } from '@walletconnect/types' -import { utils } from 'ethers' +import { isAddress, isHexString, toBeHex, toUtf8String } from 'ethers' import type { ConfirmData, CosmosSignAminoCallRequestParams, @@ -26,7 +26,7 @@ import { isSome } from 'lib/utils' */ export const maybeConvertHexEncodedMessageToUtf8 = (value: string) => { try { - return utils.isHexString(value) ? utils.toUtf8String(value) : value + return isHexString(value) ? toUtf8String(value) : value } catch (e) { // use raw hex string if unable to convert to utf8 (ex. keccak256) return value @@ -34,7 +34,7 @@ export const maybeConvertHexEncodedMessageToUtf8 = (value: string) => { } export const convertNumberToHex = (value: number | string): string => - typeof value === 'number' ? utils.hexlify(value) : utils.hexlify(utils.hexlify(parseInt(value))) + typeof value === 'number' ? toBeHex(value) : toBeHex(parseInt(value)) export const convertHexToNumber = (value: string): number => parseInt(value, 16) @@ -81,7 +81,7 @@ export const getGasData = ( * If it is a hex string, it gets converted to utf8 string */ export const getSignParamsMessage = (params: [string, string], toUtf8: boolean) => { - const message = params.filter(p => !utils.isAddress(p))[0] + const message = params.filter(p => !isAddress(p))[0] return toUtf8 ? maybeConvertHexEncodedMessageToUtf8(message) : message } diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 14f30c4bb95..004df1fb3fa 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -1,7 +1,7 @@ import { type AccountId, type AssetId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset, KnownChainIds, MarketData } from '@shapeshiftoss/types' import { useQuery } from '@tanstack/react-query' -import { utils } from 'ethers' +import { hexlify, toUtf8Bytes } from 'ethers' import { useMemo } from 'react' import type { EstimateFeesInput } from 'components/Modals/Send/utils' import { estimateFees } from 'components/Modals/Send/utils' @@ -71,7 +71,7 @@ export const useQuoteEstimatedFeesQuery = ({ confirmedQuote && 'quoteMemo' in confirmedQuote ? confirmedQuote.quoteMemo : '' const memo = assetId && supportedEvmChainIds.includes(fromAssetId(assetId).chainId as KnownChainIds) - ? utils.hexlify(utils.toUtf8Bytes(quoteMemo)) + ? hexlify(toUtf8Bytes(quoteMemo)) : quoteMemo const to = confirmedQuote && 'quoteInboundAddress' in confirmedQuote diff --git a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts index 962d6c4ac2a..1e54f9d820b 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts @@ -4,7 +4,7 @@ import type { TokenAmount } from '@uniswap/sdk' import { WETH_TOKEN_CONTRACT_ADDRESS } from 'contracts/constants' import { fetchUniV2PairData, getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ethers } from 'ethers' +import { getAddress } from 'ethers' import type { BN } from 'lib/bignumber/bignumber' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { getEthersProvider } from 'lib/ethersProviderSingleton' @@ -131,8 +131,8 @@ export const uniV2LpOpportunitiesMetadataResolver = async ({ token1Decimals = zapperAppBalanceData.tokens?.[1].decimals! token0Reserves = bnOrZero(zapperAppBalanceData.dataProps?.reserves?.[0])! token1Reserves = bnOrZero(zapperAppBalanceData.dataProps?.reserves?.[1])! - token0Address = ethers.utils.getAddress(zapperAppBalanceData?.tokens?.[0].address!) - token1Address = ethers.utils.getAddress(zapperAppBalanceData?.tokens?.[1].address!) + token0Address = getAddress(zapperAppBalanceData?.tokens?.[0].address!) + token1Address = getAddress(zapperAppBalanceData?.tokens?.[1].address!) apr = bnOrZero(zapperAppBalanceData.dataProps?.apy!).toFixed() return { token0Decimals, @@ -191,7 +191,7 @@ export const uniV2LpOpportunitiesMetadataResolver = async ({ const { assetReference } = fromAssetId(opportunityId) // Checksum - const contractAddress = ethers.utils.getAddress(assetReference) + const contractAddress = getAddress(assetReference) const uniV2LPContract = getOrCreateContractByType({ address: contractAddress, type: ContractType.UniV2Pair, diff --git a/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts b/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts index eecc910b366..36e6ee2ed61 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts @@ -5,7 +5,7 @@ import type { TokenAmount } from '@uniswap/sdk' import type { IUniswapV2Pair } from 'contracts/abis/IUniswapV2Pair' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ethers } from 'ethers' +import { getAddress } from 'ethers' import memoize from 'lodash/memoize' import type { GetContractReturnType, PublicClient, WalletClient } from 'viem' import { parseAbiItem } from 'viem' @@ -65,7 +65,7 @@ export const calculateAPRFromToken0 = memoize( const { assetReference } = fromAssetId(pairAssetId) // Checksum - const contractAddress = ethers.utils.getAddress(assetReference) + const contractAddress = getAddress(assetReference) const pair = getOrCreateContractByType({ address: contractAddress, type: ContractType.UniV2Pair, diff --git a/src/test/mocks/txs.ts b/src/test/mocks/txs.ts index cf877b0a70e..11cd812b582 100644 --- a/src/test/mocks/txs.ts +++ b/src/test/mocks/txs.ts @@ -1,7 +1,7 @@ -import { AddressZero } from '@ethersproject/constants' import { ethAssetId, ethChainId, foxAssetId } from '@shapeshiftoss/caip' import { UtxoAccountType } from '@shapeshiftoss/types' import { Dex, TradeType, TransferType, TxStatus } from '@shapeshiftoss/unchained-client' +import { ZeroAddress } from 'ethers' import type { Tx } from 'state/slices/txHistorySlice/txHistorySlice' export const EthSend: Tx = { @@ -119,7 +119,7 @@ export const TradeTx: Tx = { transfers: [ { assetId: 'eip155:1/erc20:0x5f18c75abdae578b483e5f43f12a39cf75b973a9', - from: [AddressZero], + from: [ZeroAddress], to: ['0x934be745172066EDF795ffc5EA9F28f19b440c63'], type: TransferType.Receive, value: '9178352', @@ -315,7 +315,7 @@ export const yearnVaultDeposit: Tx = { transfers: [ { assetId: 'eip155:1/erc20:0x5f18c75abdae578b483e5f43f12a39cf75b973a9', - from: [AddressZero], + from: [ZeroAddress], to: ['0x934be745172066EDF795ffc5EA9F28f19b440c63'], type: TransferType.Receive, value: '9178352', @@ -353,7 +353,7 @@ export const createMockEthTxs = (account: string): Tx[] => { }, { assetId: 'eip155:1/erc20:0xfbeb78a723b8087fd2ea7ef1afec93d35e8bed42', - from: [AddressZero], + from: [ZeroAddress], to: [account], type: TransferType.Receive, value: '5481290118862792961', @@ -378,7 +378,7 @@ export const createMockEthTxs = (account: string): Tx[] => { { assetId: 'eip155:1/erc20:0xfbeb78a723b8087fd2ea7ef1afec93d35e8bed42', from: [account], - to: [AddressZero], + to: [ZeroAddress], type: TransferType.Send, value: '5481290118862792961', }, diff --git a/yarn.lock b/yarn.lock index 21b42e77066..44266a80502 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,13 @@ __metadata: languageName: node linkType: hard +"@adraffy/ens-normalize@npm:1.10.1": + version: 1.10.1 + resolution: "@adraffy/ens-normalize@npm:1.10.1" + checksum: 0836f394ea256972ec19a0b5e78cb7f5bcdfd48d8a32c7478afc94dd53ae44c04d1aa2303d7f3077b4f3ac2323b1f557ab9188e8059978748fdcd83e04a80dcc + languageName: node + linkType: hard + "@adraffy/ens-normalize@npm:1.9.4": version: 1.9.4 resolution: "@adraffy/ens-normalize@npm:1.9.4" @@ -10093,7 +10100,7 @@ __metadata: eslint-plugin-react-memo: ^0.0.3 eslint-plugin-simple-import-sort: ^10.0.0 eth-url-parser: ^1.0.4 - ethers: ^5.7.2 + ethers: ^6.11.1 express: ^4.18.2 fast-json-stable-stringify: ^2.1.0 framer-motion: ^11.0.3 @@ -11732,6 +11739,13 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:18.15.13": + version: 18.15.13 + resolution: "@types/node@npm:18.15.13" + checksum: 79cc5a2b5f98e8973061a4260a781425efd39161a0e117a69cd089603964816c1a14025e1387b4590c8e82d05133b7b4154fa53a7dffb3877890a66145e76515 + languageName: node + linkType: hard + "@types/node@npm:>= 8, @types/node@npm:^20.2.5": version: 20.8.4 resolution: "@types/node@npm:20.8.4" @@ -14489,6 +14503,13 @@ __metadata: languageName: node linkType: hard +"aes-js@npm:4.0.0-beta.5": + version: 4.0.0-beta.5 + resolution: "aes-js@npm:4.0.0-beta.5" + checksum: cc2ea969d77df939c32057f7e361b6530aa6cb93cb10617a17a45cd164e6d761002f031ff6330af3e67e58b1f0a3a8fd0b63a720afd591a653b02f649470e15b + languageName: node + linkType: hard + "aes-js@npm:^3.1.2": version: 3.1.2 resolution: "aes-js@npm:3.1.2" @@ -21093,6 +21114,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.11.1": + version: 6.11.1 + resolution: "ethers@npm:6.11.1" + 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.5.0 + checksum: e8027c5071ad0370c61a1978f0602ab950d840c5923948f55e88b9808300e4e02e792bb793ea109ce7fa0e748f30a40a05f1202204a2b0402cdffbcb64a218e4 + languageName: node + linkType: hard + "ethjs-unit@npm:0.1.6, ethjs-unit@npm:^0.1.6": version: 0.1.6 resolution: "ethjs-unit@npm:0.1.6" @@ -36781,6 +36817,21 @@ pvutils@latest: languageName: node linkType: hard +"ws@npm:8.5.0": + version: 8.5.0 + resolution: "ws@npm:8.5.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 76f2f90e40344bf18fd544194e7067812fb1372b2a37865678d8f12afe4b478ff2ebc0c7c0aff82cd5e6b66fc43d889eec0f1865c2365d8f7a66d92da7744a77 + languageName: node + linkType: hard + "ws@npm:^3.2.0": version: 3.3.3 resolution: "ws@npm:3.3.3" From 67045477a44a6427eb1c0b445cc5b3813a32057e Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:52:08 +0100 Subject: [PATCH 02/60] feat: fragments bs --- scripts/generateAssetData/ethereum/yearnVaults.ts | 4 ++++ src/components/Layout/Header/NavBar/ChainMenu.tsx | 4 ++-- src/components/Layout/Header/NavBar/Notifications.tsx | 4 ++-- src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/scripts/generateAssetData/ethereum/yearnVaults.ts b/scripts/generateAssetData/ethereum/yearnVaults.ts index e93412e3065..cd5583ecda1 100644 --- a/scripts/generateAssetData/ethereum/yearnVaults.ts +++ b/scripts/generateAssetData/ethereum/yearnVaults.ts @@ -9,7 +9,11 @@ import { ethereum } from '../baseAssets' import { colorMap } from '../colorMap' const network = 1 // 1 for mainnet +// This is wrong, but this doesn't matter since yearn is nuked +// 1. we should not instantiate a provider at module scope, which will make an XHR for nothing when this module gets evaluated +// 2. we should pass the provider in as a dependency, since it is cached in web const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NODE_URL) +// @ts-ignore @yfi/sdk expects an ethers v5 provider, but we're now using v6 export const yearnSdk = new Yearn(network, { provider }) const explorerData = { diff --git a/src/components/Layout/Header/NavBar/ChainMenu.tsx b/src/components/Layout/Header/NavBar/ChainMenu.tsx index 1d93965b347..17b4cda2212 100644 --- a/src/components/Layout/Header/NavBar/ChainMenu.tsx +++ b/src/components/Layout/Header/NavBar/ChainMenu.tsx @@ -17,7 +17,7 @@ import type { ChainId } from '@shapeshiftoss/caip' import { fromChainId, gnosisChainId } from '@shapeshiftoss/caip' import type { ETHWallet } from '@shapeshiftoss/hdwallet-core' import { supportsEthSwitchChain } from '@shapeshiftoss/hdwallet-core' -import { utils } from 'ethers' +import { toQuantity } from 'ethers' import { memo, useCallback, useMemo } from 'react' import { useTranslate } from 'react-polyglot' import { AssetIcon } from 'components/AssetIcon' @@ -106,7 +106,7 @@ export const ChainMenu = memo((props: ChainMenuProps) => { requestedChainId === gnosisChainId ? ['https://rpc.gnosischain.com'] : [] const requestedChainRpcUrl = requestedChainChainAdapter.getRpcUrl() await (state.wallet as ETHWallet).ethSwitchChain?.({ - chainId: utils.hexValue(Number(requestedEthNetwork)), + chainId: toQuantity(Number(requestedEthNetwork)), chainName: requestedChainChainAdapter.getDisplayName(), nativeCurrency: { name: requestedChainFeeAsset.name, diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index b95fb7e4423..6731eba9975 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -3,7 +3,7 @@ import type { BIP32Path, ETHSignTypedData } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { CustomTheme, ThemeMode as ThemeModeType } from '@wherever/react-notification-feed' import { getConfig } from 'config' -import { utils } from 'ethers' +import { toQuantity, toUtf8Bytes } from 'ethers' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { KeyManager } from 'context/WalletProvider/KeyManager' @@ -92,7 +92,7 @@ export const Notifications = memo(() => { try { const signedMsg = await wallet.ethSignMessage({ addressNList, - message: utils.hexlify(utils.toUtf8Bytes(message)), + message: toQuantity(toUtf8Bytes(message)), }) return signedMsg?.signature diff --git a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx index d2a11542bfc..db88d3c2879 100644 --- a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx +++ b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx @@ -1,6 +1,6 @@ import { skipToken } from '@reduxjs/toolkit/query' import { KnownChainIds } from '@shapeshiftoss/types' -import { ethers } from 'ethers' +import { ethers, Fragment } from 'ethers' import type { TransactionParams } from 'plugins/walletConnectToDapps/types' import { useEffect, useMemo, useState } from 'react' import { getEthersProvider } from 'lib/ethersProviderSingleton' @@ -49,7 +49,7 @@ export const useGetAbi = (transactionParams: TransactionParams): ethers.Interfac let proxyFunctionNameIfExists: string | undefined if (rootContractInterface) { // TODO(gomes): how to do this with v6? looks like we should probably map over fragments, and then map over functions - const rootFunctions = Object.values(rootContractInterface.functions) + const rootFunctions = rootContractInterface.fragments.filter(Fragment.isFunction) proxyFunctionNameIfExists = Object.values(PROXY_CONTRACT_METHOD_NAME).find(x => rootFunctions.find(y => y.name === x), ) From 4c1223ff2f9e8fdf75fc897c1b43c9581eb1a9cb Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:22:16 +0100 Subject: [PATCH 03/60] feat: almost there --- src/context/WalletProvider/WalletProvider.tsx | 4 ++-- .../FoxyManager/Withdraw/components/Confirm.tsx | 15 +++++++++------ .../Deposit/components/Confirm.tsx | 6 +++--- .../Withdraw/components/Confirm.tsx | 2 +- .../UniV2Manager/Deposit/components/Approve.tsx | 7 +++---- .../UniV2Manager/Withdraw/components/Approve.tsx | 3 ++- .../useIsSnapInstalled/useIsSnapInstalled.tsx | 9 +++++---- src/lib/ethersProviderSingleton.ts | 2 +- src/lib/investor/investor-foxy/abi/erc20-abi.ts | 4 ++-- src/lib/investor/investor-foxy/abi/foxy-abi.ts | 4 ++-- .../investor-foxy/abi/foxy-staking-abi.ts | 4 ++-- .../investor-foxy/abi/liquidity-reserve-abi.ts | 4 ++-- .../investor-foxy/abi/toke-manager-abi.ts | 4 ++-- .../investor/investor-foxy/abi/toke-pool-abi.ts | 4 ++-- .../investor-foxy/abi/toke-reward-hash-abi.ts | 4 ++-- src/lib/investor/investor-foxy/api/api.ts | 15 +++++++++++---- .../modals/ContractInteractionBreakdown.tsx | 5 ++--- 17 files changed, 53 insertions(+), 43 deletions(-) diff --git a/src/context/WalletProvider/WalletProvider.tsx b/src/context/WalletProvider/WalletProvider.tsx index a56d76fcf94..1e2f22404c1 100644 --- a/src/context/WalletProvider/WalletProvider.tsx +++ b/src/context/WalletProvider/WalletProvider.tsx @@ -8,7 +8,7 @@ import type { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import { Dummy } from '@shapeshiftoss/hdwallet-native/dist/crypto/isolation/engines' import type { EthereumProvider as EthereumProviderType } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider' import { PublicWalletXpubs } from 'constants/PublicWalletXpubs' -import type { providers } from 'ethers' +import type { BrowserProvider } from 'ethers' import findIndex from 'lodash/findIndex' import omit from 'lodash/omit' import React, { useCallback, useEffect, useMemo, useReducer } from 'react' @@ -73,7 +73,7 @@ const initialDeviceState: DeviceState = { isUpdatingPin: false, isDeviceLoading: false, } -export type MetaMaskLikeProvider = providers.Web3Provider +export type MetaMaskLikeProvider = BrowserProvider // A subset of wallets which have an EIP-1193-like provider export type KeyManagerWithProvider = diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/components/Confirm.tsx index 4adee13f16e..b7910700f64 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/components/Confirm.tsx @@ -3,7 +3,7 @@ import type { AccountId } from '@shapeshiftoss/caip' import { fromAccountId } from '@shapeshiftoss/caip' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import { WithdrawType } from '@shapeshiftoss/types' -import type { ethers } from 'ethers' +import type { TransactionReceipt, TransactionReceiptParams } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' @@ -34,7 +34,7 @@ export const Confirm: React.FC { - const { poll } = usePoll() + const { poll } = usePoll() const foxyApi = getFoxyApi() const { state, dispatch } = useContext(WithdrawContext) const translate = useTranslate() @@ -103,16 +103,19 @@ export const Confirm: React.FC foxyApi.getTxReceipt({ txid }), - validate: (result: ethers.providers.TransactionReceipt) => !isNil(result), + validate: (result: TransactionReceipt | null) => !isNil(result), interval: 15000, maxAttempts: 30, }) dispatch({ type: FoxyWithdrawActionType.SET_WITHDRAW, payload: { - txStatus: transactionReceipt.status ? 'success' : 'failed', - usedGasFeeCryptoBaseUnit: transactionReceipt.effectiveGasPrice - .mul(transactionReceipt.gasUsed) + txStatus: transactionReceipt?.status ? 'success' : 'failed', + usedGasFeeCryptoBaseUnit: bnOrZero( + // Types are drunk here, TransactionReceipt *does* implement TransactionReceiptParams but things are not narrowed down properly for some reason + (transactionReceipt as TransactionReceiptParams | null)?.effectiveGasPrice?.toString(), + ) + .times(bnOrZero(transactionReceipt?.gasUsed?.toString())) .toString(), }, }) diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index 2635d197611..82b2609fe71 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -18,7 +18,7 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { utils } from 'ethers' +import { toQuantity, toUtf8Bytes } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import type { @@ -258,7 +258,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { from: maybeFromUTXOAccountAddress, to: quote.inbound_address, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? utils.hexlify(utils.toUtf8Bytes(memoUtf8)) + ? toQuantity(toUtf8Bytes(memoUtf8)) : memoUtf8, sendMax: Boolean(!isUtxoChainId(chainId) && state?.deposit.sendMax), accountId, @@ -477,7 +477,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { sendMax: Boolean(state?.deposit.sendMax), accountId, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? utils.hexlify(utils.toUtf8Bytes(memoUtf8)) + ? toQuantity(toUtf8Bytes(memoUtf8)) : memoUtf8, amountFieldError: '', estimatedFees, diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx index d73b1763fe1..7ec5e7b87f8 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx @@ -415,7 +415,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - ZeroAddress, + getAddress(ZeroAddress), BigInt(amount), quote.memo, BigInt(quote.expiry), diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx index 618e91b741c..f7e9101b85e 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Approve.tsx @@ -3,7 +3,6 @@ import type { AccountId } from '@shapeshiftoss/caip' import { ethAssetId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import { UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS } from 'contracts/constants' -import { ethers } from 'ethers' import { Approve as ReusableApprove } from 'features/defi/components/Approve/Approve' import { ApprovePreFooter } from 'features/defi/components/Approve/ApprovePreFooter' import type { @@ -15,7 +14,7 @@ import { canCoverTxFees } from 'features/defi/helpers/utils' import { useUniV2LiquidityPool } from 'features/defi/providers/univ2/hooks/useUniV2LiquidityPool' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' -import type { Address } from 'viem' +import { type Address, getAddress } from 'viem' import type { StepComponentProps } from 'components/DeFi/components/Steps' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' import { usePoll } from 'hooks/usePoll/usePoll' @@ -101,11 +100,11 @@ export const Approve: React.FC = ({ accountId, onNext }) => { const asset0ContractAddress = useMemo(() => { if (assetId0 === ethAssetId) return undefined - return ethersgetAddress(fromAssetId(assetId0).assetReference) + return getAddress(fromAssetId(assetId0).assetReference) }, [assetId0]) const asset1ContractAddress = useMemo(() => { if (assetId1 === ethAssetId) return undefined - return ethers.getAddress(fromAssetId(assetId1).assetReference) + return getAddress(fromAssetId(assetId1).assetReference) }, [assetId1]) const neededApprovals = [ isApprove0Needed && asset0ContractAddress, diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx index 3e11fb5e90b..0024590a8e0 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx @@ -15,6 +15,7 @@ import { canCoverTxFees } from 'features/defi/helpers/utils' import { useUniV2LiquidityPool } from 'features/defi/providers/univ2/hooks/useUniV2LiquidityPool' import { useCallback, useContext, useEffect, useMemo } from 'react' import { useTranslate } from 'react-polyglot' +import { getAddress } from 'viem' import type { StepComponentProps } from 'components/DeFi/components/Steps' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' import { usePoll } from 'hooks/usePoll/usePoll' @@ -113,7 +114,7 @@ export const Approve: React.FC = ({ accountId, onNext }) => { try { dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: true }) const lpAssetContractAddress = ethers.getAddress(fromAssetId(lpAssetId).assetReference) - await approveAsset(lpAssetContractAddress) + await approveAsset(getAddress(lpAssetContractAddress)) await poll({ fn: () => lpAllowance(), validate: (result: string) => { diff --git a/src/hooks/useIsSnapInstalled/useIsSnapInstalled.tsx b/src/hooks/useIsSnapInstalled/useIsSnapInstalled.tsx index c50d6fcc34b..b5728c4d95c 100644 --- a/src/hooks/useIsSnapInstalled/useIsSnapInstalled.tsx +++ b/src/hooks/useIsSnapInstalled/useIsSnapInstalled.tsx @@ -3,7 +3,7 @@ import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { MetaMaskShapeShiftMultiChainHDWallet } from '@shapeshiftoss/hdwallet-shapeshift-multichain' import { shapeShiftSnapInstalled } from '@shapeshiftoss/metamask-snaps-adapter' import { getConfig } from 'config' -import type { providers } from 'ethers' +import type { Eip1193Provider } from 'ethers' import pDebounce from 'p-debounce' import pMemoize from 'p-memoize' import { useCallback, useEffect, useState } from 'react' @@ -87,9 +87,10 @@ export const checkIsMetaMask = pMemoize( // We don't want to run this hook altogether if using any wallet other than MM if (!isMetaMaskMultichainWallet) return false - const provider = (await detectEthereumProvider()) as providers.ExternalProvider + const provider = (await detectEthereumProvider()) as Eip1193Provider // MetaMask impersonators don't support the methods we need to check for snap installation, and will throw - if (!provider.isMetaMask) return false + // `as any` because isMetaMask is gone from the providers in ethers v6 + if (!(provider as any).isMetaMask) return false return true }, @@ -104,7 +105,7 @@ export const checkIsMetaMaskImpersonator = pMemoize( // We don't want to run this hook altogether if using any wallet other than MM if (!isMetaMaskMultichainWallet) return false - const provider = (await detectEthereumProvider()) as providers.ExternalProvider + const provider = (await detectEthereumProvider()) as Eip1193Provider // Some impersonators really like to make it difficult for us to detect *actual* MetaMask // Note, checking for the truthiness of the value isn't enough - some impersonators have the key present but undefined // This is weird, but welcome to the world of web3 diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index a7534ece35d..dfd7161bf9e 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -2,7 +2,7 @@ import type { ChainId } from '@shapeshiftoss/caip' import type { EvmChainId } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' -import { JsonRpcProvider, providers } from 'ethers' +import { JsonRpcProvider } from 'ethers' import { assertUnreachable } from './utils' diff --git a/src/lib/investor/investor-foxy/abi/erc20-abi.ts b/src/lib/investor/investor-foxy/abi/erc20-abi.ts index ae7e19c78ef..33b361e15e0 100644 --- a/src/lib/investor/investor-foxy/abi/erc20-abi.ts +++ b/src/lib/investor/investor-foxy/abi/erc20-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const erc20Abi: ContractInterface = [ +export const erc20Abi: InterfaceAbi = [ { constant: true, inputs: [], diff --git a/src/lib/investor/investor-foxy/abi/foxy-abi.ts b/src/lib/investor/investor-foxy/abi/foxy-abi.ts index 99522a88a09..35c59c92f97 100644 --- a/src/lib/investor/investor-foxy/abi/foxy-abi.ts +++ b/src/lib/investor/investor-foxy/abi/foxy-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const foxyAbi: ContractInterface = [ +export const foxyAbi: InterfaceAbi = [ { inputs: [], stateMutability: 'nonpayable', diff --git a/src/lib/investor/investor-foxy/abi/foxy-staking-abi.ts b/src/lib/investor/investor-foxy/abi/foxy-staking-abi.ts index 0d62f0aae71..659c34beb4b 100644 --- a/src/lib/investor/investor-foxy/abi/foxy-staking-abi.ts +++ b/src/lib/investor/investor-foxy/abi/foxy-staking-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const foxyStakingAbi: ContractInterface = [ +export const foxyStakingAbi: InterfaceAbi = [ { inputs: [ { diff --git a/src/lib/investor/investor-foxy/abi/liquidity-reserve-abi.ts b/src/lib/investor/investor-foxy/abi/liquidity-reserve-abi.ts index 4cea3c40602..c27ffe98eb8 100644 --- a/src/lib/investor/investor-foxy/abi/liquidity-reserve-abi.ts +++ b/src/lib/investor/investor-foxy/abi/liquidity-reserve-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const liquidityReserveAbi: ContractInterface = [ +export const liquidityReserveAbi: InterfaceAbi = [ { inputs: [ { diff --git a/src/lib/investor/investor-foxy/abi/toke-manager-abi.ts b/src/lib/investor/investor-foxy/abi/toke-manager-abi.ts index a4a5250015e..05fa03c7b39 100644 --- a/src/lib/investor/investor-foxy/abi/toke-manager-abi.ts +++ b/src/lib/investor/investor-foxy/abi/toke-manager-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const tokeManagerAbi: ContractInterface = [ +export const tokeManagerAbi: InterfaceAbi = [ { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, diff --git a/src/lib/investor/investor-foxy/abi/toke-pool-abi.ts b/src/lib/investor/investor-foxy/abi/toke-pool-abi.ts index 4ef28248b05..365958d9ec6 100644 --- a/src/lib/investor/investor-foxy/abi/toke-pool-abi.ts +++ b/src/lib/investor/investor-foxy/abi/toke-pool-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const tokePoolAbi: ContractInterface = [ +export const tokePoolAbi: InterfaceAbi = [ { anonymous: false, inputs: [ diff --git a/src/lib/investor/investor-foxy/abi/toke-reward-hash-abi.ts b/src/lib/investor/investor-foxy/abi/toke-reward-hash-abi.ts index c2d62f9274c..de4e9189d26 100644 --- a/src/lib/investor/investor-foxy/abi/toke-reward-hash-abi.ts +++ b/src/lib/investor/investor-foxy/abi/toke-reward-hash-abi.ts @@ -1,6 +1,6 @@ -import type { ContractInterface } from 'ethers' +import type { InterfaceAbi } from 'ethers' -export const tokeRewardHashAbi: ContractInterface = [ +export const tokeRewardHashAbi: InterfaceAbi = [ { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 143b09c0ffa..77092392ba7 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -10,6 +10,7 @@ import { import { KnownChainIds, WithdrawType } from '@shapeshiftoss/types' import axios from 'axios' import type { BigNumber } from 'bignumber.js' +import type { TransactionReceipt } from 'ethers' import { ethers } from 'ethers' import { toLower } from 'lodash' import { bn, bnOrZero } from 'lib/bignumber/bignumber' @@ -192,7 +193,9 @@ export class FoxyApi { private getStakingContract(contractAddress: string): ethers.Contract { const stakingContract = this.foxyStakingContracts.find( - item => toLower(item.address) === toLower(contractAddress), + // This can be string | Addressable, where Addressable is an object containing getAddress() + // for ENS names. We can safely narrow it down to a string, as we do not instantiate contracts with an ens name. + item => toLower(item.target as string) === toLower(contractAddress), ) if (!stakingContract) throw new Error('Not a valid contract address') return stakingContract @@ -200,7 +203,9 @@ export class FoxyApi { private getLiquidityReserveContract(liquidityReserveAddress: string): ethers.Contract { const liquidityReserveContract = this.liquidityReserveContracts.find( - item => toLower(item.address) === toLower(liquidityReserveAddress), + // This can be string | Addressable, where Addressable is an object containing getAddress() + // for ENS names. We can safely narrow it down to a string, as we do not instantiate contracts with an ens name. + item => toLower(item.target as string) === toLower(liquidityReserveAddress), ) if (!liquidityReserveContract) throw new Error('Not a valid reserve contract address') return liquidityReserveContract @@ -211,7 +216,9 @@ export class FoxyApi { const opportunities = await Promise.all( this.foxyAddresses.map(async addresses => { const stakingContract = this.foxyStakingContracts.find( - item => toLower(item.address) === toLower(addresses.staking), + // This can be string | Addressable, where Addressable is an object containing getAddress() + // for ENS names. We can safely narrow it down to a string, as we do not instantiate contracts with an ens name. + item => toLower(item.target as string) === toLower(addresses.staking), ) try { const expired = await stakingContract?.pauseStaking() @@ -248,7 +255,7 @@ export class FoxyApi { } } - getTxReceipt({ txid }: TxReceipt): Promise { + getTxReceipt({ txid }: TxReceipt): Promise { if (!txid) throw new Error('Must pass txid') return this.provider.getTransactionReceipt(txid) } diff --git a/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx b/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx index 893ca7f3ad8..f84f3d243da 100644 --- a/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx +++ b/src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx @@ -1,7 +1,6 @@ import { Box, Divider, Flex, HStack, useColorModeValue } from '@chakra-ui/react' -import type { ParamType } from '@ethersproject/abi' import type { Asset } from '@shapeshiftoss/types' -import type { TransactionDescription } from 'ethers' +import type { ParamType, TransactionDescription } from 'ethers' import startCase from 'lodash/startCase' import { CopyButton } from 'plugins/walletConnectToDapps/components/modals/CopyButton' import { ExternalLinkButton } from 'plugins/walletConnectToDapps/components/modals/ExternalLinkButtons' @@ -113,7 +112,7 @@ export const ContractInteractionBreakdown: FC )} {!!transaction && - transaction.functionFragment.inputs.map((input, index) => { + transaction.fragment.inputs.map((input, index) => { const Wrapper = input.type === 'bytes[]' ? Flex : Fragment const wrapperProps = input.type === 'bytes[]' From f87a43d73a72992e154cbdf6b1a91bd57e0c9646 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 15 Feb 2024 21:29:59 +0100 Subject: [PATCH 04/60] feat: almost there --- src/contracts/contractManager.ts | 9 ++++++++- .../FoxyManager/Overview/Claim/ClaimStatus.tsx | 16 +++++++++------- src/lib/investor/investor-foxy/api/api.ts | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/contracts/contractManager.ts b/src/contracts/contractManager.ts index e968ba9e27f..274e3796acc 100644 --- a/src/contracts/contractManager.ts +++ b/src/contracts/contractManager.ts @@ -10,6 +10,7 @@ import { FarmingABI } from 'contracts/abis/farmingAbi' import { IUniswapV2Pair } from 'contracts/abis/IUniswapV2Pair' import { IUniswapV2Router02 } from 'contracts/abis/IUniswapV2Router02' import { THORChain_RouterABI } from 'contracts/abis/THORCHAIN_RouterABI' +import type { Provider } from 'ethers' import { ethers } from 'ethers' import memoize from 'lodash/memoize' import type { Address } from 'viem' @@ -118,7 +119,7 @@ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { type: ContractType.UniV2Pair, chainId: KnownChainIds.EthereumMainnet, }) - const ethersProvider = getEthersProvider() + const ethersProvider = getEthersProvider() as Provider const token0Address = await pair.read.token0() const token1Address = await pair.read.token1() @@ -141,13 +142,19 @@ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { const token0: Token = await Fetcher.fetchTokenData( Number(asset0EvmChainId), asset0Address, + // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber + // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open ethersProvider, ) const token1: Token = await Fetcher.fetchTokenData( Number(asset1EvmChainId), asset1Address, + // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber + // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open ethersProvider, ) + // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber + // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open return Fetcher.fetchPairData(token0, token1, ethersProvider) }) diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Overview/Claim/ClaimStatus.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Overview/Claim/ClaimStatus.tsx index 75d68b5e1de..dcfcba22bd8 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Overview/Claim/ClaimStatus.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Overview/Claim/ClaimStatus.tsx @@ -1,7 +1,7 @@ import { Box, Button, Center, Link, ModalBody, ModalFooter, Stack } from '@chakra-ui/react' import type { AccountId, AssetId, ChainId } from '@shapeshiftoss/caip' import { ASSET_REFERENCE, toAssetId } from '@shapeshiftoss/caip' -import type { ethers } from 'ethers' +import type { TransactionReceipt, TransactionReceiptParams } from 'ethers' import isNil from 'lodash/isNil' import { useCallback, useEffect, useMemo, useState } from 'react' import { FaCheck, FaTimes } from 'react-icons/fa' @@ -68,7 +68,7 @@ type ClaimStatusProps = { } export const ClaimStatus: React.FC = ({ accountId }) => { - const { poll } = usePoll() + const { poll } = usePoll() const { history: browserHistory } = useBrowserRouter() const foxyApi = getFoxyApi() const translate = useTranslate() @@ -118,20 +118,22 @@ export const ClaimStatus: React.FC = ({ accountId }) => { try { const transactionReceipt = await poll({ fn: () => foxyApi.getTxReceipt({ txid }), - validate: (result: ethers.providers.TransactionReceipt) => !isNil(result), + validate: (result: TransactionReceipt | null) => !isNil(result), interval: 15000, maxAttempts: 30, }) - if (transactionReceipt.status) { + if (transactionReceipt?.status) { refetchFoxyBalances() } setState({ ...state, - txStatus: transactionReceipt.status ? TxStatus.SUCCESS : TxStatus.FAILED, - usedGasFeeCryptoBaseUnit: transactionReceipt.effectiveGasPrice - .mul(transactionReceipt.gasUsed) + txStatus: transactionReceipt?.status ? TxStatus.SUCCESS : TxStatus.FAILED, + usedGasFeeCryptoBaseUnit: bnOrZero( + (transactionReceipt as TransactionReceiptParams | null)?.effectiveGasPrice?.toString(), + ) + .times(bnOrZero(transactionReceipt?.gasUsed.toString())) .toString(), }) } catch (error) { diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 77092392ba7..34fca136e25 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -370,7 +370,7 @@ export class FoxyApi { const liquidityReserveContract = this.getLiquidityReserveContract(contractAddress) try { - const data = liquidityReserveContract.encodeFunctionData('removeLiquidity', [ + const data = await liquidityReserveContract.encodeFunctionData('removeLiquidity', [ this.normalizeAmount(amountDesired), ]) From a992e5e49ec66d7bfc3777439201f4db487494aa Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:08:59 -0700 Subject: [PATCH 05/60] fix: all types --- .../FoxyManager/Deposit/components/Confirm.tsx | 14 ++++++++------ .../Deposit/components/Deposit.tsx | 18 +++++++++--------- src/lib/investor/investor-foxy/api/api.ts | 18 +++++++++++++----- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/components/Confirm.tsx index 5679d141534..42eb6cee32d 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/components/Confirm.tsx @@ -2,7 +2,7 @@ import { Alert, AlertIcon, Box, Stack, useToast } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { fromAccountId } from '@shapeshiftoss/caip' import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { ethers } from 'ethers' +import type { TransactionReceipt, TransactionReceiptParams } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' @@ -32,7 +32,7 @@ import { DepositContext } from '../DepositContext' type ConfirmProps = StepComponentProps & { accountId: AccountId | undefined } export const Confirm: React.FC = ({ onNext, accountId }) => { - const { poll } = usePoll() + const { poll } = usePoll() const foxyApi = getFoxyApi() const { state, dispatch } = useContext(DepositContext) const translate = useTranslate() @@ -98,16 +98,18 @@ export const Confirm: React.FC = ({ onNext, accountId }) => { const transactionReceipt = await poll({ fn: () => foxyApi.getTxReceipt({ txid }), - validate: (result: ethers.providers.TransactionReceipt) => !isNil(result), + validate: (result: TransactionReceipt | null) => !isNil(result), interval: 15000, maxAttempts: 30, }) dispatch({ type: FoxyDepositActionType.SET_DEPOSIT, payload: { - txStatus: transactionReceipt.status ? 'success' : 'failed', - usedGasFeeCryptoBaseUnit: transactionReceipt.effectiveGasPrice - .mul(transactionReceipt.gasUsed) + txStatus: transactionReceipt?.status ? 'success' : 'failed', + usedGasFeeCryptoBaseUnit: bnOrZero( + (transactionReceipt as TransactionReceiptParams | null)?.effectiveGasPrice?.toString(), + ) + .times(transactionReceipt?.gasUsed.toString() ?? 0) .toString(), }, }) diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx index fbaf6eb7090..df6c5404876 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx @@ -1,7 +1,6 @@ import { useToast } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { ASSET_REFERENCE, ethAssetId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' -import { ethers } from 'ethers' import type { DepositValues } from 'features/defi/components/Deposit/PairDeposit' import { PairDeposit } from 'features/defi/components/Deposit/PairDeposit' import type { @@ -14,6 +13,7 @@ import qs from 'qs' import { useCallback, useContext, useMemo } from 'react' import { useTranslate } from 'react-polyglot' import { useHistory } from 'react-router-dom' +import { getAddress } from 'viem' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import type { StepComponentProps } from 'components/DeFi/components/Steps' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' @@ -186,23 +186,23 @@ export const Deposit: React.FC = ({ dispatch({ type: UniV2DepositActionType.SET_LOADING, payload: false }) } else { const asset0ContractAddress = - assetId0 !== ethAssetId - ? ethers.getAddress(fromAssetId(assetId0).assetReference) - : undefined + assetId0 !== ethAssetId ? getAddress(fromAssetId(assetId0).assetReference) : undefined const asset1ContractAddress = - assetId1 !== ethAssetId - ? ethers.getAddress(fromAssetId(assetId1).assetReference) - : undefined + assetId1 !== ethAssetId ? getAddress(fromAssetId(assetId1).assetReference) : undefined // While the naive approach would be to think both assets approve() calls are going to result in the same gas estimation, // this is not necesssarly true. Some ERC-20s approve() might have a bit more logic, and thus require more gas. // e.g https://github.com/Uniswap/governance/blob/eabd8c71ad01f61fb54ed6945162021ee419998e/contracts/Uni.sol#L119 const asset0ApprovalFee = asset0ContractAddress && - bnOrZero((await getApproveFees(asset0ContractAddress))?.networkFeeCryptoBaseUnit) + bnOrZero( + (await getApproveFees(getAddress(asset0ContractAddress)))?.networkFeeCryptoBaseUnit, + ) const asset1ApprovalFee = asset1ContractAddress && - bnOrZero((await getApproveFees(asset1ContractAddress))?.networkFeeCryptoBaseUnit) + bnOrZero( + (await getApproveFees(getAddress(asset1ContractAddress)))?.networkFeeCryptoBaseUnit, + ) if (!(asset0ApprovalFee || asset1ApprovalFee)) return diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 34fca136e25..481aa37dcef 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -659,7 +659,9 @@ export class FoxyApi { } })() - const epoch = await (() => { + // This was typed as any previously but is now typed as {} + // Can we surface the contract types here? + const epoch: any = await (() => { try { return stakingContract.epoch() } catch (e) { @@ -668,7 +670,9 @@ export class FoxyApi { } })() - const requestedWithdrawals = await (() => { + // This was typed as any previously but is now typed as {} + // Can we surface the contract types here? + const requestedWithdrawals: any = await (() => { try { return tokePoolContract.requestedWithdrawals(stakingContract.address) } catch (e) { @@ -677,7 +681,9 @@ export class FoxyApi { } })() - const currentCycleIndex = await (() => { + // This was typed as any previously but is now typed as {} + // Can we surface the contract types here? + const currentCycleIndex: any = await (() => { try { return tokeManagerContract.getCurrentCycleIndex() } catch (e) { @@ -686,7 +692,9 @@ export class FoxyApi { } })() - const withdrawalAmount = await (() => { + // This was typed as any previously but is now typed as {} + // Can we surface the contract types here? + const withdrawalAmount: any = await (() => { try { return stakingContract.withdrawalAmount() } catch (e) { @@ -823,7 +831,7 @@ export class FoxyApi { const nextCycleStart = bnOrZero(currentCycleStart).plus(duration) const blockNumber = await this.provider.getBlockNumber() - const timestamp = (await this.provider.getBlock(blockNumber)).timestamp + const timestamp = (await this.provider.getBlock(blockNumber))?.timestamp const isTimeToRequest = bnOrZero(timestamp) .plus(timeLeftToRequestWithdrawal) From d646d52e6559c018025e569cfc1a75449c3d771a Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:19:36 -0700 Subject: [PATCH 06/60] feat: start migrating unchained-client to v6 --- packages/unchained-client/package.json | 1 + packages/unchained-client/src/evm/parser/index.ts | 8 ++++---- yarn.lock | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/unchained-client/package.json b/packages/unchained-client/package.json index f1c2371ac00..f07ee0be644 100644 --- a/packages/unchained-client/package.json +++ b/packages/unchained-client/package.json @@ -20,6 +20,7 @@ "dependencies": { "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/common-api": "^9.3.0", + "ethers": "^6.11.1", "isomorphic-ws": "^4.0.1", "ws": "^8.3.0" }, diff --git a/packages/unchained-client/src/evm/parser/index.ts b/packages/unchained-client/src/evm/parser/index.ts index f6b3131d121..ca8cd7e78a4 100644 --- a/packages/unchained-client/src/evm/parser/index.ts +++ b/packages/unchained-client/src/evm/parser/index.ts @@ -1,7 +1,7 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' import { ASSET_NAMESPACE, ASSET_REFERENCE, ethChainId, toAssetId } from '@shapeshiftoss/caip' import { BigNumber } from 'bignumber.js' -import { ethers } from 'ethers' +import { getAddress, JsonRpcProvider } from 'ethers' import type { Token, TxStatus } from '../../types' import { TransferType } from '../../types' @@ -26,7 +26,7 @@ export class BaseTransactionParser { assetId: AssetId protected readonly api: Api - protected readonly provider: ethers.JsonRpcProvider + protected readonly provider: JsonRpcProvider private parsers: SubParser[] = [] @@ -34,7 +34,7 @@ export class BaseTransactionParser { this.chainId = args.chainId this.assetId = args.assetId this.api = args.api - this.provider = new ethers.JsonRpcProvider(args.rpcUrl) + this.provider = new JsonRpcProvider(args.rpcUrl) } /** @@ -51,7 +51,7 @@ export class BaseTransactionParser { } async parse(tx: T, address: string): Promise { - address = ethers.getAddress(address) + address = getAddress(address) // We expect only one Parser to return a result. If multiple do, we take the first and early exit. const contractParserResult = await findAsyncSequential, TxSpecific>( diff --git a/yarn.lock b/yarn.lock index 44266a80502..251d1bf1164 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9951,6 +9951,7 @@ __metadata: "@openapitools/openapi-generator-cli": ^2.5.1 "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/common-api": ^9.3.0 + ethers: ^6.11.1 isomorphic-ws: ^4.0.1 ws: ^8.3.0 languageName: unknown From 0674d036b0cc3bb58e55691ddd56387d964c2857 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:33:54 -0700 Subject: [PATCH 07/60] feat: enforce unchained-client to workspace version --- package.json | 3 ++- yarn.lock | 23 +++-------------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 78b54de5422..cbf20b5cac8 100644 --- a/package.json +++ b/package.json @@ -290,6 +290,7 @@ "p-queue": "^6.6.2", "web3": "4.2.1-dev.a0d6730.0", "@wherever/react-notification-feed/wagmi": "^0.10.12", - "react-scripts@^5.0.1": "patch:react-scripts@npm%3A5.0.1#./.yarn/patches/react-scripts-npm-5.0.1-d06bd2d5ad.patch" + "react-scripts@^5.0.1": "patch:react-scripts@npm%3A5.0.1#./.yarn/patches/react-scripts-npm-5.0.1-d06bd2d5ad.patch", + "@shapeshiftoss/unchained-client": "workspace:^" } } diff --git a/yarn.lock b/yarn.lock index 251d1bf1164..5e9c4792019 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9944,7 +9944,7 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/unchained-client@^10.1.1, @shapeshiftoss/unchained-client@workspace:^, @shapeshiftoss/unchained-client@workspace:packages/unchained-client": +"@shapeshiftoss/unchained-client@workspace:^, @shapeshiftoss/unchained-client@workspace:packages/unchained-client": version: 0.0.0-use.local resolution: "@shapeshiftoss/unchained-client@workspace:packages/unchained-client" dependencies: @@ -9957,23 +9957,6 @@ __metadata: languageName: unknown linkType: soft -"@shapeshiftoss/unchained-client@npm:10.1.1": - version: 10.1.1 - resolution: "@shapeshiftoss/unchained-client@npm:10.1.1" - dependencies: - "@yfi/sdk": ^1.0.30 - bignumber.js: ^9.0.2 - ethers: ^5.5.3 - isomorphic-ws: ^4.0.1 - ws: ^8.3.0 - peerDependencies: - "@shapeshiftoss/caip": ^8.0.0 - "@shapeshiftoss/logger": ^1.1.2 - "@shapeshiftoss/types": ^8.1.0 - checksum: 0cd585a7131a859af175e454f249c8bde50889987733aca9bc0635453b11ca5f9cbe2580bdb2cf630ae88a4c305bc0cf5898f43e7a6c3be0b28784a68896dcf6 - languageName: node - linkType: hard - "@shapeshiftoss/web@workspace:.": version: 0.0.0-use.local resolution: "@shapeshiftoss/web@workspace:." @@ -14211,7 +14194,7 @@ __metadata: languageName: node linkType: hard -"@yfi/sdk@npm:^1.0.30, @yfi/sdk@npm:^1.2.0": +"@yfi/sdk@npm:^1.2.0": version: 1.2.0 resolution: "@yfi/sdk@npm:1.2.0" dependencies: @@ -21077,7 +21060,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:5.7.2, ethers@npm:^5.5.3, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": +"ethers@npm:5.7.2, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: From 6d0c7d3a5970ef9e0d6472b7b82adf8dcba31d58 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:39:10 -0700 Subject: [PATCH 08/60] feat: more resolutions enforcement --- packages/unchained-client/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/unchained-client/package.json b/packages/unchained-client/package.json index f07ee0be644..3867028de15 100644 --- a/packages/unchained-client/package.json +++ b/packages/unchained-client/package.json @@ -26,5 +26,8 @@ }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.5.1" + }, + "resolutions": { + "ethers": "^6.11.1" } } From 2a0036c5bdca629d1e5a76aba71d269f021db265 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:41:31 -0700 Subject: [PATCH 09/60] fix: derp mocks --- __mocks__/ethers.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/__mocks__/ethers.ts b/__mocks__/ethers.ts index e0a67eda388..9abe6aede49 100644 --- a/__mocks__/ethers.ts +++ b/__mocks__/ethers.ts @@ -3,9 +3,7 @@ import { vi } from 'vitest' const ethersMock = { ...ethers, - providers: { - JsonRpcProvider: vi.fn(), - }, + JsonRpcProvider: vi.fn(), Contract: vi.fn().mockImplementation(address => ({ decimals: () => { switch (address as string) { From 450e9713a6228b0afc0995e3af65689bde51817e Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Sat, 17 Feb 2024 05:56:45 -0700 Subject: [PATCH 10/60] fix: many tests --- __mocks__/ethers.ts | 2 - .../parser/__tests__/ethereum.test.ts | 93 +++++++++++++++++++ .../unchained-client/src/evm/parser/index.ts | 4 +- 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/__mocks__/ethers.ts b/__mocks__/ethers.ts index 9abe6aede49..e5693549a69 100644 --- a/__mocks__/ethers.ts +++ b/__mocks__/ethers.ts @@ -1,8 +1,6 @@ -import ethers from 'ethers' import { vi } from 'vitest' const ethersMock = { - ...ethers, JsonRpcProvider: vi.fn(), Contract: vi.fn().mockImplementation(address => ({ decimals: () => { diff --git a/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts b/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts index 338e92d3379..82ba5ec135c 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts @@ -1,5 +1,6 @@ import { ethAssetId, ethChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type ethers from 'ethers' import { beforeAll, describe, expect, it, vi } from 'vitest' import type { Trade } from '../../../../types' @@ -86,6 +87,98 @@ import zrxTradeEthToMatic from './mockData/zrxTradeEthToMatic' import zrxTradeTetherToKishu from './mockData/zrxTradeTetherToKishu' import zrxTradeTribeToEth from './mockData/zrxTradeTribeToEth' +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const mocks = vi.hoisted(() => { const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', diff --git a/packages/unchained-client/src/evm/parser/index.ts b/packages/unchained-client/src/evm/parser/index.ts index ca8cd7e78a4..94a4a215a74 100644 --- a/packages/unchained-client/src/evm/parser/index.ts +++ b/packages/unchained-client/src/evm/parser/index.ts @@ -1,7 +1,7 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' import { ASSET_NAMESPACE, ASSET_REFERENCE, ethChainId, toAssetId } from '@shapeshiftoss/caip' import { BigNumber } from 'bignumber.js' -import { getAddress, JsonRpcProvider } from 'ethers' +import ethers, { getAddress, JsonRpcProvider } from 'ethers' import type { Token, TxStatus } from '../../types' import { TransferType } from '../../types' @@ -11,6 +11,8 @@ import type { Api } from '..' import type { ParsedTx, SubParser, Tx, TxSpecific } from './types' import { getTxStatus } from './utils' +console.log({ ethers, JsonRpcProvider }) + export * from './types' export * from './utils' From 8162f437e934477979e1e5e3725ff50e1a89c191 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 07:04:10 -0800 Subject: [PATCH 11/60] fix: most tests --- __mocks__/ethers.ts | 2 + .../evm/arbitrum/ArbitrumChainAdapter.test.ts | 93 +++++++++++++++++++ .../ArbitrumNovaChainAdapter.test.ts | 93 +++++++++++++++++++ .../avalanche/AvalancheChainAdapter.test.ts | 93 +++++++++++++++++++ .../evm/bnbsmartchain/BscChainAdapter.test.ts | 93 +++++++++++++++++++ .../evm/ethereum/EthereumChainAdapter.test.ts | 93 +++++++++++++++++++ .../src/evm/gnosis/GnosisChainAdapter.test.ts | 93 +++++++++++++++++++ .../evm/optimism/OptimismChainAdapter.test.ts | 93 +++++++++++++++++++ .../evm/polygon/PolygonChainAdapter.test.ts | 93 +++++++++++++++++++ .../parser/__tests__/arbitrum.test.ts | 93 +++++++++++++++++++ .../parser/__tests__/arbitrumNova.test.ts | 93 +++++++++++++++++++ .../parser/__tests__/avalanche.test.ts | 93 +++++++++++++++++++ .../parser/__tests__/bnbsmartchain.test.ts | 93 +++++++++++++++++++ .../gnosis/parser/__tests__/gnosis.test.ts | 93 +++++++++++++++++++ .../parser/__tests__/optimism.test.ts | 93 +++++++++++++++++++ .../unchained-client/src/evm/parser/index.ts | 4 +- .../polygon/parser/__tests__/polygon.test.ts | 93 +++++++++++++++++++ 17 files changed, 1398 insertions(+), 3 deletions(-) diff --git a/__mocks__/ethers.ts b/__mocks__/ethers.ts index e5693549a69..9abe6aede49 100644 --- a/__mocks__/ethers.ts +++ b/__mocks__/ethers.ts @@ -1,6 +1,8 @@ +import ethers from 'ethers' import { vi } from 'vitest' const ethersMock = { + ...ethers, JsonRpcProvider: vi.fn(), Contract: vi.fn().mockImplementation(address => ({ decimals: () => { diff --git a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts index 0e19b6f0602..b08f40694e3 100644 --- a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts @@ -5,6 +5,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -20,6 +21,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' diff --git a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts index 7835e2bf29d..5080fd59aaf 100644 --- a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts @@ -10,6 +10,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -25,6 +26,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' diff --git a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts index 712df823ae0..a8d95ade678 100644 --- a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts @@ -10,6 +10,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -25,6 +26,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' diff --git a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts index 091ccf9ce2f..872f0f3c6bd 100644 --- a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts @@ -5,6 +5,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -20,6 +21,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' diff --git a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts index 1aa5f393701..4d9785a850b 100644 --- a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts @@ -5,6 +5,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -20,6 +21,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const ENS_NAME = 'vitalik.eth' diff --git a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts index e2216c04028..8b77d9f83af 100644 --- a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts @@ -11,6 +11,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { ZeroAddress } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' @@ -27,6 +28,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const testMnemonic = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' diff --git a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts index 22d798765a9..d2f5aded5b7 100644 --- a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts @@ -5,6 +5,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -21,6 +22,98 @@ const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const testMnemonic = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const getWallet = async (): Promise => { const nativeAdapterArgs: NativeAdapterArgs = { mnemonic: testMnemonic, diff --git a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts index ed6b55be9b7..51db2c6f6ac 100644 --- a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts @@ -5,6 +5,7 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' +import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -20,6 +21,98 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' diff --git a/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts b/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts index 39832308dec..eb1e14244f8 100644 --- a/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts +++ b/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts @@ -1,5 +1,6 @@ import { arbitrumAssetId, arbitrumChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -21,6 +22,98 @@ import zrxTradeUsdcToWbtc from './mockData/zrxTradeUsdcToWbtc' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts b/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts index 60331600c59..591b168573f 100644 --- a/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts +++ b/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts @@ -1,5 +1,6 @@ import { arbitrumNovaAssetId, arbitrumNovaChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import { TransferType, TxStatus } from '../../../../types' @@ -17,6 +18,98 @@ import tokenStandard from './mockData/tokenStandard' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts b/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts index 0bc2dd8ba70..4b744477719 100644 --- a/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts +++ b/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts @@ -1,5 +1,6 @@ import { avalancheAssetId, avalancheChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -21,6 +22,98 @@ import zrxTradeWethToWbtc from './mockData/zrxTradeWethToWbtc' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts index 2c37ac1e20d..7ffb09e5322 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts @@ -1,5 +1,6 @@ import { bscAssetId, bscChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -21,6 +22,98 @@ import zrxTradeUsdtToBusd from './mockData/zrxTradeUsdtToBusd' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts b/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts index 515fa18044b..c0fc66d7581 100644 --- a/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts +++ b/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts @@ -1,5 +1,6 @@ import { gnosisAssetId, gnosisChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import { TransferType, TxStatus } from '../../../../types' @@ -17,6 +18,98 @@ import xdaiStandard from './mockData/xdaiStandard' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts b/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts index 389c60dbb09..a3197836ed2 100644 --- a/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts +++ b/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts @@ -1,5 +1,6 @@ import { optimismAssetId, optimismChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -21,6 +22,98 @@ import zrxTradeUsdcToOp from './mockData/zrxTradeUsdcToOp' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/parser/index.ts b/packages/unchained-client/src/evm/parser/index.ts index 94a4a215a74..ca8cd7e78a4 100644 --- a/packages/unchained-client/src/evm/parser/index.ts +++ b/packages/unchained-client/src/evm/parser/index.ts @@ -1,7 +1,7 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' import { ASSET_NAMESPACE, ASSET_REFERENCE, ethChainId, toAssetId } from '@shapeshiftoss/caip' import { BigNumber } from 'bignumber.js' -import ethers, { getAddress, JsonRpcProvider } from 'ethers' +import { getAddress, JsonRpcProvider } from 'ethers' import type { Token, TxStatus } from '../../types' import { TransferType } from '../../types' @@ -11,8 +11,6 @@ import type { Api } from '..' import type { ParsedTx, SubParser, Tx, TxSpecific } from './types' import { getTxStatus } from './utils' -console.log({ ethers, JsonRpcProvider }) - export * from './types' export * from './utils' diff --git a/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts b/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts index d6536c0692b..81ffaef0c75 100644 --- a/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts +++ b/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts @@ -1,5 +1,6 @@ import { polygonAssetId, polygonChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' +import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -21,6 +22,98 @@ import zrxTradeUsdcToUsdt from './mockData/zrxTradeUsdcToUsdt' const mockedApi = vi.mocked(new V1Api()) +vi.mock('ethers', async importActual => { + const actual: typeof ethers = await importActual() + return { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + + JsonRpcProvider: vi.fn(), + default: { + ...actual, + Contract: vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + })), + }, + } +}) + const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', From ddfae0ec718bbacb9cbed886a2e36c76cf5144e1 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 07:07:23 -0800 Subject: [PATCH 12/60] fix: all tests --- packages/unchained-client/src/evm/ethereum/parser/uniV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts index bced105109a..6021020c49b 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts @@ -1,6 +1,6 @@ import type { ChainId } from '@shapeshiftoss/caip' import { fromChainId, toAssetId } from '@shapeshiftoss/caip' -import { ethers } from 'ethers' +import ethers from 'ethers' import type { Tx } from '../../../generated/ethereum' import type { BaseTxMetadata } from '../../../types' From 20ee753c9f5d5afb695a3e1dedefc7b748b5a9fe Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:02:23 -0800 Subject: [PATCH 13/60] feat: yarn v5 aliased node_module --- package.json | 1 + react-app-rewired/index.ts | 3 ++- yarn.lock | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cbf20b5cac8..9c8dca3e4d6 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,7 @@ "eslint-plugin-react-memo": "^0.0.3", "eth-url-parser": "^1.0.4", "ethers": "^6.11.1", + "ethers5": "npm:ethers@5.7.2", "framer-motion": "^11.0.3", "friendly-challenge": "0.9.2", "grapheme-splitter": "^1.0.4", diff --git a/react-app-rewired/index.ts b/react-app-rewired/index.ts index 14a4f5d8b0d..ced5538ecad 100644 --- a/react-app-rewired/index.ts +++ b/react-app-rewired/index.ts @@ -335,7 +335,8 @@ const reactAppRewireConfig = { _.merge(config, { resolve: { alias: { - 'ethers/lib/utils': 'ethers/lib/utils.js', + 'ethers/lib/utils': 'ethers5/lib/utils.js', + 'ethers/lib/utils.js': 'ethers5/lib/utils.js', }, }, }), diff --git a/yarn.lock b/yarn.lock index 5e9c4792019..1dd50d5625d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10085,6 +10085,7 @@ __metadata: eslint-plugin-simple-import-sort: ^10.0.0 eth-url-parser: ^1.0.4 ethers: ^6.11.1 + ethers5: "npm:ethers@5.7.2" express: ^4.18.2 fast-json-stable-stringify: ^2.1.0 framer-motion: ^11.0.3 @@ -21060,7 +21061,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:5.7.2, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": +"ethers5@npm:ethers@5.7.2, ethers@npm:5.7.2, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: From 2563e79373533e0e65aa8b084ad6ebbd6b57a54d Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:07:12 -0800 Subject: [PATCH 14/60] feat: don't install ethers as direct dep in unchained-client --- packages/unchained-client/package.json | 4 ---- yarn.lock | 1 - 2 files changed, 5 deletions(-) diff --git a/packages/unchained-client/package.json b/packages/unchained-client/package.json index 3867028de15..f1c2371ac00 100644 --- a/packages/unchained-client/package.json +++ b/packages/unchained-client/package.json @@ -20,14 +20,10 @@ "dependencies": { "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/common-api": "^9.3.0", - "ethers": "^6.11.1", "isomorphic-ws": "^4.0.1", "ws": "^8.3.0" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.5.1" - }, - "resolutions": { - "ethers": "^6.11.1" } } diff --git a/yarn.lock b/yarn.lock index 1dd50d5625d..ba56e788da1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9951,7 +9951,6 @@ __metadata: "@openapitools/openapi-generator-cli": ^2.5.1 "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/common-api": ^9.3.0 - ethers: ^6.11.1 isomorphic-ws: ^4.0.1 ws: ^8.3.0 languageName: unknown From 6d576d0025098b891597d536a8b1b4cf94b6e177 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:13:20 -0800 Subject: [PATCH 15/60] feat: cleanup package.json monkey patch --- package.json | 3 +-- yarn.lock | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9c8dca3e4d6..59fb441318e 100644 --- a/package.json +++ b/package.json @@ -291,7 +291,6 @@ "p-queue": "^6.6.2", "web3": "4.2.1-dev.a0d6730.0", "@wherever/react-notification-feed/wagmi": "^0.10.12", - "react-scripts@^5.0.1": "patch:react-scripts@npm%3A5.0.1#./.yarn/patches/react-scripts-npm-5.0.1-d06bd2d5ad.patch", - "@shapeshiftoss/unchained-client": "workspace:^" + "react-scripts@^5.0.1": "patch:react-scripts@npm%3A5.0.1#./.yarn/patches/react-scripts-npm-5.0.1-d06bd2d5ad.patch" } } diff --git a/yarn.lock b/yarn.lock index ba56e788da1..d4a130819d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9944,7 +9944,7 @@ __metadata: languageName: node linkType: hard -"@shapeshiftoss/unchained-client@workspace:^, @shapeshiftoss/unchained-client@workspace:packages/unchained-client": +"@shapeshiftoss/unchained-client@^10.1.1, @shapeshiftoss/unchained-client@workspace:^, @shapeshiftoss/unchained-client@workspace:packages/unchained-client": version: 0.0.0-use.local resolution: "@shapeshiftoss/unchained-client@workspace:packages/unchained-client" dependencies: @@ -9956,6 +9956,23 @@ __metadata: languageName: unknown linkType: soft +"@shapeshiftoss/unchained-client@npm:10.1.1": + version: 10.1.1 + resolution: "@shapeshiftoss/unchained-client@npm:10.1.1" + dependencies: + "@yfi/sdk": ^1.0.30 + bignumber.js: ^9.0.2 + ethers: ^5.5.3 + isomorphic-ws: ^4.0.1 + ws: ^8.3.0 + peerDependencies: + "@shapeshiftoss/caip": ^8.0.0 + "@shapeshiftoss/logger": ^1.1.2 + "@shapeshiftoss/types": ^8.1.0 + checksum: 0cd585a7131a859af175e454f249c8bde50889987733aca9bc0635453b11ca5f9cbe2580bdb2cf630ae88a4c305bc0cf5898f43e7a6c3be0b28784a68896dcf6 + languageName: node + linkType: hard + "@shapeshiftoss/web@workspace:.": version: 0.0.0-use.local resolution: "@shapeshiftoss/web@workspace:." @@ -14194,7 +14211,7 @@ __metadata: languageName: node linkType: hard -"@yfi/sdk@npm:^1.2.0": +"@yfi/sdk@npm:^1.0.30, @yfi/sdk@npm:^1.2.0": version: 1.2.0 resolution: "@yfi/sdk@npm:1.2.0" dependencies: @@ -21060,7 +21077,7 @@ __metadata: languageName: node linkType: hard -"ethers5@npm:ethers@5.7.2, ethers@npm:5.7.2, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": +"ethers5@npm:ethers@5.7.2, ethers@npm:5.7.2, ethers@npm:^5.5.3, ethers@npm:^5.6.5, ethers@npm:^5.6.9, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: From 8c0af33f2a1b767b30d856eafab29725a7ca2351 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:16:56 -0800 Subject: [PATCH 16/60] feat: bring back v6 resolution in unchained-client This reverts commit 849fd13c03a71d31e6462df30c17014a1c11419d. --- packages/unchained-client/package.json | 4 ++++ yarn.lock | 1 + 2 files changed, 5 insertions(+) diff --git a/packages/unchained-client/package.json b/packages/unchained-client/package.json index f1c2371ac00..3867028de15 100644 --- a/packages/unchained-client/package.json +++ b/packages/unchained-client/package.json @@ -20,10 +20,14 @@ "dependencies": { "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/common-api": "^9.3.0", + "ethers": "^6.11.1", "isomorphic-ws": "^4.0.1", "ws": "^8.3.0" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.5.1" + }, + "resolutions": { + "ethers": "^6.11.1" } } diff --git a/yarn.lock b/yarn.lock index d4a130819d6..2432f0897bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9951,6 +9951,7 @@ __metadata: "@openapitools/openapi-generator-cli": ^2.5.1 "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/common-api": ^9.3.0 + ethers: ^6.11.1 isomorphic-ws: ^4.0.1 ws: ^8.3.0 languageName: unknown From 566db588489c2e384bd74f50d1e5b6e62a757a50 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:24:20 -0800 Subject: [PATCH 17/60] feat: default export shenanigans --- .../src/evm/ethereum/parser/uniV2.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts index 6021020c49b..dfe877efd28 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts @@ -1,6 +1,7 @@ import type { ChainId } from '@shapeshiftoss/caip' import { fromChainId, toAssetId } from '@shapeshiftoss/caip' -import ethers from 'ethers' +import type { JsonRpcProvider } from 'ethers' +import { Contract, getAddress, getCreate2Address, Interface, solidityPackedKeccak256 } from 'ethers' import type { Tx } from '../../../generated/ethereum' import type { BaseTxMetadata } from '../../../types' @@ -23,15 +24,15 @@ export interface TxMetadata extends BaseTxMetadata { export interface ParserArgs { chainId: ChainId - provider: ethers.JsonRpcProvider + provider: JsonRpcProvider } export class Parser implements SubParser { - provider: ethers.JsonRpcProvider + provider: JsonRpcProvider readonly chainId: ChainId readonly wethContract: string - readonly abiInterface = new ethers.Interface(UNIV2_ABI) - readonly stakingRewardsInterface = new ethers.Interface(UNIV2_STAKING_REWARDS_ABI) + readonly abiInterface = new Interface(UNIV2_ABI) + readonly stakingRewardsInterface = new Interface(UNIV2_STAKING_REWARDS_ABI) readonly supportedFunctions = { addLiquidityEthSigHash: this.abiInterface.getFunction('addLiquidityETH')?.selector, @@ -81,13 +82,13 @@ export class Parser implements SubParser { }, } - const tokenAddress = ethers.getAddress(decoded.args.token.toLowerCase()) + const tokenAddress = getAddress(decoded.args.token.toLowerCase()) const lpTokenAddress = Parser.pairFor(tokenAddress, this.wethContract) const transfers = await (async () => { switch (getSigHash(tx.inputData)) { case this.supportedFunctions.addLiquidityEthSigHash: { - const contract = new ethers.Contract(tokenAddress, ERC20_ABI, this.provider) + const contract = new Contract(tokenAddress, ERC20_ABI, this.provider) const decimals = await contract.decimals() const name = await contract.name() const symbol = await contract.symbol() @@ -112,7 +113,7 @@ export class Parser implements SubParser { ] } case this.supportedFunctions.removeLiquidityEthSigHash: { - const contract = new ethers.Contract(lpTokenAddress, ERC20_ABI, this.provider) + const contract = new Contract(lpTokenAddress, ERC20_ABI, this.provider) const decimals = await contract.decimals() const name = await contract.name() const symbol = await contract.symbol() @@ -188,8 +189,8 @@ export class Parser implements SubParser { private static pairFor(tokenA: string, tokenB: string): string { const [token0, token1] = tokenA < tokenB ? [tokenA, tokenB] : [tokenB, tokenA] const factoryContract = '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f' - const salt = ethers.solidityPackedKeccak256(['address', 'address'], [token0, token1]) + const salt = solidityPackedKeccak256(['address', 'address'], [token0, token1]) const initCodeHash = '0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // https://github.com/Uniswap/v2-periphery/blob/dda62473e2da448bc9cb8f4514dadda4aeede5f4/contracts/libraries/UniswapV2Library.sol#L24 - return ethers.getCreate2Address(factoryContract, salt, initCodeHash) + return getCreate2Address(factoryContract, salt, initCodeHash) } } From dc47e9cea46c8198f25a7aa5dd46cf04dbdfca31 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:38:15 -0800 Subject: [PATCH 18/60] fix: uni-v2 DeFi opportunities resolver --- src/contracts/contractManager.ts | 16 +++++----------- src/lib/ethersProviderSingleton.ts | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/contracts/contractManager.ts b/src/contracts/contractManager.ts index 274e3796acc..2b6083faed8 100644 --- a/src/contracts/contractManager.ts +++ b/src/contracts/contractManager.ts @@ -15,7 +15,7 @@ import { ethers } from 'ethers' import memoize from 'lodash/memoize' import type { Address } from 'viem' import { getContract } from 'viem' -import { getEthersProvider } from 'lib/ethersProviderSingleton' +import { getEthersProvider, getEthersV5Provider } from 'lib/ethersProviderSingleton' import { viemClientByChainId, viemEthMainnetClient } from 'lib/viem-client' import { @@ -119,7 +119,7 @@ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { type: ContractType.UniV2Pair, chainId: KnownChainIds.EthereumMainnet, }) - const ethersProvider = getEthersProvider() as Provider + const ethersV5Provider = getEthersV5Provider() const token0Address = await pair.read.token0() const token1Address = await pair.read.token1() @@ -142,19 +142,13 @@ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { const token0: Token = await Fetcher.fetchTokenData( Number(asset0EvmChainId), asset0Address, - // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber - // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open - ethersProvider, + ethersV5Provider, ) const token1: Token = await Fetcher.fetchTokenData( Number(asset1EvmChainId), asset1Address, - // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber - // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open - ethersProvider, + ethersV5Provider, ) - // @ts-ignore TODO(gomes): FIXME, this is 99% likely to fail because ethers v6 now uses BigInt instead of BigNumber - // We may want to patch @uniswap/sdk while https://github.com/Uniswap/web3-react/issues/812 is open - return Fetcher.fetchPairData(token0, token1, ethersProvider) + return Fetcher.fetchPairData(token0, token1, ethersV5Provider) }) diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index dfd7161bf9e..edc63527403 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -3,6 +3,7 @@ import type { EvmChainId } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' import { JsonRpcProvider } from 'ethers' +import { ethers as ethersV5 } from 'ethers5' import { assertUnreachable } from './utils' @@ -30,6 +31,7 @@ export const rpcUrlByChainId = (chainId: EvmChainId): string => { } const ethersProviders: Map = new Map() +const ethersV5Providers: Map = new Map() export const getEthersProvider = ( chainId: EvmChainId = KnownChainIds.EthereumMainnet, @@ -42,3 +44,16 @@ export const getEthersProvider = ( return ethersProviders.get(chainId)! } } + +// For backwards-compatibility for libraries still stuck in v5 +export const getEthersV5Provider = ( + chainId: EvmChainId = KnownChainIds.EthereumMainnet, +): ethersV5.providers.JsonRpcProvider => { + if (!ethersProviders.has(chainId)) { + const provider = new ethersV5.providers.StaticJsonRpcProvider(rpcUrlByChainId(chainId)) + ethersV5Providers.set(chainId, provider) + return provider + } else { + return ethersV5Providers.get(chainId)! + } +} From 4531a5f6a5e1b516bdc0b8df290a54ffc1c71b33 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:42:24 -0800 Subject: [PATCH 19/60] feat: revert console log --- packages/unchained-client/src/evm/parser/erc20.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/unchained-client/src/evm/parser/erc20.ts b/packages/unchained-client/src/evm/parser/erc20.ts index 47f3e867e64..0327263ed9c 100644 --- a/packages/unchained-client/src/evm/parser/erc20.ts +++ b/packages/unchained-client/src/evm/parser/erc20.ts @@ -59,8 +59,6 @@ export class Parser implements SubParser { case this.supportedFunctions.approveSigHash: { const amount = decoded.args.amount as BigInt const value = amount.toString() - // For paranoia's sake, remove me before opening the PR - console.log({ amount }) if (amount === BigInt(0)) { return await Promise.resolve({ data: { ...data, method: 'revoke', value } }) } From b8d75f68cf9b24b99734e68fc3341176cef5efcd Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:47:15 -0800 Subject: [PATCH 20/60] fix: ci --- src/contracts/contractManager.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/contracts/contractManager.ts b/src/contracts/contractManager.ts index 2b6083faed8..b8fc5b0a53e 100644 --- a/src/contracts/contractManager.ts +++ b/src/contracts/contractManager.ts @@ -10,12 +10,11 @@ import { FarmingABI } from 'contracts/abis/farmingAbi' import { IUniswapV2Pair } from 'contracts/abis/IUniswapV2Pair' import { IUniswapV2Router02 } from 'contracts/abis/IUniswapV2Router02' import { THORChain_RouterABI } from 'contracts/abis/THORCHAIN_RouterABI' -import type { Provider } from 'ethers' import { ethers } from 'ethers' import memoize from 'lodash/memoize' import type { Address } from 'viem' import { getContract } from 'viem' -import { getEthersProvider, getEthersV5Provider } from 'lib/ethersProviderSingleton' +import { getEthersV5Provider } from 'lib/ethersProviderSingleton' import { viemClientByChainId, viemEthMainnetClient } from 'lib/viem-client' import { From 8588b384b0cb460c6e865238f2adbbfb9a96de73 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 09:56:51 -0800 Subject: [PATCH 21/60] fix: derp --- src/lib/ethersProviderSingleton.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index edc63527403..a1f43e3dfd2 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -49,7 +49,7 @@ export const getEthersProvider = ( export const getEthersV5Provider = ( chainId: EvmChainId = KnownChainIds.EthereumMainnet, ): ethersV5.providers.JsonRpcProvider => { - if (!ethersProviders.has(chainId)) { + if (!ethersV5Providers.has(chainId)) { const provider = new ethersV5.providers.StaticJsonRpcProvider(rpcUrlByChainId(chainId)) ethersV5Providers.set(chainId, provider) return provider From dae05416ee00282874d158bc619d2222d71ff02f Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:15:15 -0800 Subject: [PATCH 22/60] fix: investor-foxy access .target vs. .address --- src/lib/investor/investor-foxy/api/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 481aa37dcef..2ee83b9c284 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -674,7 +674,7 @@ export class FoxyApi { // Can we surface the contract types here? const requestedWithdrawals: any = await (() => { try { - return tokePoolContract.requestedWithdrawals(stakingContract.address) + return tokePoolContract.requestedWithdrawals(stakingContract.target) } catch (e) { console.error(e, 'failed to get requestedWithdrawals') return {} From 7543a79fe85d14ee2979af3ee3f4832c70f6ee8b Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:22:29 -0800 Subject: [PATCH 23/60] feat: more BigInt / bignumber.js shenanigans --- src/lib/investor/investor-foxy/api/api.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 2ee83b9c284..9b0c93a02c3 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -705,10 +705,13 @@ export class FoxyApi { const currentBlock = await this.provider.getBlockNumber() - const epochExpired = epoch.number.gte(coolDownInfo.endEpoch) - const coolDownValid = !coolDownInfo.endEpoch.isZero() && !coolDownInfo.amount.isZero() + const epochExpired = bnOrZero(epoch.number.toString()).gte(coolDownInfo.endEpoch.toString()) + const coolDownValid = + !bnOrZero(coolDownInfo.endEpoch).isZero() && !bnOrZero(coolDownInfo.amount).isZero() - const pastTokeCycleIndex = requestedWithdrawals.minCycle.lte(currentCycleIndex) + const pastTokeCycleIndex = bnOrZero(requestedWithdrawals.minCycle).lte( + currentCycleIndex.toString(), + ) const stakingTokenAvailableWithTokemak = requestedWithdrawals.amount.add(withdrawalAmount) const stakingTokenAvailable = withdrawalAmount.gte(coolDownInfo.amount) const validCycleAndAmount = From 69e599f6aa204f28df2c638e9b85d19ea083f85c Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:39:54 -0800 Subject: [PATCH 24/60] feat: everything is saner with types --- src/lib/investor/investor-foxy/api/api.ts | 54 +++++++++++++---------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 9b0c93a02c3..36b35ba84db 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -659,9 +659,12 @@ export class FoxyApi { } })() - // This was typed as any previously but is now typed as {} - // Can we surface the contract types here? - const epoch: any = await (() => { + const epoch: { + length?: BigInt + number?: BigInt + endBlock?: BigInt + distribute?: BigInt + } = await (() => { try { return stakingContract.epoch() } catch (e) { @@ -670,9 +673,10 @@ export class FoxyApi { } })() - // This was typed as any previously but is now typed as {} - // Can we surface the contract types here? - const requestedWithdrawals: any = await (() => { + const requestedWithdrawals: { + minCycle?: BigInt + amount?: BigInt + } = await (() => { try { return tokePoolContract.requestedWithdrawals(stakingContract.target) } catch (e) { @@ -681,50 +685,54 @@ export class FoxyApi { } })() - // This was typed as any previously but is now typed as {} - // Can we surface the contract types here? - const currentCycleIndex: any = await (() => { + const currentCycleIndex: BigInt = await (() => { try { return tokeManagerContract.getCurrentCycleIndex() } catch (e) { console.error(e, 'failed to get currentCycleIndex') - return 0 + return BigInt(0) } })() - - // This was typed as any previously but is now typed as {} - // Can we surface the contract types here? - const withdrawalAmount: any = await (() => { + const withdrawalAmount: BigInt = await (() => { try { return stakingContract.withdrawalAmount() } catch (e) { console.error(e, 'failed to get currentCycleIndex') - return 0 + return BigInt(0) } })() const currentBlock = await this.provider.getBlockNumber() - const epochExpired = bnOrZero(epoch.number.toString()).gte(coolDownInfo.endEpoch.toString()) + const epochExpired = bnOrZero(epoch.number?.toString()).gte(coolDownInfo.endEpoch.toString()) const coolDownValid = !bnOrZero(coolDownInfo.endEpoch).isZero() && !bnOrZero(coolDownInfo.amount).isZero() - const pastTokeCycleIndex = bnOrZero(requestedWithdrawals.minCycle).lte( + const pastTokeCycleIndex = bnOrZero(requestedWithdrawals.minCycle?.toString()).lte( currentCycleIndex.toString(), ) - const stakingTokenAvailableWithTokemak = requestedWithdrawals.amount.add(withdrawalAmount) - const stakingTokenAvailable = withdrawalAmount.gte(coolDownInfo.amount) + const stakingTokenAvailableWithTokemak = bnOrZero(requestedWithdrawals.amount?.toString()).plus( + withdrawalAmount.toString(), + ) + const stakingTokenAvailable = bnOrZero(withdrawalAmount.toString()).gte(coolDownInfo.amount) const validCycleAndAmount = (pastTokeCycleIndex && stakingTokenAvailableWithTokemak.gte(coolDownInfo.amount)) || stakingTokenAvailable - const epochsLeft = bnOrZero(coolDownInfo.endEpoch.toString()).minus(epoch.number.toString()) + const epochsLeft = bnOrZero(coolDownInfo.endEpoch.toString()).minus( + epoch.number?.toString() ?? '0', + ) const blocksLeftInCurrentEpoch = - epochsLeft.gt(0) && epoch.endBlock.gt(currentBlock) - ? epoch.endBlock.sub(currentBlock).toNumber() + epochsLeft.gt(0) && bnOrZero(epoch.endBlock?.toString()).gt(currentBlock) + ? bnOrZero(epoch.endBlock?.toString()) + .minus(currentBlock) + .toNumber() : 0 // calculate time remaining in current epoch const blocksLeftInFutureEpochs = epochsLeft.minus(1).gt(0) - ? epochsLeft.minus(1).times(epoch.length).toNumber() + ? epochsLeft + .minus(1) + .times(epoch.length?.toString() ?? '0') + .toNumber() : 0 return ( From d877645ad5a0ddca2c46acbeb4724484141484c6 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 19 Feb 2024 14:30:15 -0800 Subject: [PATCH 25/60] fix: tests --- src/contracts/contractManager.ts | 7 +++---- .../getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts | 2 ++ .../swappers/CowSwapper/utils/helpers/helpers.test.ts | 2 ++ .../slices/opportunitiesSlice/resolvers/uniV2/utils.ts | 3 +-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/contracts/contractManager.ts b/src/contracts/contractManager.ts index b8fc5b0a53e..b59a82edb05 100644 --- a/src/contracts/contractManager.ts +++ b/src/contracts/contractManager.ts @@ -10,10 +10,9 @@ import { FarmingABI } from 'contracts/abis/farmingAbi' import { IUniswapV2Pair } from 'contracts/abis/IUniswapV2Pair' import { IUniswapV2Router02 } from 'contracts/abis/IUniswapV2Router02' import { THORChain_RouterABI } from 'contracts/abis/THORCHAIN_RouterABI' -import { ethers } from 'ethers' import memoize from 'lodash/memoize' import type { Address } from 'viem' -import { getContract } from 'viem' +import { getAddress, getContract } from 'viem' import { getEthersV5Provider } from 'lib/ethersProviderSingleton' import { viemClientByChainId, viemEthMainnetClient } from 'lib/viem-client' @@ -104,7 +103,7 @@ export const getOrCreateContractByType = ({ }) definedContracts.push({ contract, - address: ethers.getAddress(address), + address: getAddress(address), } as unknown as DefinedContract) return contract as KnownContractByType } @@ -112,7 +111,7 @@ export const getOrCreateContractByType = ({ export const fetchUniV2PairData = memoize(async (pairAssetId: AssetId) => { const { assetReference, chainId } = fromAssetId(pairAssetId) // Checksum - const contractAddress = ethers.getAddress(assetReference) + const contractAddress = getAddress(assetReference) const pair = getOrCreateContractByType({ address: contractAddress, type: ContractType.UniV2Pair, diff --git a/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts b/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts index e25fac85020..3b8dd0a578a 100644 --- a/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts +++ b/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts @@ -25,6 +25,8 @@ const mocks = vi.hoisted(() => ({ post: vi.fn(), })) +vi.unmock('ethers') + vi.mock('../utils/cowService', () => { const mockAxios = { default: { diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts index f80b30c8fc9..0a76a4846f8 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts @@ -14,6 +14,8 @@ vi.mock('../cowService', async () => { } }) +vi.unmock('ethers') + describe('utils', () => { describe('getNowPlusThirtyMinutesTimestamp', () => { const mockDay = '2020-12-31' diff --git a/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts b/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts index 36e6ee2ed61..f61e93812e4 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/uniV2/utils.ts @@ -5,10 +5,9 @@ import type { TokenAmount } from '@uniswap/sdk' import type { IUniswapV2Pair } from 'contracts/abis/IUniswapV2Pair' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { getAddress } from 'ethers' import memoize from 'lodash/memoize' import type { GetContractReturnType, PublicClient, WalletClient } from 'viem' -import { parseAbiItem } from 'viem' +import { getAddress, parseAbiItem } from 'viem' import type { BN } from 'lib/bignumber/bignumber' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { viemEthMainnetClient } from 'lib/viem-client' From db30dd593393c021911fa8e6370ae002c8dbcedc Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 09:45:12 -0800 Subject: [PATCH 26/60] feat: temporarily exclude tests --- vitest-web.config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vitest-web.config.ts b/vitest-web.config.ts index 2e0ce781add..c4083c636b3 100644 --- a/vitest-web.config.ts +++ b/vitest-web.config.ts @@ -16,6 +16,9 @@ export default defineConfig({ exclude: [ 'src/lib/poll/poll.test.ts', 'src/lib/cryptography/login.test.ts', + // Temporarily skipped until https://github.com/shapeshift/hdwallet/pull/666 goes in + 'src/components/Modals/Send/hooks/useSendDetails/useSendDetails.test.tsx', + 'src/components/Modals/Send/hooks/useFormSend/useFormSend.test.tsx', 'packages/**/*.test.ts', 'packages/**/*.test.tsx', ], From e7115354ce97022b074a781cf8959479b69633ff Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:12:57 -0800 Subject: [PATCH 27/60] feat: import zeroAddress from viem --- .../src/evm/gnosis/GnosisChainAdapter.test.ts | 8 ++++---- .../Withdraw/components/Confirm.tsx | 5 ++--- .../Withdraw/components/Withdraw.tsx | 5 ++--- src/lib/swapper/swappers/CowSwapper/utils/constants.ts | 4 ++-- .../components/ReusableLpStatus/TransactionRow.tsx | 7 +++---- src/test/mocks/txs.ts | 10 +++++----- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts index 8b77d9f83af..206f8af4792 100644 --- a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts @@ -12,8 +12,8 @@ import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' import type { ethers } from 'ethers' -import { ZeroAddress } from 'ethers' import { merge } from 'lodash' +import { zeroAddress } from 'viem' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -227,7 +227,7 @@ describe('GnosisChainAdapter', () => { to: '0x642F4Bda144C63f6DC47EE0fDfbac0a193e2eDb7', value: '123', chainSpecific: { - from: ZeroAddress, + from: zeroAddress, data: '0x', }, } @@ -553,7 +553,7 @@ describe('GnosisChainAdapter', () => { const adapter = new gnosis.ChainAdapter(args) const wallet = await getWallet() - wallet.ethGetAddress = async () => await Promise.resolve(ZeroAddress) + wallet.ethGetAddress = async () => await Promise.resolve(zeroAddress) const tx = { wallet, @@ -656,7 +656,7 @@ describe('GnosisChainAdapter', () => { const tx = { wallet: await getWallet(), accountNumber, - to: ZeroAddress, + to: zeroAddress, value, chainSpecific: makeChainSpecific({ contractAddress }), } as unknown as BuildSendTxInput diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx index 7ec5e7b87f8..6aaebf947ea 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx @@ -19,7 +19,6 @@ import { getConfig } from 'config' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' import dayjs from 'dayjs' -import { ZeroAddress } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import type { @@ -30,7 +29,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useIsTradingActive } from 'react-queries/hooks/useIsTradingActive' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, zeroAddress } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetIcon } from 'components/AssetIcon' import type { StepComponentProps } from 'components/DeFi/components/Steps' @@ -415,7 +414,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - getAddress(ZeroAddress), + getAddress(zeroAddress), BigInt(amount), quote.memo, BigInt(quote.expiry), diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx index 4259b910034..6b0248ce5df 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx @@ -6,7 +6,6 @@ import { Err, Ok, type Result } from '@sniptt/monads' import { useQueryClient } from '@tanstack/react-query' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ZeroAddress } from 'ethers' import type { WithdrawValues } from 'features/defi/components/Withdraw/Withdraw' import { Field, Withdraw as ReusableWithdraw } from 'features/defi/components/Withdraw/Withdraw' import type { @@ -17,7 +16,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useCallback, useContext, useMemo, useState } from 'react' import { FormProvider, useForm } from 'react-hook-form' import { useTranslate } from 'react-polyglot' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, zeroAddress } from 'viem' import { Amount } from 'components/Amount/Amount' import type { StepComponentProps } from 'components/DeFi/components/Steps' import { getChainShortName } from 'components/MultiHopTrade/components/MultiHopTradeConfirm/utils/getChainShortName' @@ -274,7 +273,7 @@ export const Withdraw: React.FC = ({ accountId, fromAddress, onNe getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - getAddress(ZeroAddress), + getAddress(zeroAddress), BigInt(amountCryptoBaseUnit), quote.memo, BigInt(quote.expiry), diff --git a/src/lib/swapper/swappers/CowSwapper/utils/constants.ts b/src/lib/swapper/swappers/CowSwapper/utils/constants.ts index 6e1afaec3e5..2de8b3370c7 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/constants.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/constants.ts @@ -1,5 +1,5 @@ import { KnownChainIds } from '@shapeshiftoss/types' -import { ZeroAddress } from 'ethers' +import { zeroAddress } from 'viem' import type { CowChainId } from '../types' @@ -8,7 +8,7 @@ export const MIN_COWSWAP_USD_TRADE_VALUES_BY_CHAIN_ID: Record = ({ if (!inboundAddressData?.router) return undefined const assetAddress = isToken(fromAssetId(assetId).assetReference) ? getAddress(fromAssetId(assetId).assetReference) - : ZeroAddress + : zeroAddress const amount = BigInt(toBaseUnit(amountCryptoPrecision, asset.precision).toString()) const args = (() => { @@ -297,7 +296,7 @@ export const TransactionRow: React.FC = ({ ? getAddress(fromAssetId(assetId).assetReference) : // Native EVM assets use the 0 address as the asset address // https://dev.thorchain.org/concepts/sending-transactions.html#admonition-info-1 - ZeroAddress + zeroAddress const memo = `+:${thorchainNotationAssetId}:${otherAssetAddress ?? ''}:ss:${ confirmedQuote.feeBps diff --git a/src/test/mocks/txs.ts b/src/test/mocks/txs.ts index 11cd812b582..9de9145f88b 100644 --- a/src/test/mocks/txs.ts +++ b/src/test/mocks/txs.ts @@ -1,7 +1,7 @@ import { ethAssetId, ethChainId, foxAssetId } from '@shapeshiftoss/caip' import { UtxoAccountType } from '@shapeshiftoss/types' import { Dex, TradeType, TransferType, TxStatus } from '@shapeshiftoss/unchained-client' -import { ZeroAddress } from 'ethers' +import { zeroAddress } from 'viem' import type { Tx } from 'state/slices/txHistorySlice/txHistorySlice' export const EthSend: Tx = { @@ -119,7 +119,7 @@ export const TradeTx: Tx = { transfers: [ { assetId: 'eip155:1/erc20:0x5f18c75abdae578b483e5f43f12a39cf75b973a9', - from: [ZeroAddress], + from: [zeroAddress], to: ['0x934be745172066EDF795ffc5EA9F28f19b440c63'], type: TransferType.Receive, value: '9178352', @@ -315,7 +315,7 @@ export const yearnVaultDeposit: Tx = { transfers: [ { assetId: 'eip155:1/erc20:0x5f18c75abdae578b483e5f43f12a39cf75b973a9', - from: [ZeroAddress], + from: [zeroAddress], to: ['0x934be745172066EDF795ffc5EA9F28f19b440c63'], type: TransferType.Receive, value: '9178352', @@ -353,7 +353,7 @@ export const createMockEthTxs = (account: string): Tx[] => { }, { assetId: 'eip155:1/erc20:0xfbeb78a723b8087fd2ea7ef1afec93d35e8bed42', - from: [ZeroAddress], + from: [zeroAddress], to: [account], type: TransferType.Receive, value: '5481290118862792961', @@ -378,7 +378,7 @@ export const createMockEthTxs = (account: string): Tx[] => { { assetId: 'eip155:1/erc20:0xfbeb78a723b8087fd2ea7ef1afec93d35e8bed42', from: [account], - to: [ZeroAddress], + to: [zeroAddress], type: TransferType.Send, value: '5481290118862792961', }, From ee8e6c3f4057c14c849a0523d0e960f11ac5a4df Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:16:17 -0800 Subject: [PATCH 28/60] feat: viem getAddress --- .../foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx | 4 ++-- .../foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx | 3 ++- .../UniV2Manager/Withdraw/components/Approve.tsx | 3 +-- .../UniV2Manager/Withdraw/components/Withdraw.tsx | 3 +-- .../defi/providers/univ2/hooks/useUniV2LiquidityPool.ts | 7 +++---- src/lib/address/yat.ts | 4 ++-- src/lib/investor/investor-foxy/api/api.ts | 5 +++-- src/lib/utils/evm.ts | 4 ++-- src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx | 3 ++- .../slices/opportunitiesSlice/resolvers/uniV2/index.ts | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx index 69289bdfb53..1edaf8ff7b1 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Deposit/FoxyDeposit.tsx @@ -2,7 +2,6 @@ import { Center } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { toAssetId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import { ethers } from 'ethers' import { DefiModalContent } from 'features/defi/components/DefiModal/DefiModalContent' import { DefiModalHeader } from 'features/defi/components/DefiModal/DefiModalHeader' import type { @@ -14,6 +13,7 @@ import qs from 'qs' import { useCallback, useEffect, useMemo, useReducer } from 'react' import { useTranslate } from 'react-polyglot' import { useSelector } from 'react-redux' +import { getAddress } from 'viem' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import { CircularProgress } from 'components/CircularProgress/CircularProgress' import type { DefiStepProps } from 'components/DeFi/components/Steps' @@ -93,7 +93,7 @@ export const FoxyDeposit: React.FC<{ ) return const foxyOpportunity = await foxyApi.getFoxyOpportunityByStakingAddress( - ethers.getAddress(foxyStakingContractAddress), + getAddress(foxyStakingContractAddress), ) dispatch({ type: FoxyDepositActionType.SET_OPPORTUNITY, diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx index 391b489ac89..18b5e3d754a 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx @@ -14,6 +14,7 @@ import qs from 'qs' import { useCallback, useEffect, useMemo, useReducer } from 'react' import { useTranslate } from 'react-polyglot' import { useSelector } from 'react-redux' +import { getAddress } from 'viem' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import { CircularProgress } from 'components/CircularProgress/CircularProgress' import type { DefiStepProps } from 'components/DeFi/components/Steps' @@ -75,7 +76,7 @@ export const FoxyWithdraw: React.FC<{ ) return const foxyOpportunity = await foxyApi.getFoxyOpportunityByStakingAddress( - ethers.getAddress(foxyStakingContractAddress), + getAddress(foxyStakingContractAddress), ) // Get foxy fee for instant sends const foxyFeePercentage = await foxyApi.instantUnstakeFee({ diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx index 0024590a8e0..a4b06d7ab1b 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx @@ -3,7 +3,6 @@ import type { AccountId } from '@shapeshiftoss/caip' import { ethAssetId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import { UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS } from 'contracts/constants' -import { ethers } from 'ethers' import { Approve as ReusableApprove } from 'features/defi/components/Approve/Approve' import { ApprovePreFooter } from 'features/defi/components/Approve/ApprovePreFooter' import type { @@ -113,7 +112,7 @@ export const Approve: React.FC = ({ accountId, onNext }) => { try { dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: true }) - const lpAssetContractAddress = ethers.getAddress(fromAssetId(lpAssetId).assetReference) + const lpAssetContractAddress = getAddress(fromAssetId(lpAssetId).assetReference) await approveAsset(getAddress(lpAssetContractAddress)) await poll({ fn: () => lpAllowance(), diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx index 6eb6bd65018..6d95c9f57ba 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx @@ -1,6 +1,5 @@ import type { AccountId } from '@shapeshiftoss/caip' import { ASSET_REFERENCE, fromAssetId, toAssetId } from '@shapeshiftoss/caip' -import { ethers } from 'ethers' import type { WithdrawValues } from 'features/defi/components/Withdraw/Withdraw' import { Field, Withdraw as ReusableWithdraw } from 'features/defi/components/Withdraw/Withdraw' import type { @@ -201,7 +200,7 @@ export const Withdraw: React.FC = ({ onNext(DefiStep.Confirm) dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: false }) } else { - const lpAssetContractAddress = ethers.getAddress(fromAssetId(lpAssetId).assetReference) + const lpAssetContractAddress = getAddress(fromAssetId(lpAssetId).assetReference) const fees = await getApproveFees(getAddress(lpAssetContractAddress)) if (!fees) return diff --git a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts index 54a3306b008..806ccdc440a 100644 --- a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts +++ b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts @@ -9,7 +9,6 @@ import { } from 'contracts/constants' import { getOrCreateContractByAddress, getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ethers } from 'ethers' import isNumber from 'lodash/isNumber' import { useCallback, useMemo } from 'react' import { type Address, encodeFunctionData, getAddress } from 'viem' @@ -81,16 +80,16 @@ export const useUniV2LiquidityPool = ({ // Checksummed addresses const asset0ContractAddress = useMemo( - () => ethers.getAddress(fromAssetId(assetId0OrWeth).assetReference), + () => getAddress(fromAssetId(assetId0OrWeth).assetReference), [assetId0OrWeth], ) const asset1ContractAddress = useMemo( - () => ethers.getAddress(fromAssetId(assetId1OrWeth).assetReference), + () => getAddress(fromAssetId(assetId1OrWeth).assetReference), [assetId1OrWeth], ) const lpContractAddress = useMemo( - () => ethers.getAddress(fromAssetId(lpAssetId).assetReference), + () => getAddress(fromAssetId(lpAssetId).assetReference), [lpAssetId], ) diff --git a/src/lib/address/yat.ts b/src/lib/address/yat.ts index 005c63ddf11..c87a154de5e 100644 --- a/src/lib/address/yat.ts +++ b/src/lib/address/yat.ts @@ -1,8 +1,8 @@ import type { AssetId } from '@shapeshiftoss/caip' import axios from 'axios' import { getConfig } from 'config' -import { ethers } from 'ethers' import GraphemeSplitter from 'grapheme-splitter' +import { getAddress } from 'viem' // validate a yat type ValidateYatArgs = { @@ -77,7 +77,7 @@ export const resolveYat: ResolveYat = async args => { })() if (!maybeAddress) return '' - return ethers.getAddress(maybeAddress) + return getAddress(maybeAddress) } catch (e) { return '' } diff --git a/src/lib/investor/investor-foxy/api/api.ts b/src/lib/investor/investor-foxy/api/api.ts index 2bcd57980dd..22f94599e6b 100644 --- a/src/lib/investor/investor-foxy/api/api.ts +++ b/src/lib/investor/investor-foxy/api/api.ts @@ -13,6 +13,7 @@ import type { BigNumber } from 'bignumber.js' import type { TransactionReceipt } from 'ethers' import { ethers } from 'ethers' import { toLower } from 'lodash' +import { getAddress } from 'viem' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { MAX_ALLOWANCE } from 'lib/investor/constants' import { DefiType } from 'state/slices/opportunitiesSlice/types' @@ -179,8 +180,8 @@ export class FoxyApi { } checksumAddress(address: string): string { - // ethers always returns checksum addresses from getAddress() calls - return ethers.getAddress(address) + // viem always returns checksum addresses from getAddress() calls + return getAddress(address) } private verifyAddresses(addresses: string[]) { diff --git a/src/lib/utils/evm.ts b/src/lib/utils/evm.ts index f88ee8281ac..b55b3ef67a8 100644 --- a/src/lib/utils/evm.ts +++ b/src/lib/utils/evm.ts @@ -16,7 +16,7 @@ import { getTxStatus } from '@shapeshiftoss/unchained-client/dist/evm' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' import { ethers } from 'ethers' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, getAddress } from 'viem' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' @@ -219,7 +219,7 @@ export const getApproveContractData = ({ spender, chainId, }: GetApproveContractDataArgs): string => { - const address = ethers.getAddress(to) + const address = getAddress(to) const contract = getOrCreateContractByType({ address, type: ContractType.ERC20, diff --git a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx index db88d3c2879..7ac06bc5d02 100644 --- a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx +++ b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx @@ -3,6 +3,7 @@ import { KnownChainIds } from '@shapeshiftoss/types' import { ethers, Fragment } from 'ethers' import type { TransactionParams } from 'plugins/walletConnectToDapps/types' import { useEffect, useMemo, useState } from 'react' +import { getAddress } from 'viem' import { getEthersProvider } from 'lib/ethersProviderSingleton' import { useGetContractAbiQuery } from 'state/apis/abi/abiApi' @@ -69,7 +70,7 @@ export const useGetAbi = (transactionParams: TransactionParams): ethers.Interfac EIP1967_IMPLEMENTATION_SLOT, ) // Remove the first 26 chars (64 hex digits) - implementationAddress = ethers.getAddress(paddedImplementationAddress.substring(26)) + implementationAddress = getAddress(paddedImplementationAddress.substring(26)) break default: implementationAddress = null diff --git a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts index 1e54f9d820b..325a63695ed 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/uniV2/index.ts @@ -4,7 +4,7 @@ import type { TokenAmount } from '@uniswap/sdk' import { WETH_TOKEN_CONTRACT_ADDRESS } from 'contracts/constants' import { fetchUniV2PairData, getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { getAddress } from 'ethers' +import { getAddress } from 'viem' import type { BN } from 'lib/bignumber/bignumber' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { getEthersProvider } from 'lib/ethersProviderSingleton' From efc5f1b26e54e40405e45cebef7970c5e0f94810 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:17:47 -0800 Subject: [PATCH 29/60] feat: viem isHex --- src/lib/swapper/swappers/CowSwapper/CowSwapper.ts | 5 +++-- src/plugins/walletConnectToDapps/utils.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts b/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts index ae251b1e93a..c101d82b5a1 100644 --- a/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts +++ b/src/lib/swapper/swappers/CowSwapper/CowSwapper.ts @@ -7,7 +7,8 @@ import type { } from '@shapeshiftoss/swapper' import type { Asset } from '@shapeshiftoss/types' import { getConfig } from 'config' -import { ethers, isHexString } from 'ethers' +import { ethers } from 'ethers' +import { isHex } from 'viem' import { filterAssetIdsBySellable } from './filterAssetIdsBySellable/filterAssetIdsBySellable' import { filterBuyAssetsBySellAssetId } from './filterBuyAssetsBySellAssetId/filterBuyAssetsBySellAssetId' @@ -37,7 +38,7 @@ export const cowSwapper: Swapper = { // orderDigest should be an hex string here. All we need to do is pass it to signMessage/wallet.ethSignMessage and sign it const messageToSign = orderDigest - if (!isHexString(messageToSign)) throw new Error('messageToSign is not an hex string') + if (!isHex(messageToSign)) throw new Error('messageToSign is not an hex string') const signatureOrderDigest = await signMessage(messageToSign) diff --git a/src/plugins/walletConnectToDapps/utils.ts b/src/plugins/walletConnectToDapps/utils.ts index 160e9535539..8fd6329f3e0 100644 --- a/src/plugins/walletConnectToDapps/utils.ts +++ b/src/plugins/walletConnectToDapps/utils.ts @@ -8,7 +8,7 @@ import type { GetFeeDataInput, } from '@shapeshiftoss/chain-adapters' import type { SessionTypes } from '@walletconnect/types' -import { isAddress, isHexString, toBeHex, toUtf8String } from 'ethers' +import { isAddress, toBeHex, toUtf8String } from 'ethers' import type { ConfirmData, CosmosSignAminoCallRequestParams, @@ -18,6 +18,7 @@ import type { TransactionParams, WalletConnectState, } from 'plugins/walletConnectToDapps/types' +import { isHex } from 'viem' import { bnOrZero } from 'lib/bignumber/bignumber' import { isSome } from 'lib/utils' @@ -26,7 +27,7 @@ import { isSome } from 'lib/utils' */ export const maybeConvertHexEncodedMessageToUtf8 = (value: string) => { try { - return isHexString(value) ? toUtf8String(value) : value + return isHex(value) ? toUtf8String(value) : value } catch (e) { // use raw hex string if unable to convert to utf8 (ex. keccak256) return value From 6d833575d4668b9801024ed5f4215552c76a8453 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:19:26 -0800 Subject: [PATCH 30/60] feat: viem isAddress --- packages/chain-adapters/src/evm/EvmBaseAdapter.ts | 3 ++- src/plugins/walletConnectToDapps/utils.ts | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts index 8e5b549e118..4480a4697e2 100644 --- a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts +++ b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts @@ -21,7 +21,8 @@ import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' import BigNumber from 'bignumber.js' -import { isAddress, toQuantity } from 'ethers' +import { toQuantity } from 'ethers' +import { isAddress } from 'viem' import { numberToHex } from 'web3-utils' import type { ChainAdapter as IChainAdapter } from '../api' diff --git a/src/plugins/walletConnectToDapps/utils.ts b/src/plugins/walletConnectToDapps/utils.ts index 8fd6329f3e0..f903daa9e38 100644 --- a/src/plugins/walletConnectToDapps/utils.ts +++ b/src/plugins/walletConnectToDapps/utils.ts @@ -8,7 +8,7 @@ import type { GetFeeDataInput, } from '@shapeshiftoss/chain-adapters' import type { SessionTypes } from '@walletconnect/types' -import { isAddress, toBeHex, toUtf8String } from 'ethers' +import { toBeHex, toUtf8String } from 'ethers' import type { ConfirmData, CosmosSignAminoCallRequestParams, @@ -18,7 +18,7 @@ import type { TransactionParams, WalletConnectState, } from 'plugins/walletConnectToDapps/types' -import { isHex } from 'viem' +import { isAddress, isHex } from 'viem' import { bnOrZero } from 'lib/bignumber/bignumber' import { isSome } from 'lib/utils' From a526412bc92e428a1d72e03a395a416ae6c55f4a Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:21:02 -0800 Subject: [PATCH 31/60] feat: viem toHex --- packages/chain-adapters/src/evm/EvmBaseAdapter.ts | 5 ++--- src/components/Layout/Header/NavBar/ChainMenu.tsx | 4 ++-- src/components/Layout/Header/NavBar/Notifications.tsx | 4 ++-- .../ThorchainSaversManager/Deposit/components/Confirm.tsx | 8 ++++---- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts index 4480a4697e2..f6db31a8d30 100644 --- a/packages/chain-adapters/src/evm/EvmBaseAdapter.ts +++ b/packages/chain-adapters/src/evm/EvmBaseAdapter.ts @@ -21,8 +21,7 @@ import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' import BigNumber from 'bignumber.js' -import { toQuantity } from 'ethers' -import { isAddress } from 'viem' +import { isAddress, toHex } from 'viem' import { numberToHex } from 'web3-utils' import type { ChainAdapter as IChainAdapter } from '../api' @@ -248,7 +247,7 @@ export abstract class EvmBaseAdapter implements IChainAdap }[this.chainId] await wallet.ethSwitchChain({ - chainId: toQuantity(adapterChainReference), + chainId: toHex(adapterChainReference), chainName: this.getDisplayName(), nativeCurrency: { name: targetNetwork.name, diff --git a/src/components/Layout/Header/NavBar/ChainMenu.tsx b/src/components/Layout/Header/NavBar/ChainMenu.tsx index 17b4cda2212..d17745c9d95 100644 --- a/src/components/Layout/Header/NavBar/ChainMenu.tsx +++ b/src/components/Layout/Header/NavBar/ChainMenu.tsx @@ -17,9 +17,9 @@ import type { ChainId } from '@shapeshiftoss/caip' import { fromChainId, gnosisChainId } from '@shapeshiftoss/caip' import type { ETHWallet } from '@shapeshiftoss/hdwallet-core' import { supportsEthSwitchChain } from '@shapeshiftoss/hdwallet-core' -import { toQuantity } from 'ethers' import { memo, useCallback, useMemo } from 'react' import { useTranslate } from 'react-polyglot' +import { toHex } from 'viem' import { AssetIcon } from 'components/AssetIcon' import { CircleIcon } from 'components/Icons/Circle' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' @@ -106,7 +106,7 @@ export const ChainMenu = memo((props: ChainMenuProps) => { requestedChainId === gnosisChainId ? ['https://rpc.gnosischain.com'] : [] const requestedChainRpcUrl = requestedChainChainAdapter.getRpcUrl() await (state.wallet as ETHWallet).ethSwitchChain?.({ - chainId: toQuantity(Number(requestedEthNetwork)), + chainId: toHex(Number(requestedEthNetwork)), chainName: requestedChainChainAdapter.getDisplayName(), nativeCurrency: { name: requestedChainFeeAsset.name, diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index 6731eba9975..4fba919571c 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -3,7 +3,7 @@ import type { BIP32Path, ETHSignTypedData } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { CustomTheme, ThemeMode as ThemeModeType } from '@wherever/react-notification-feed' import { getConfig } from 'config' -import { toQuantity, toUtf8Bytes } from 'ethers' +import { toUtf8Bytes } from 'ethers' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { KeyManager } from 'context/WalletProvider/KeyManager' @@ -92,7 +92,7 @@ export const Notifications = memo(() => { try { const signedMsg = await wallet.ethSignMessage({ addressNList, - message: toQuantity(toUtf8Bytes(message)), + message: toHex(toUtf8Bytes(message)), }) return signedMsg?.signature diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index 82b2609fe71..4d2c1f90eb6 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -18,7 +18,7 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { toQuantity, toUtf8Bytes } from 'ethers' +import { toUtf8Bytes } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import type { @@ -29,7 +29,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useIsTradingActive } from 'react-queries/hooks/useIsTradingActive' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetIcon } from 'components/AssetIcon' import type { StepComponentProps } from 'components/DeFi/components/Steps' @@ -258,7 +258,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { from: maybeFromUTXOAccountAddress, to: quote.inbound_address, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toQuantity(toUtf8Bytes(memoUtf8)) + ? toHex(toUtf8Bytes(memoUtf8)) : memoUtf8, sendMax: Boolean(!isUtxoChainId(chainId) && state?.deposit.sendMax), accountId, @@ -477,7 +477,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { sendMax: Boolean(state?.deposit.sendMax), accountId, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toQuantity(toUtf8Bytes(memoUtf8)) + ? toHex(toUtf8Bytes(memoUtf8)) : memoUtf8, amountFieldError: '', estimatedFees, From 5ed9d65a45dbcbd5821d5bccab96dfff116ce324 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:24:33 -0800 Subject: [PATCH 32/60] feat: viem hexlify -> toHex --- .../src/evm/arbitrum/ArbitrumChainAdapter.test.ts | 2 +- .../src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts | 2 +- .../src/evm/avalanche/AvalancheChainAdapter.test.ts | 2 +- .../src/evm/bnbsmartchain/BscChainAdapter.test.ts | 2 +- .../src/evm/ethereum/EthereumChainAdapter.test.ts | 2 +- .../src/evm/gnosis/GnosisChainAdapter.test.ts | 2 +- .../src/evm/optimism/OptimismChainAdapter.test.ts | 2 +- .../src/evm/polygon/PolygonChainAdapter.test.ts | 2 +- src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx | 5 +++-- src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx | 7 ++++--- src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts | 5 +++-- 11 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts index b08f40694e3..4a94ce6fad8 100644 --- a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts @@ -399,7 +399,7 @@ describe('ArbitrumChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts index 5080fd59aaf..87390e7a344 100644 --- a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts @@ -404,7 +404,7 @@ describe('ArbitrumNovaChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts index a8d95ade678..65fb9acc863 100644 --- a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts @@ -405,7 +405,7 @@ describe('AvalancheChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts index 872f0f3c6bd..8a5131b22d0 100644 --- a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts @@ -382,7 +382,7 @@ describe('BscChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts index 4d9785a850b..496b28ca3d3 100644 --- a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts @@ -439,7 +439,7 @@ describe('EthereumChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts index 206f8af4792..6cb16d6afb7 100644 --- a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts @@ -405,7 +405,7 @@ describe('GnosisChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts index d2f5aded5b7..04c770931ef 100644 --- a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts @@ -406,7 +406,7 @@ describe('OptimismChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts index 51db2c6f6ac..85f9a329911 100644 --- a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts @@ -399,7 +399,7 @@ describe('PolygonChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) }) }) diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx index d55b7f8a02b..01af32fe04d 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx @@ -21,12 +21,13 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { hexlify, toUtf8Bytes } from 'ethers' +import { toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' +import { toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' @@ -299,7 +300,7 @@ export const BorrowConfirm = ({ sendMax: false, accountId: collateralAccountId, memo: supportedEvmChainIds.includes(fromAssetId(collateralAssetId).chainId as KnownChainIds) - ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index d9dd9c1a964..8a085fc3b35 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -23,12 +23,13 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { hexlify, toUtf8Bytes } from 'ethers' +import { toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' +import { toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' @@ -290,7 +291,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset.assetId).chainId as KnownChainIds, ) - ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, to: confirmedQuote.quoteInboundAddress, sendMax: false, @@ -342,7 +343,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset?.assetId).chainId as KnownChainIds, ) - ? hexlify(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 004df1fb3fa..05c15e84e57 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -1,8 +1,9 @@ import { type AccountId, type AssetId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset, KnownChainIds, MarketData } from '@shapeshiftoss/types' import { useQuery } from '@tanstack/react-query' -import { hexlify, toUtf8Bytes } from 'ethers' +import { toUtf8Bytes } from 'ethers' import { useMemo } from 'react' +import { toHex } from 'viem' import type { EstimateFeesInput } from 'components/Modals/Send/utils' import { estimateFees } from 'components/Modals/Send/utils' import { bn, bnOrZero } from 'lib/bignumber/bignumber' @@ -71,7 +72,7 @@ export const useQuoteEstimatedFeesQuery = ({ confirmedQuote && 'quoteMemo' in confirmedQuote ? confirmedQuote.quoteMemo : '' const memo = assetId && supportedEvmChainIds.includes(fromAssetId(assetId).chainId as KnownChainIds) - ? hexlify(toUtf8Bytes(quoteMemo)) + ? toHex(toUtf8Bytes(quoteMemo)) : quoteMemo const to = confirmedQuote && 'quoteInboundAddress' in confirmedQuote From 57bcfca1dbbbe7c2f2be66525a6a0db94d36f6d3 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:27:12 -0800 Subject: [PATCH 33/60] feat: viem stringToBytes --- src/components/Layout/Header/NavBar/Notifications.tsx | 4 ++-- .../ThorchainSaversManager/Deposit/components/Confirm.tsx | 7 +++---- .../swapper/swappers/CowSwapper/utils/helpers/helpers.ts | 5 +++-- src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx | 5 ++--- src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx | 7 +++---- src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts | 5 ++--- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index 4fba919571c..24f9f28d72a 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -3,9 +3,9 @@ import type { BIP32Path, ETHSignTypedData } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { CustomTheme, ThemeMode as ThemeModeType } from '@wherever/react-notification-feed' import { getConfig } from 'config' -import { toUtf8Bytes } from 'ethers' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' +import { stringToBytes } from 'viem' import { KeyManager } from 'context/WalletProvider/KeyManager' import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from 'hooks/useWallet/useWallet' @@ -92,7 +92,7 @@ export const Notifications = memo(() => { try { const signedMsg = await wallet.ethSignMessage({ addressNList, - message: toHex(toUtf8Bytes(message)), + message: toHex(stringToBytes(message)), }) return signedMsg?.signature diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index 4d2c1f90eb6..ae4ef606328 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -18,7 +18,6 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { toUtf8Bytes } from 'ethers' import { Confirm as ReusableConfirm } from 'features/defi/components/Confirm/Confirm' import { Summary } from 'features/defi/components/Summary' import type { @@ -29,7 +28,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useIsTradingActive } from 'react-queries/hooks/useIsTradingActive' -import { encodeFunctionData, getAddress, toHex } from 'viem' +import { encodeFunctionData, getAddress, stringToBytes, toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetIcon } from 'components/AssetIcon' import type { StepComponentProps } from 'components/DeFi/components/Steps' @@ -258,7 +257,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { from: maybeFromUTXOAccountAddress, to: quote.inbound_address, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toHex(toUtf8Bytes(memoUtf8)) + ? toHex(stringToBytes(memoUtf8)) : memoUtf8, sendMax: Boolean(!isUtxoChainId(chainId) && state?.deposit.sendMax), accountId, @@ -477,7 +476,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { sendMax: Boolean(state?.deposit.sendMax), accountId, memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toHex(toUtf8Bytes(memoUtf8)) + ? toHex(stringToBytes(memoUtf8)) : memoUtf8, amountFieldError: '', estimatedFees, diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts index 5334dfadb10..6e533c0d166 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts @@ -11,7 +11,8 @@ import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import { getConfig } from 'config' import type { TypedDataDomain, TypedDataField } from 'ethers' -import { keccak256, toUtf8Bytes, TypedDataEncoder } from 'ethers' +import { keccak256, TypedDataEncoder } from 'ethers' +import { stringToBytes } from 'viem' import { bnOrZero, convertPrecision } from 'lib/bignumber/bignumber' import { fromBaseUnit } from 'lib/math' import { convertDecimalPercentageToBasisPoints } from 'state/slices/tradeQuoteSlice/utils' @@ -215,7 +216,7 @@ const generateAppDataFromDoc = async ( doc: LatestAppDataDocVersion, ): Promise> => { const appData = await stringifyDeterministic(doc) - const appDataKeccak256 = keccak256(toUtf8Bytes(appData)) + const appDataKeccak256 = keccak256(stringToBytes(appData)) return { fullAppData: appData, appDataKeccak256 } } diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx index 01af32fe04d..64e2a398ec5 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx @@ -21,13 +21,12 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' -import { toHex } from 'viem' +import { stringToBytes, toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' @@ -300,7 +299,7 @@ export const BorrowConfirm = ({ sendMax: false, accountId: collateralAccountId, memo: supportedEvmChainIds.includes(fromAssetId(collateralAssetId).chainId as KnownChainIds) - ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(stringToBytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index 8a085fc3b35..e9582430433 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -23,13 +23,12 @@ import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { useMutation, useMutationState } from '@tanstack/react-query' import dayjs from 'dayjs' -import { toUtf8Bytes } from 'ethers' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' -import { toHex } from 'viem' +import { stringToBytes, toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' @@ -291,7 +290,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset.assetId).chainId as KnownChainIds, ) - ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(stringToBytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, to: confirmedQuote.quoteInboundAddress, sendMax: false, @@ -343,7 +342,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset?.assetId).chainId as KnownChainIds, ) - ? toHex(toUtf8Bytes(confirmedQuote.quoteMemo)) + ? toHex(stringToBytes(confirmedQuote.quoteMemo)) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 05c15e84e57..89a335e353e 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -1,9 +1,8 @@ import { type AccountId, type AssetId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset, KnownChainIds, MarketData } from '@shapeshiftoss/types' import { useQuery } from '@tanstack/react-query' -import { toUtf8Bytes } from 'ethers' import { useMemo } from 'react' -import { toHex } from 'viem' +import { stringToBytes, toHex } from 'viem' import type { EstimateFeesInput } from 'components/Modals/Send/utils' import { estimateFees } from 'components/Modals/Send/utils' import { bn, bnOrZero } from 'lib/bignumber/bignumber' @@ -72,7 +71,7 @@ export const useQuoteEstimatedFeesQuery = ({ confirmedQuote && 'quoteMemo' in confirmedQuote ? confirmedQuote.quoteMemo : '' const memo = assetId && supportedEvmChainIds.includes(fromAssetId(assetId).chainId as KnownChainIds) - ? toHex(toUtf8Bytes(quoteMemo)) + ? toHex(stringToBytes(quoteMemo)) : quoteMemo const to = confirmedQuote && 'quoteInboundAddress' in confirmedQuote From 604bf0573fab42d03839dfb4d5145a45fa60ceab Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:30:17 -0800 Subject: [PATCH 34/60] feat: viem keccak256 --- src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts index 6e533c0d166..a0d060a6d44 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts @@ -11,8 +11,8 @@ import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import { getConfig } from 'config' import type { TypedDataDomain, TypedDataField } from 'ethers' -import { keccak256, TypedDataEncoder } from 'ethers' -import { stringToBytes } from 'viem' +import { TypedDataEncoder } from 'ethers' +import { keccak256, stringToBytes } from 'viem' import { bnOrZero, convertPrecision } from 'lib/bignumber/bignumber' import { fromBaseUnit } from 'lib/math' import { convertDecimalPercentageToBasisPoints } from 'state/slices/tradeQuoteSlice/utils' From 214c676c9cec41b63901eb36c43d27a00ed86365 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 21 Feb 2024 07:14:15 -0800 Subject: [PATCH 35/60] feat: cleanup --- src/components/Layout/Header/NavBar/Notifications.tsx | 2 +- .../foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx | 1 - src/lib/utils/evm.ts | 3 +-- .../ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index 24f9f28d72a..83496753202 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -5,7 +5,7 @@ import type { CustomTheme, ThemeMode as ThemeModeType } from '@wherever/react-no import { getConfig } from 'config' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' -import { stringToBytes } from 'viem' +import { stringToBytes, toHex } from 'viem' import { KeyManager } from 'context/WalletProvider/KeyManager' import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from 'hooks/useWallet/useWallet' diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx index 18b5e3d754a..2906db8dac4 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx @@ -1,7 +1,6 @@ import { Center } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import { ethers } from 'ethers' import { DefiModalContent } from 'features/defi/components/DefiModal/DefiModalContent' import { DefiModalHeader } from 'features/defi/components/DefiModal/DefiModalHeader' import type { diff --git a/src/lib/utils/evm.ts b/src/lib/utils/evm.ts index b55b3ef67a8..a2dddac44b0 100644 --- a/src/lib/utils/evm.ts +++ b/src/lib/utils/evm.ts @@ -15,8 +15,7 @@ import { TxStatus } from '@shapeshiftoss/unchained-client' import { getTxStatus } from '@shapeshiftoss/unchained-client/dist/evm' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ethers } from 'ethers' -import { encodeFunctionData, getAddress, getAddress } from 'viem' +import { encodeFunctionData, getAddress } from 'viem' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' diff --git a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx index 45ebfc9a8e7..6211b479bb8 100644 --- a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx +++ b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx @@ -471,7 +471,7 @@ export const TransactionRow: React.FC = ({ ? getAddress(fromAssetId(assetId).assetReference) : // Native EVM assets use the 0 address as the asset address // https://dev.thorchain.org/concepts/sending-transactions.html#admonition-info-1 - ZeroAddress + zeroAddress const memo = `+:${thorchainNotationAssetId}:${otherAssetAddress ?? ''}:ss:${ confirmedQuote.feeBps From b8919ab1aa6468bfce8c2daff053a5c1aa6d577a Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:17:11 -0700 Subject: [PATCH 36/60] fix tests and remove mock --- .../evm/arbitrum/ArbitrumChainAdapter.test.ts | 95 +------------------ .../ArbitrumNovaChainAdapter.test.ts | 95 +------------------ .../avalanche/AvalancheChainAdapter.test.ts | 95 +------------------ .../evm/bnbsmartchain/BscChainAdapter.test.ts | 95 +------------------ .../evm/ethereum/EthereumChainAdapter.test.ts | 95 +------------------ .../src/evm/gnosis/GnosisChainAdapter.test.ts | 95 +------------------ .../evm/optimism/OptimismChainAdapter.test.ts | 95 +------------------ .../evm/polygon/PolygonChainAdapter.test.ts | 95 +------------------ 8 files changed, 8 insertions(+), 752 deletions(-) diff --git a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts index 4a94ce6fad8..0e19b6f0602 100644 --- a/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrum/ArbitrumChainAdapter.test.ts @@ -5,7 +5,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -21,98 +20,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' @@ -399,7 +306,7 @@ describe('ArbitrumChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts index 87390e7a344..7835e2bf29d 100644 --- a/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/arbitrumNova/ArbitrumNovaChainAdapter.test.ts @@ -10,7 +10,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -26,98 +25,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' @@ -404,7 +311,7 @@ describe('ArbitrumNovaChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts index 65fb9acc863..712df823ae0 100644 --- a/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/avalanche/AvalancheChainAdapter.test.ts @@ -10,7 +10,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -26,98 +25,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' @@ -405,7 +312,7 @@ describe('AvalancheChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts index 8a5131b22d0..091ccf9ce2f 100644 --- a/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/bnbsmartchain/BscChainAdapter.test.ts @@ -5,7 +5,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -21,98 +20,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' @@ -382,7 +289,7 @@ describe('BscChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts index 496b28ca3d3..1aa5f393701 100644 --- a/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/ethereum/EthereumChainAdapter.test.ts @@ -5,7 +5,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -21,98 +20,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const ENS_NAME = 'vitalik.eth' @@ -439,7 +346,7 @@ describe('EthereumChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts index 6cb16d6afb7..d494ef8879e 100644 --- a/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/gnosis/GnosisChainAdapter.test.ts @@ -11,7 +11,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { zeroAddress } from 'viem' import { describe, expect, it, vi } from 'vitest' @@ -28,98 +27,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const testMnemonic = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' @@ -405,7 +312,7 @@ describe('GnosisChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts index 04c770931ef..22d798765a9 100644 --- a/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/optimism/OptimismChainAdapter.test.ts @@ -5,7 +5,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -22,98 +21,6 @@ const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' const testMnemonic = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const getWallet = async (): Promise => { const nativeAdapterArgs: NativeAdapterArgs = { mnemonic: testMnemonic, @@ -406,7 +313,7 @@ describe('OptimismChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) diff --git a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts index 85f9a329911..ed6b55be9b7 100644 --- a/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts +++ b/packages/chain-adapters/src/evm/polygon/PolygonChainAdapter.test.ts @@ -5,7 +5,6 @@ import { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { BIP44Params } from '@shapeshiftoss/types' import { KnownChainIds } from '@shapeshiftoss/types' import type * as unchained from '@shapeshiftoss/unchained-client' -import type { ethers } from 'ethers' import { merge } from 'lodash' import { describe, expect, it, vi } from 'vitest' import { numberToHex } from 'web3-utils' @@ -21,98 +20,6 @@ vi.mock('../../utils/validateAddress', () => ({ validateAddress: vi.fn(), })) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const EOA_ADDRESS = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' @@ -399,7 +306,7 @@ describe('PolygonChainAdapter', () => { }, } as unknown as SignTxInput - await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid toHex value/) + await expect(adapter.signTransaction(tx)).rejects.toThrow(/invalid hexlify value/) }) }) From 89dab361906a000102450de305c7fe6bf0bb0800 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:17:40 -0700 Subject: [PATCH 37/60] utils.ts @ethersproject -> ethers --- packages/chain-adapters/src/evm/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/chain-adapters/src/evm/utils.ts b/packages/chain-adapters/src/evm/utils.ts index 4a8344ef4ee..cd7779c73d5 100644 --- a/packages/chain-adapters/src/evm/utils.ts +++ b/packages/chain-adapters/src/evm/utils.ts @@ -1,4 +1,4 @@ -import { Contract } from '@ethersproject/contracts' +import { Contract } from 'ethers' import erc20Abi from './erc20Abi.json' @@ -9,6 +9,6 @@ export const getErc20Data = async ( ): Promise => { if (!contractAddress) return '' const erc20Contract = new Contract(contractAddress, erc20Abi) - const { data: callData } = await erc20Contract.populateTransaction.transfer(to, value) + const { data: callData } = await erc20Contract.transfer.populateTransaction(to, value) return callData || '' } From 37884a559880117aa552ebdf870a1f1cd713b1a9 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:27:12 -0800 Subject: [PATCH 38/60] feat: viem stringToBytes --- src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts index 5334dfadb10..6e533c0d166 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts @@ -11,7 +11,8 @@ import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import { getConfig } from 'config' import type { TypedDataDomain, TypedDataField } from 'ethers' -import { keccak256, toUtf8Bytes, TypedDataEncoder } from 'ethers' +import { keccak256, TypedDataEncoder } from 'ethers' +import { stringToBytes } from 'viem' import { bnOrZero, convertPrecision } from 'lib/bignumber/bignumber' import { fromBaseUnit } from 'lib/math' import { convertDecimalPercentageToBasisPoints } from 'state/slices/tradeQuoteSlice/utils' @@ -215,7 +216,7 @@ const generateAppDataFromDoc = async ( doc: LatestAppDataDocVersion, ): Promise> => { const appData = await stringifyDeterministic(doc) - const appDataKeccak256 = keccak256(toUtf8Bytes(appData)) + const appDataKeccak256 = keccak256(stringToBytes(appData)) return { fullAppData: appData, appDataKeccak256 } } From 7e2f644ca3366ffc6209e6e8f0305c51de1d08a1 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 20 Feb 2024 19:30:17 -0800 Subject: [PATCH 39/60] feat: viem keccak256 --- src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts index 6e533c0d166..a0d060a6d44 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.ts @@ -11,8 +11,8 @@ import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import { getConfig } from 'config' import type { TypedDataDomain, TypedDataField } from 'ethers' -import { keccak256, TypedDataEncoder } from 'ethers' -import { stringToBytes } from 'viem' +import { TypedDataEncoder } from 'ethers' +import { keccak256, stringToBytes } from 'viem' import { bnOrZero, convertPrecision } from 'lib/bignumber/bignumber' import { fromBaseUnit } from 'lib/math' import { convertDecimalPercentageToBasisPoints } from 'state/slices/tradeQuoteSlice/utils' From 24becf9fe03081f841d63f689ce56bb4f2683fb2 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Wed, 21 Feb 2024 07:14:15 -0800 Subject: [PATCH 40/60] feat: cleanup --- src/components/Layout/Header/NavBar/Notifications.tsx | 4 ++++ .../foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx | 1 - src/lib/utils/evm.ts | 3 +-- .../components/ReusableLpStatus/TransactionRow.tsx | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index 6731eba9975..a11a0c6ff89 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -6,6 +6,10 @@ import { getConfig } from 'config' import { toQuantity, toUtf8Bytes } from 'ethers' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' +<<<<<<< HEAD +======= +import { stringToBytes, toHex } from 'viem' +>>>>>>> 214c676c9c (feat: cleanup) import { KeyManager } from 'context/WalletProvider/KeyManager' import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from 'hooks/useWallet/useWallet' diff --git a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx index 18b5e3d754a..2906db8dac4 100644 --- a/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx +++ b/src/features/defi/providers/foxy/components/FoxyManager/Withdraw/FoxyWithdraw.tsx @@ -1,7 +1,6 @@ import { Center } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { KnownChainIds } from '@shapeshiftoss/types' -import { ethers } from 'ethers' import { DefiModalContent } from 'features/defi/components/DefiModal/DefiModalContent' import { DefiModalHeader } from 'features/defi/components/DefiModal/DefiModalHeader' import type { diff --git a/src/lib/utils/evm.ts b/src/lib/utils/evm.ts index b55b3ef67a8..a2dddac44b0 100644 --- a/src/lib/utils/evm.ts +++ b/src/lib/utils/evm.ts @@ -15,8 +15,7 @@ import { TxStatus } from '@shapeshiftoss/unchained-client' import { getTxStatus } from '@shapeshiftoss/unchained-client/dist/evm' import { getOrCreateContractByType } from 'contracts/contractManager' import { ContractType } from 'contracts/types' -import { ethers } from 'ethers' -import { encodeFunctionData, getAddress, getAddress } from 'viem' +import { encodeFunctionData, getAddress } from 'viem' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' diff --git a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx index 45ebfc9a8e7..6211b479bb8 100644 --- a/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx +++ b/src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx @@ -471,7 +471,7 @@ export const TransactionRow: React.FC = ({ ? getAddress(fromAssetId(assetId).assetReference) : // Native EVM assets use the 0 address as the asset address // https://dev.thorchain.org/concepts/sending-transactions.html#admonition-info-1 - ZeroAddress + zeroAddress const memo = `+:${thorchainNotationAssetId}:${otherAssetAddress ?? ''}:ss:${ confirmedQuote.feeBps From 807ce487e3bddc986ce59a6cf7bf8cabd2652e98 Mon Sep 17 00:00:00 2001 From: kevin <35275952+kaladinlight@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:38:57 -0700 Subject: [PATCH 41/60] fix: use correct account id for matching buy account (#6263) --- .../MultiHopTrade/hooks/useReceiveAddress.tsx | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx b/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx index abdbf45fbbb..45516a2f8e2 100644 --- a/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx +++ b/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx @@ -1,10 +1,14 @@ import { fromAccountId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import type { GetReceiveAddressArgs } from 'components/MultiHopTrade/types' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' -import { selectPortfolioAccountMetadataByAccountId } from 'state/slices/portfolioSlice/selectors' +import { + selectAccountIdByAccountNumberAndChainId, + selectAccountNumberByAccountId, + selectPortfolioAccountMetadataByAccountId, +} from 'state/slices/portfolioSlice/selectors' import { isUtxoAccountId } from 'state/slices/portfolioSlice/utils' import { selectFirstHopSellAccountId, @@ -40,9 +44,26 @@ export const useReceiveAddress = ({ // Selectors const buyAsset = useAppSelector(selectInputBuyAsset) const sellAssetAccountId = useAppSelector(selectFirstHopSellAccountId) + const sellAssetAccountNumberFilter = useMemo( + () => ({ accountId: sellAssetAccountId }), + [sellAssetAccountId], + ) + const sellAssetAccountNumber = useAppSelector(state => + selectAccountNumberByAccountId(state, sellAssetAccountNumberFilter), + ) + + const accountIdsByAccountNumberAndChainId = useAppSelector( + selectAccountIdByAccountNumberAndChainId, + ) + + const maybeMatchingBuyAccountId = useMemo(() => { + if (!buyAsset) return + if (sellAssetAccountNumber === undefined) return + return accountIdsByAccountNumberAndChainId[sellAssetAccountNumber]?.[buyAsset.chainId] + }, [accountIdsByAccountNumberAndChainId, sellAssetAccountNumber, buyAsset]) const buyAccountId = useAppSelector(state => - selectLastHopBuyAccountId(state, { accountId: sellAssetAccountId }), + selectLastHopBuyAccountId(state, { accountId: maybeMatchingBuyAccountId }), ) const buyAccountMetadata = useAppSelector(state => selectPortfolioAccountMetadataByAccountId(state, { accountId: buyAccountId }), From b50b749cecc05ecf483d21688f95b6f0f165195b Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Thu, 22 Feb 2024 10:37:47 +1100 Subject: [PATCH 42/60] Merge branch 'main' into develop (#6271) * fix: trades from native assets & utxos (#6260) fix: native allowance * fix: use correct chain id for matching buy account * fix: allow quote sell amounts to be lower than user input sell amount (#6265) * fix: allow quote sell amounts to be lower than user input sell amount * fix: fix logic, add a teeny tiny thrshold so cowswap works * fix: consolidate matching buy account id selection logic (#6268) * chore: fix merge --------- Co-authored-by: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Co-authored-by: woody <125113430+woodenfurniture@users.noreply.github.com> --- .../hooks/useIsApprovalNeeded.tsx | 2 +- .../MultiHopTrade/hooks/useAccountIds.tsx | 35 ++------------ .../useGetTradeQuotes/useGetTradeQuotes.tsx | 5 +- .../MultiHopTrade/hooks/useReceiveAddress.tsx | 48 ++++++------------- .../swapper/helpers/validateTradeQuote.ts | 8 ++-- src/state/slices/tradeInputSlice/selectors.ts | 48 +++++++++++++------ 6 files changed, 59 insertions(+), 87 deletions(-) diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useIsApprovalNeeded.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useIsApprovalNeeded.tsx index b3d4c520d7e..2b885d61738 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useIsApprovalNeeded.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useIsApprovalNeeded.tsx @@ -21,7 +21,7 @@ export const useIsApprovalNeeded = ( ? bn(allowanceCryptoBaseUnit).lt( tradeQuoteStep.sellAmountIncludingProtocolFeesCryptoBaseUnit, ) - : undefined + : false }, [tradeQuoteStep], ) diff --git a/src/components/MultiHopTrade/hooks/useAccountIds.tsx b/src/components/MultiHopTrade/hooks/useAccountIds.tsx index e90df7366c4..85f82ac7d86 100644 --- a/src/components/MultiHopTrade/hooks/useAccountIds.tsx +++ b/src/components/MultiHopTrade/hooks/useAccountIds.tsx @@ -1,12 +1,6 @@ import type { AccountId } from '@shapeshiftoss/caip' -import { useCallback, useMemo } from 'react' -import { - selectAccountIdByAccountNumberAndChainId, - selectAccountNumberByAccountId, - selectFirstHopSellAccountId, - selectInputBuyAsset, - selectLastHopBuyAccountId, -} from 'state/slices/selectors' +import { useCallback } from 'react' +import { selectFirstHopSellAccountId, selectLastHopBuyAccountId } from 'state/slices/selectors' import { tradeInput } from 'state/slices/tradeInputSlice/tradeInputSlice' import { useAppDispatch, useAppSelector } from 'state/store' @@ -19,31 +13,8 @@ export const useAccountIds = (): { const dispatch = useAppDispatch() // Default sellAssetAccountId selection - const sellAssetAccountId = useAppSelector(selectFirstHopSellAccountId) - const sellAssetAccountNumberFilter = useMemo( - () => ({ accountId: sellAssetAccountId }), - [sellAssetAccountId], - ) - const sellAssetAccountNumber = useAppSelector(state => - selectAccountNumberByAccountId(state, sellAssetAccountNumberFilter), - ) - - // Default buyAssetAccountId selection - - const accountIdsByAccountNumberAndChainId = useAppSelector( - selectAccountIdByAccountNumberAndChainId, - ) - const inputBuyAsset = useAppSelector(selectInputBuyAsset) - const maybeMatchingBuyAccountId = - accountIdsByAccountNumberAndChainId[sellAssetAccountNumber as number]?.[inputBuyAsset?.chainId] - - // We always default the buy asset account to be synchronized with the sellAssetAccountNumber - // - if this isn't possible, i.e there is no matching account number on the buy side, we default to the highest balance - // - if this was to fail for any reason, we default to the first account number as a default - const buyAssetAccountId = useAppSelector(state => - selectLastHopBuyAccountId(state, { accountId: maybeMatchingBuyAccountId }), - ) + const buyAssetAccountId = useAppSelector(selectLastHopBuyAccountId) // Setters - the selectors above initially select a *default* value, but eventually onAccountIdChange may fire if the user changes the account diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx index f498ce16001..396cc4e0f26 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/useGetTradeQuotes.tsx @@ -124,10 +124,7 @@ export const useGetTradeQuotes = () => { const isDebouncing = debouncedSellAmountCryptoPrecision !== sellAmountCryptoPrecision const sellAccountId = useAppSelector(selectFirstHopSellAccountId) - // No need to pass a sellAssetAccountId to synchronize the buy account here - by the time this is called, we already have a valid buyAccountId - const buyAccountId = useAppSelector(state => - selectLastHopBuyAccountId(state, { accountId: undefined }), - ) + const buyAccountId = useAppSelector(selectLastHopBuyAccountId) const userslippageTolerancePercentageDecimal = useAppSelector(selectUserSlippagePercentageDecimal) diff --git a/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx b/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx index 45516a2f8e2..4da30b6e32c 100644 --- a/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx +++ b/src/components/MultiHopTrade/hooks/useReceiveAddress.tsx @@ -1,17 +1,12 @@ import { fromAccountId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' -import { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import type { GetReceiveAddressArgs } from 'components/MultiHopTrade/types' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' -import { - selectAccountIdByAccountNumberAndChainId, - selectAccountNumberByAccountId, - selectPortfolioAccountMetadataByAccountId, -} from 'state/slices/portfolioSlice/selectors' +import { selectPortfolioAccountMetadataByAccountId } from 'state/slices/portfolioSlice/selectors' import { isUtxoAccountId } from 'state/slices/portfolioSlice/utils' import { - selectFirstHopSellAccountId, selectInputBuyAsset, selectLastHopBuyAccountId, selectManualReceiveAddress, @@ -43,28 +38,7 @@ export const useReceiveAddress = ({ // Selectors const buyAsset = useAppSelector(selectInputBuyAsset) - const sellAssetAccountId = useAppSelector(selectFirstHopSellAccountId) - const sellAssetAccountNumberFilter = useMemo( - () => ({ accountId: sellAssetAccountId }), - [sellAssetAccountId], - ) - const sellAssetAccountNumber = useAppSelector(state => - selectAccountNumberByAccountId(state, sellAssetAccountNumberFilter), - ) - - const accountIdsByAccountNumberAndChainId = useAppSelector( - selectAccountIdByAccountNumberAndChainId, - ) - - const maybeMatchingBuyAccountId = useMemo(() => { - if (!buyAsset) return - if (sellAssetAccountNumber === undefined) return - return accountIdsByAccountNumberAndChainId[sellAssetAccountNumber]?.[buyAsset.chainId] - }, [accountIdsByAccountNumberAndChainId, sellAssetAccountNumber, buyAsset]) - - const buyAccountId = useAppSelector(state => - selectLastHopBuyAccountId(state, { accountId: maybeMatchingBuyAccountId }), - ) + const buyAccountId = useAppSelector(selectLastHopBuyAccountId) const buyAccountMetadata = useAppSelector(state => selectPortfolioAccountMetadataByAccountId(state, { accountId: buyAccountId }), ) @@ -72,9 +46,15 @@ export const useReceiveAddress = ({ const getReceiveAddressFromBuyAsset = useCallback( async (buyAsset: Asset) => { - if (!wallet) return - if (!buyAccountId) return - if (!buyAccountMetadata) return + if (!wallet) { + return + } + if (!buyAccountId) { + return + } + if (!buyAccountMetadata) { + return + } if (isUtxoAccountId(buyAccountId) && !buyAccountMetadata.accountType) throw new Error(`Missing accountType for UTXO account ${buyAccountId}`) const buyAssetChainId = buyAsset.chainId @@ -83,7 +63,9 @@ export const useReceiveAddress = ({ * do NOT remove * super dangerous - don't use the wrong bip44 params to generate receive addresses */ - if (buyAssetChainId !== buyAssetAccountChainId) return + if (buyAssetChainId !== buyAssetAccountChainId) { + return + } const receiveAddress = await getReceiveAddress({ asset: buyAsset, wallet, diff --git a/src/state/apis/swapper/helpers/validateTradeQuote.ts b/src/state/apis/swapper/helpers/validateTradeQuote.ts index 8ba75e8ebd3..f18004f1b8e 100644 --- a/src/state/apis/swapper/helpers/validateTradeQuote.ts +++ b/src/state/apis/swapper/helpers/validateTradeQuote.ts @@ -254,9 +254,11 @@ export const validateTradeQuote = async ( return false })() - // ensure the trade is not selling an amount higher than the user input - const invalidQuoteSellAmount = - inputSellAmountCryptoBaseUnit !== firstHop.sellAmountIncludingProtocolFeesCryptoBaseUnit + // Ensure the trade is not selling an amount higher than the user input, within a very safe threshold. + // Threshold is required because cowswap sometimes quotes a sell amount a teeny-tiny bit more than you input. + const invalidQuoteSellAmount = bn(inputSellAmountCryptoBaseUnit) + .times('1.0000000000001') + .lt(firstHop.sellAmountIncludingProtocolFeesCryptoBaseUnit) return { errors: [ diff --git a/src/state/slices/tradeInputSlice/selectors.ts b/src/state/slices/tradeInputSlice/selectors.ts index a517033982f..80060a736cb 100644 --- a/src/state/slices/tradeInputSlice/selectors.ts +++ b/src/state/slices/tradeInputSlice/selectors.ts @@ -4,14 +4,17 @@ import { bn } from 'lib/bignumber/bignumber' import { toBaseUnit } from 'lib/math' import type { ReduxState } from 'state/reducer' import { createDeepEqualOutputSelector } from 'state/selector-utils' -import { selectAccountIdParamFromFilter } from 'state/selectors' import { selectPortfolioCryptoBalanceBaseUnitByFilter, selectWalletAccountIds, } from '../common-selectors' import { selectCryptoMarketData, selectUserCurrencyToUsdRate } from '../marketDataSlice/selectors' -import { selectPortfolioAssetAccountBalancesSortedUserCurrency } from '../portfolioSlice/selectors' +import { + selectAccountIdByAccountNumberAndChainId, + selectPortfolioAccountMetadata, + selectPortfolioAssetAccountBalancesSortedUserCurrency, +} from '../portfolioSlice/selectors' import { getFirstAccountIdByChainId, getHighestUserCurrencyBalanceAccountByAssetId, @@ -105,23 +108,40 @@ export const selectLastHopSellAccountId = selectFirstHopSellAccountId export const selectLastHopBuyAccountId = createSelector( selectTradeInput, selectInputBuyAsset, - selectPortfolioAssetAccountBalancesSortedUserCurrency, selectWalletAccountIds, - selectAccountIdParamFromFilter, - (tradeInput, buyAsset, accountIdAssetValues, accountIds, maybeMatchingBuyAccountId) => { + selectAccountIdByAccountNumberAndChainId, + selectFirstHopSellAccountId, + selectPortfolioAccountMetadata, + ( + tradeInput, + buyAsset, + accountIds, + accountIdByAccountNumberAndChainId, + firstHopSellAccountId, + accountMetadata, + ) => { // return the users selection if it exists - if (tradeInput.buyAssetAccountId) return tradeInput.buyAssetAccountId - // an AccountId was found matching the sell asset's account number, return it - if (maybeMatchingBuyAccountId) return maybeMatchingBuyAccountId + if (tradeInput.buyAssetAccountId) { + return tradeInput.buyAssetAccountId + } - const highestFiatBalanceBuyAccountId = getHighestUserCurrencyBalanceAccountByAssetId( - accountIdAssetValues, - buyAsset.assetId, - ) - const firstBuyAssetAccountId = getFirstAccountIdByChainId(accountIds, buyAsset.chainId) + // maybe convert the account id to an account number + const maybeMatchingBuyAccountNumber = firstHopSellAccountId + ? accountMetadata[firstHopSellAccountId]?.bip44Params.accountNumber + : undefined + + // maybe convert account number to account id on the buy asset chain + const maybeMatchingBuyAccountId = maybeMatchingBuyAccountNumber + ? accountIdByAccountNumberAndChainId[maybeMatchingBuyAccountNumber]?.[buyAsset.chainId] + : undefined + + // an AccountId was found matching the sell asset's account number and chainId, return it + if (maybeMatchingBuyAccountId) { + return maybeMatchingBuyAccountId + } // otherwise return a sane default - return highestFiatBalanceBuyAccountId ?? firstBuyAssetAccountId + return getFirstAccountIdByChainId(accountIds, buyAsset.chainId) }, ) From 0882ccb31e127c28728b8e4044285bd541fd5655 Mon Sep 17 00:00:00 2001 From: woody <125113430+woodenfurniture@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:10:59 +1100 Subject: [PATCH 43/60] feat: enable chain selection for assets (#6176) * feat: enable chain selection for assets * chore: move asset selection components into correct directory structure * chore: move asset selection to top-level components directory * chore: move asset menu dropdown button to separate component * chore: move ChainDropdown into separate directory * chore: break out fiat balance responsibility to the consumer of ChainRow * chore: split out ChainDropdown from ChainDropdownBase * Revert "chore: split out ChainDropdown from ChainDropdownBase" This reverts commit 547ccf2ee027beea968dffb74683338d42e46450. * Revert "chore: break out fiat balance responsibility to the consumer of ChainRow" This reverts commit 854ce2cabbeb251e180d55ed345bf73bd26349f6. * feat: asset chain selection with sorting of menu items * chore: make menu items a bit more compact * fix: only render tooltip when dropdown is disabled * chore: actioned code review feedback * fix: filter unsupported assets in asset chain dropdown * fix: use non-placeholder callbacks for asset selection in lending and lp pages * chore: actioned code review feedback --- src/assets/translations/en/main.json | 3 +- .../AssetSelection/AssetSelection.tsx | 96 +++++++++++++++ .../AssetChainDropdown/AssetChainDropdown.tsx | 113 ++++++++++++++++++ .../AssetChainDropdown/AssetChainRow.tsx | 57 +++++++++ .../components/AssetMenuButton.tsx | 54 +++++++++ .../components/AssetRowLoading.tsx | 11 ++ .../ChainDropdown.tsx | 0 .../Chains => ChainDropdown}/ChainRow.tsx | 0 .../components/AssetChainDropdown.tsx | 106 ---------------- .../components/AssetSelection.tsx | 113 ------------------ .../components/TradeInput/TradeInput.tsx | 2 +- src/components/StakingVaults/DeFiEarn.tsx | 2 +- src/pages/Accounts/AddAccountModal.tsx | 2 +- .../Pool/components/Borrow/BorrowInput.tsx | 21 ++-- .../Pool/components/Repay/RepayInput.tsx | 25 ++-- .../AddLiquitity/AddLiquidityInput.tsx | 16 +-- src/state/slices/assetsSlice/selectors.ts | 29 ++++- src/state/slices/portfolioSlice/selectors.ts | 23 +++- 18 files changed, 409 insertions(+), 264 deletions(-) create mode 100644 src/components/AssetSelection/AssetSelection.tsx create mode 100644 src/components/AssetSelection/components/AssetChainDropdown/AssetChainDropdown.tsx create mode 100644 src/components/AssetSelection/components/AssetChainDropdown/AssetChainRow.tsx create mode 100644 src/components/AssetSelection/components/AssetMenuButton.tsx create mode 100644 src/components/AssetSelection/components/AssetRowLoading.tsx rename src/components/{AssetSearch/Chains => ChainDropdown}/ChainDropdown.tsx (100%) rename src/components/{AssetSearch/Chains => ChainDropdown}/ChainRow.tsx (100%) delete mode 100644 src/components/MultiHopTrade/components/AssetChainDropdown.tsx delete mode 100644 src/components/MultiHopTrade/components/AssetSelection.tsx diff --git a/src/assets/translations/en/main.json b/src/assets/translations/en/main.json index 3c9b21585c4..15c5d03e8ff 100644 --- a/src/assets/translations/en/main.json +++ b/src/assets/translations/en/main.json @@ -767,7 +767,8 @@ "amountPercentageDifference": "This is the percentage difference in the total amount of %{buyAssetSymbol} you will receive, compared to the best quote", "overallPercentageDifference": "This is the percentage difference in the overall amount received after all fees are deducted, compared to the best quote", "gasFee": "This is the estimated gas fee to complete this trade.", - "slippage": "If the price moves so that you will receive less than %{amount}, your transaction will be reverted. This is the minimum amount you are guaranteed to receive." + "slippage": "If the price moves so that you will receive less than %{amount}, your transaction will be reverted. This is the minimum amount you are guaranteed to receive.", + "noRelatedAssets": "This asset is only available on %{chainDisplayName}" }, "rates": { "tags": { diff --git a/src/components/AssetSelection/AssetSelection.tsx b/src/components/AssetSelection/AssetSelection.tsx new file mode 100644 index 00000000000..907799eacf6 --- /dev/null +++ b/src/components/AssetSelection/AssetSelection.tsx @@ -0,0 +1,96 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import type { ButtonProps, FlexProps } from '@chakra-ui/react' +import { Flex } from '@chakra-ui/react' +import type { AssetId } from '@shapeshiftoss/caip' +import type { Asset } from '@shapeshiftoss/types' +import { useCallback, useMemo } from 'react' +import { Text } from 'components/Text' +import { selectAssets } from 'state/slices/selectors' +import { useAppSelector } from 'state/store' + +import { AssetChainDropdown } from './components/AssetChainDropdown/AssetChainDropdown' +import { AssetMenuButton } from './components/AssetMenuButton' + +const disabledStyle = { opacity: 0.5 } + +type TradeAssetSelectBaseProps = { + assetId?: AssetId + assetIds?: AssetId[] + isLoading: boolean + buttonProps?: ButtonProps +} & FlexProps + +type TradeAssetSelectReadonlyProps = { + isReadOnly: true + onAssetClick?: undefined + onAssetChange?: undefined +} & TradeAssetSelectBaseProps + +type TradeAssetSelectEditableProps = { + isReadOnly?: false + onAssetClick: () => void + onAssetChange: (asset: Asset) => void +} & TradeAssetSelectBaseProps + +type TradeAssetSelectProps = TradeAssetSelectReadonlyProps | TradeAssetSelectEditableProps + +export const TradeAssetSelect: React.FC = ({ + onAssetClick, + onAssetChange, + assetId, + assetIds, + isReadOnly, + isLoading, + buttonProps, + ...rest +}) => { + const assets = useAppSelector(selectAssets) + + const handleAssetChange = useCallback( + (assetId?: AssetId) => { + if (!assetId) return + const asset = assets[assetId] + if (!asset) return + onAssetChange?.(asset) + }, + [assets, onAssetChange], + ) + + const rightIcon = useMemo(() => (isReadOnly ? undefined : ), [isReadOnly]) + const combinedButtonProps = useMemo(() => { + return Object.assign( + { + height: '40px', + justifyContent: 'flex-end', + px: 2, + py: 2, + gap: 2, + size: 'sm', + borderRadius: 'full', + rightIcon, + _disabled: disabledStyle, + }, + buttonProps, + ) + }, [rightIcon, buttonProps]) + + return ( + + + + + + ) +} diff --git a/src/components/AssetSelection/components/AssetChainDropdown/AssetChainDropdown.tsx b/src/components/AssetSelection/components/AssetChainDropdown/AssetChainDropdown.tsx new file mode 100644 index 00000000000..1926062e43c --- /dev/null +++ b/src/components/AssetSelection/components/AssetChainDropdown/AssetChainDropdown.tsx @@ -0,0 +1,113 @@ +import type { ButtonProps, MenuProps } from '@chakra-ui/react' +import { + Button, + Menu, + MenuButton, + MenuItemOption, + MenuList, + MenuOptionGroup, + Tooltip, +} from '@chakra-ui/react' +import type { AssetId } from '@shapeshiftoss/caip' +import { useCallback, useMemo } from 'react' +import { useTranslate } from 'react-polyglot' +import { useWallet } from 'hooks/useWallet/useWallet' +import { isAssetSupportedByWallet } from 'state/slices/portfolioSlice/utils' +import { + selectChainDisplayNameByAssetId, + selectRelatedAssetIdsInclusiveSorted, +} from 'state/slices/selectors' +import { useAppSelector } from 'state/store' + +import { AssetRowLoading } from '../AssetRowLoading' +import { AssetChainRow } from './AssetChainRow' + +type AssetChainDropdownProps = { + assetId?: AssetId + assetIds?: AssetId[] + onChangeAsset: (arg: AssetId | undefined) => void + buttonProps?: ButtonProps + isLoading?: boolean + isError?: boolean +} & Omit + +export const AssetChainDropdown: React.FC = ({ + assetId, + assetIds, + onChangeAsset, + buttonProps, + isLoading, + isError, + ...menuProps +}) => { + const { + state: { wallet }, + } = useWallet() + const translate = useTranslate() + const chainDisplayName = useAppSelector(state => + selectChainDisplayNameByAssetId(state, assetId ?? ''), + ) + const relatedAssetIds = useAppSelector(state => + selectRelatedAssetIdsInclusiveSorted(state, assetId ?? ''), + ) + + const filteredRelatedAssetIds = useMemo(() => { + if (!assetIds?.length) return relatedAssetIds + return relatedAssetIds.filter(relatedAssetId => assetIds.includes(relatedAssetId)) + }, [assetIds, relatedAssetIds]) + + const renderChains = useMemo(() => { + return filteredRelatedAssetIds.map(assetId => { + const isSupported = wallet && isAssetSupportedByWallet(assetId, wallet) + + return ( + + + + ) + }) + }, [filteredRelatedAssetIds, wallet]) + + const handleChangeAsset = useCallback( + (value: string | string[]) => { + // this should never happen, but in case it does... + if (typeof value !== 'string') { + console.error('expected string value') + return + } + onChangeAsset(value as AssetId) + }, + [onChangeAsset], + ) + + const isDisabled = useMemo(() => { + return filteredRelatedAssetIds.length <= 1 || isLoading || isError + }, [filteredRelatedAssetIds, isError, isLoading]) + + const isTooltipDisabled = useMemo(() => { + // only render the tooltip when there are no other related assets and we're not loading and not + // errored + return filteredRelatedAssetIds.length > 1 || isLoading || isError + }, [filteredRelatedAssetIds, isError, isLoading]) + + const buttonTooltipText = useMemo(() => { + return translate('trade.tooltip.noRelatedAssets', { chainDisplayName }) + }, [chainDisplayName, translate]) + + if (!assetId || isLoading) return + + return ( + + + + + + + + + {renderChains} + + + + ) +} diff --git a/src/components/AssetSelection/components/AssetChainDropdown/AssetChainRow.tsx b/src/components/AssetSelection/components/AssetChainDropdown/AssetChainRow.tsx new file mode 100644 index 00000000000..683c1fa9614 --- /dev/null +++ b/src/components/AssetSelection/components/AssetChainDropdown/AssetChainRow.tsx @@ -0,0 +1,57 @@ +import { Flex } from '@chakra-ui/react' +import type { AssetId } from '@shapeshiftoss/caip' +import { useMemo } from 'react' +import { Amount } from 'components/Amount/Amount' +import { LazyLoadAvatar } from 'components/LazyLoadAvatar' +import { bnOrZero } from 'lib/bignumber/bignumber' +import { firstNonZeroDecimal } from 'lib/math' +import { + selectAssetById, + selectFeeAssetById, + selectPortfolioCryptoPrecisionBalanceByFilter, + selectPortfolioUserCurrencyBalanceByAssetId, +} from 'state/slices/selectors' +import { useAppSelector } from 'state/store' + +type AssetChainRowProps = { + assetId: AssetId + hideBalances?: boolean +} +export const AssetChainRow: React.FC = ({ assetId, hideBalances }) => { + const asset = useAppSelector(state => selectAssetById(state, assetId)) + const feeAsset = useAppSelector(state => selectFeeAssetById(state, assetId)) + const iconSrc = feeAsset?.networkIcon ?? feeAsset?.icon + const filter = useMemo(() => ({ assetId }), [assetId]) + const cryptoHumanBalance = useAppSelector(s => + selectPortfolioCryptoPrecisionBalanceByFilter(s, filter), + ) + + const userCurrencyBalance = useAppSelector( + state => selectPortfolioUserCurrencyBalanceByAssetId(state, filter) ?? '0', + ) + + const hideAssetBalance = hideBalances || bnOrZero(cryptoHumanBalance).isZero() + + if (!feeAsset) return null + + return ( + + + + {feeAsset.networkName ?? feeAsset.name} + + {!hideAssetBalance && ( + + + + + )} + + ) +} diff --git a/src/components/AssetSelection/components/AssetMenuButton.tsx b/src/components/AssetSelection/components/AssetMenuButton.tsx new file mode 100644 index 00000000000..7744ee77997 --- /dev/null +++ b/src/components/AssetSelection/components/AssetMenuButton.tsx @@ -0,0 +1,54 @@ +import type { ButtonProps } from '@chakra-ui/react' +import { Button, Flex } from '@chakra-ui/react' +import type { AssetId } from '@shapeshiftoss/caip' +import { PairIcons } from 'features/defi/components/PairIcons/PairIcons' +import { useMemo } from 'react' +import { AssetIcon } from 'components/AssetIcon' +import { selectAssetById } from 'state/slices/selectors' +import { useAppSelector } from 'state/store' + +import { AssetRowLoading } from './AssetRowLoading' + +export type AssetMenuButtonProps = { + assetId?: AssetId + onAssetClick?: () => void + isDisabled: boolean + buttonProps?: ButtonProps + isLoading?: boolean +} + +export const AssetMenuButton = ({ + assetId, + onAssetClick, + isDisabled, + buttonProps, + isLoading, +}: AssetMenuButtonProps) => { + const asset = useAppSelector(state => selectAssetById(state, assetId ?? '')) + + const icon = useMemo(() => { + return asset?.icons ? ( + + ) : ( + + ) + }, [asset?.icons, assetId]) + + if (!assetId || isLoading) return + + return ( + + ) +} diff --git a/src/components/AssetSelection/components/AssetRowLoading.tsx b/src/components/AssetSelection/components/AssetRowLoading.tsx new file mode 100644 index 00000000000..2e57207dab9 --- /dev/null +++ b/src/components/AssetSelection/components/AssetRowLoading.tsx @@ -0,0 +1,11 @@ +import type { ButtonProps } from '@chakra-ui/react' +import { Button, Skeleton, SkeletonCircle } from '@chakra-ui/react' + +export const AssetRowLoading: React.FC = props => { + return ( + + ) +} diff --git a/src/components/AssetSearch/Chains/ChainDropdown.tsx b/src/components/ChainDropdown/ChainDropdown.tsx similarity index 100% rename from src/components/AssetSearch/Chains/ChainDropdown.tsx rename to src/components/ChainDropdown/ChainDropdown.tsx diff --git a/src/components/AssetSearch/Chains/ChainRow.tsx b/src/components/ChainDropdown/ChainRow.tsx similarity index 100% rename from src/components/AssetSearch/Chains/ChainRow.tsx rename to src/components/ChainDropdown/ChainRow.tsx diff --git a/src/components/MultiHopTrade/components/AssetChainDropdown.tsx b/src/components/MultiHopTrade/components/AssetChainDropdown.tsx deleted file mode 100644 index 091beb5a918..00000000000 --- a/src/components/MultiHopTrade/components/AssetChainDropdown.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import type { ButtonProps, FlexProps, MenuProps } from '@chakra-ui/react' -import { Button, Flex, Menu, MenuButton } from '@chakra-ui/react' -import type { AssetId } from '@shapeshiftoss/caip' -import React, { memo } from 'react' -import { AssetIcon } from 'components/AssetIcon' -import { AutoTruncateText } from 'components/AutoTruncateText' -import { selectFeeAssetById } from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -const disabled = { opacity: 1 } -const hover = { color: 'text.base' } - -export type ChainDropdownProps = { - assetId?: AssetId - onClick: (arg: AssetId) => void - showAll?: boolean - includeBalance?: boolean - buttonProps?: ButtonProps - isLoading?: boolean - isError?: boolean -} & Omit - -const AssetChainRow: React.FC<{ assetId: AssetId } & FlexProps> = memo(({ assetId, ...rest }) => { - const feeAsset = useAppSelector(state => selectFeeAssetById(state, assetId)) - const iconSrc = feeAsset?.networkIcon ?? feeAsset?.icon - return ( - - - - - ) -}) - -export const AssetChainDropdown: React.FC = ({ - assetId, - onClick, - showAll, - includeBalance, - buttonProps, - isLoading, - isError, - ...menuProps -}) => { - // const totalPortfolioUserCurrencyBalance = useAppSelector( - // selectPortfolioTotalUserCurrencyBalanceExcludeEarnDupes, - // ) - // const translate = useTranslate() - - // const renderChains = useMemo(() => { - // return assetIds?.map(assetId => ( - // - // - // - // )) - // }, [assetIds]) - - // const onChange = useCallback((value: string | string[]) => onClick(value as AssetId), [onClick]) - - // @TODO: figure out how to do this correctly using coingeck data - // const isDisabled = useMemo(() => { - // return !assetIds?.length || isLoading || isError - // }, [assetIds?.length, isError, isLoading]) - - if (!assetId) return null - - return ( - - - - - {/* - - {showAll && ( - - - - - - {translate('common.allChains')} - - - - )} - {renderChains} - - */} - - ) -} diff --git a/src/components/MultiHopTrade/components/AssetSelection.tsx b/src/components/MultiHopTrade/components/AssetSelection.tsx deleted file mode 100644 index d2c0722bc47..00000000000 --- a/src/components/MultiHopTrade/components/AssetSelection.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { ChevronDownIcon } from '@chakra-ui/icons' -import type { ButtonProps, FlexProps } from '@chakra-ui/react' -import { Button, Flex, Skeleton, SkeletonCircle, Stack, useColorModeValue } from '@chakra-ui/react' -import type { AssetId } from '@shapeshiftoss/caip' -import type { Asset } from '@shapeshiftoss/types' -import { PairIcons } from 'features/defi/components/PairIcons/PairIcons' -import { memo, useCallback, useMemo } from 'react' -import { AssetIcon } from 'components/AssetIcon' -import { Text } from 'components/Text' -import { selectAssetById, selectAssets } from 'state/slices/selectors' -import { useAppSelector } from 'state/store' - -import { AssetChainDropdown } from './AssetChainDropdown' - -const disabledStyle = { opacity: 1 } - -const TradeAssetAwaitingAsset = () => { - const bgColor = useColorModeValue('white', 'gray.850') - return ( - - - - - - - - - ) -} - -type TradeAssetSelectProps = { - assetId?: AssetId - isReadOnly?: boolean - isLoading: boolean - onAssetClick?: () => void - onAssetChange: (asset: Asset) => void - buttonProps?: ButtonProps -} & FlexProps - -export const TradeAssetSelectWithAsset: React.FC = ({ - onAssetClick, - onAssetChange, - assetId, - isReadOnly, - isLoading, - buttonProps, - ...rest -}) => { - const assets = useAppSelector(selectAssets) - const asset = useAppSelector(state => selectAssetById(state, assetId ?? '')) - - const handleAssetChange = useCallback( - (assetId: AssetId) => { - const asset = assets[assetId] - if (!asset) return - onAssetChange(asset) - }, - [assets, onAssetChange], - ) - const icon = useMemo(() => { - return asset?.icons ? ( - - ) : ( - - ) - }, [asset?.icons, assetId]) - - const rightIcon = useMemo(() => (isReadOnly ? undefined : ), [isReadOnly]) - - return ( - - - - - - ) -} - -export const TradeAssetSelect: React.FC = memo( - ({ assetId, ...restAssetInputProps }) => { - return assetId ? ( - - ) : ( - - ) - }, -) diff --git a/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx b/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx index 87698f0d09d..12b742544e8 100644 --- a/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx +++ b/src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx @@ -20,8 +20,8 @@ import { memo, useCallback, useEffect, useMemo, useState } from 'react' import { useFormContext } from 'react-hook-form' import { useTranslate } from 'react-polyglot' import { useHistory } from 'react-router' +import { TradeAssetSelect } from 'components/AssetSelection/AssetSelection' import { MessageOverlay } from 'components/MessageOverlay/MessageOverlay' -import { TradeAssetSelect } from 'components/MultiHopTrade/components/AssetSelection' import { RateGasRow } from 'components/MultiHopTrade/components/RateGasRow' import { SlippagePopover } from 'components/MultiHopTrade/components/SlippagePopover' import { TradeAssetInput } from 'components/MultiHopTrade/components/TradeAssetInput' diff --git a/src/components/StakingVaults/DeFiEarn.tsx b/src/components/StakingVaults/DeFiEarn.tsx index 1cf16adad8e..3361a9ad088 100644 --- a/src/components/StakingVaults/DeFiEarn.tsx +++ b/src/components/StakingVaults/DeFiEarn.tsx @@ -4,7 +4,7 @@ import type { ChainId } from '@shapeshiftoss/caip' import type { Property } from 'csstype' import { useState } from 'react' import { useTranslate } from 'react-polyglot' -import { ChainDropdown } from 'components/AssetSearch/Chains/ChainDropdown' +import { ChainDropdown } from 'components/ChainDropdown/ChainDropdown' import { useQuery } from 'hooks/useQuery/useQuery' import { selectPortfolioChainIdsSortedUserCurrency } from 'state/slices/selectors' import { useAppSelector } from 'state/store' diff --git a/src/pages/Accounts/AddAccountModal.tsx b/src/pages/Accounts/AddAccountModal.tsx index 8f65160595d..c745e7ab13a 100644 --- a/src/pages/Accounts/AddAccountModal.tsx +++ b/src/pages/Accounts/AddAccountModal.tsx @@ -19,7 +19,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { FaInfoCircle } from 'react-icons/fa' import { useTranslate } from 'react-polyglot' import { useSelector } from 'react-redux' -import { ChainDropdown } from 'components/AssetSearch/Chains/ChainDropdown' +import { ChainDropdown } from 'components/ChainDropdown/ChainDropdown' import { RawText } from 'components/Text' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useModal } from 'hooks/useModal/useModal' diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx index f53c97be82a..29cc3c74d99 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowInput.tsx @@ -11,15 +11,14 @@ import { } from '@chakra-ui/react' import { type AccountId, type AssetId, fromAccountId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' -import noop from 'lodash/noop' import prettyMilliseconds from 'pretty-ms' import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' import { Amount } from 'components/Amount/Amount' +import { TradeAssetSelect } from 'components/AssetSelection/AssetSelection' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' -import { TradeAssetSelect } from 'components/MultiHopTrade/components/AssetSelection' import { TradeAssetInput } from 'components/MultiHopTrade/components/TradeAssetInput' import { Row } from 'components/Row/Row' import { SlideTransition } from 'components/SlideTransition' @@ -102,6 +101,10 @@ export const BorrowInput = ({ const { data: borrowAssets, isLoading: isLendingSupportedAssetsLoading } = useLendingSupportedAssets({ type: 'borrow' }) + const borrowAssetIds = useMemo(() => { + return borrowAssets?.map(borrowAsset => borrowAsset.assetId) ?? [] + }, [borrowAssets]) + const collateralAsset = useAppSelector(state => selectAssetById(state, collateralAssetId)) useEffect(() => { @@ -122,10 +125,6 @@ export const BorrowInput = ({ }) }, [borrowAssets, buyAssetSearch, setBorrowAsset]) - const handleAssetChange = useCallback((asset: Asset) => { - return console.info(asset) - }, []) - const handleDepositInputChange = useCallback( (value: string, isFiat?: boolean) => { onDepositAmountChange(value, isFiat) @@ -391,26 +390,26 @@ export const BorrowInput = ({ return ( ) - }, [collateralAssetId, handleAssetChange, isLendingSupportedAssetsLoading]) + }, [collateralAssetId, isLendingSupportedAssetsLoading]) const borrowAssetSelectComponent = useMemo(() => { return ( ) }, [ borrowAsset?.assetId, - handleAssetChange, + borrowAssetIds, + setBorrowAsset, handleBorrowAssetClick, isLendingSupportedAssetsLoading, ]) diff --git a/src/pages/Lending/Pool/components/Repay/RepayInput.tsx b/src/pages/Lending/Pool/components/Repay/RepayInput.tsx index c3aa421361a..46d8441cb34 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayInput.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayInput.tsx @@ -22,8 +22,8 @@ import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' import { Amount } from 'components/Amount/Amount' +import { TradeAssetSelect } from 'components/AssetSelection/AssetSelection' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' -import { TradeAssetSelect } from 'components/MultiHopTrade/components/AssetSelection' import { TradeAssetInput } from 'components/MultiHopTrade/components/TradeAssetInput' import { Row } from 'components/Row/Row' import { RawText, Text } from 'components/Text' @@ -189,6 +189,10 @@ export const RepayInput = ({ const { data: lendingSupportedAssets, isLoading: isLendingSupportedAssetsLoading } = useLendingSupportedAssets({ type: 'borrow' }) + const lendingSupportedAssetIds = useMemo(() => { + return lendingSupportedAssets?.map(lendingSupportedAsset => lendingSupportedAsset.assetId) ?? [] + }, [lendingSupportedAssets]) + useEffect(() => { if (!(lendingSupportedAssets && collateralAsset)) return if (repaymentAsset) return @@ -207,16 +211,13 @@ export const RepayInput = ({ }) }, [buyAssetSearch, lendingSupportedAssets, setRepaymentAsset]) - const handleAssetChange = useCallback((asset: Asset) => { - return console.info(asset) - }, []) - const repaymentAssetSelectComponent = useMemo(() => { return ( ) }, [ - handleAssetChange, + setRepaymentAsset, handleRepaymentAssetClick, isLendingSupportedAssetsLoading, + lendingSupportedAssetIds, repaymentAsset?.assetId, ]) @@ -234,18 +236,11 @@ export const RepayInput = ({ return ( ) - }, [ - collateralAssetId, - handleAssetChange, - handleRepaymentAssetClick, - isLendingSupportedAssetsLoading, - ]) + }, [collateralAssetId, isLendingSupportedAssetsLoading]) const handleSeenNotice = useCallback(() => setSeenNotice(true), []) diff --git a/src/pages/ThorChainLP/components/AddLiquitity/AddLiquidityInput.tsx b/src/pages/ThorChainLP/components/AddLiquitity/AddLiquidityInput.tsx index df65442b763..3b913c8fefb 100644 --- a/src/pages/ThorChainLP/components/AddLiquitity/AddLiquidityInput.tsx +++ b/src/pages/ThorChainLP/components/AddLiquitity/AddLiquidityInput.tsx @@ -33,7 +33,7 @@ import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimate import { selectInboundAddressData } from 'react-queries/selectors' import { useHistory } from 'react-router' import { Amount } from 'components/Amount/Amount' -import { TradeAssetSelect } from 'components/MultiHopTrade/components/AssetSelection' +import { TradeAssetSelect } from 'components/AssetSelection/AssetSelection' import { SlippagePopover } from 'components/MultiHopTrade/components/SlippagePopover' import { TradeAssetInput } from 'components/MultiHopTrade/components/TradeAssetInput' import { Row } from 'components/Row/Row' @@ -136,6 +136,10 @@ export const AddLiquidityInput: React.FC = ({ return [...new Set(parsedPools.map(pool => assets[pool.assetId]).filter(isSome))] }, [assets, parsedPools]) + const poolAssetIds = useMemo(() => { + return poolAssets.map(poolAsset => poolAsset.assetId) + }, [poolAssets]) + // TODO(gomes): Even though that's an edge case for users, and a bad practice, handling sym and asymm positions simultaneously // *is* possible and *is* something that both we and TS do. We can do one better than TS here however: // - When a user deposits symetrically, they can then deposit asymetrically, but only on the asset side @@ -257,10 +261,6 @@ export const AddLiquidityInput: React.FC = ({ setActiveOpportunityId(foundOpportunityId) }, [poolAsset, defaultOpportunityId, parsedPools, walletSupportsAsset, walletSupportsRune]) - const handleAssetChange = useCallback((asset: Asset) => { - console.info(asset) - }, []) - const handleBackClick = useCallback(() => { browserHistory.push('/pools') }, [browserHistory]) @@ -1058,15 +1058,15 @@ export const AddLiquidityInput: React.FC = ({ = ({ /> ) - }, [poolAsset?.assetId, defaultOpportunityId, handleAssetChange, handlePoolAssetClick, translate]) + }, [defaultOpportunityId, translate, poolAsset?.assetId, poolAssetIds, handlePoolAssetClick]) const handleAsymSideChange = useCallback( (asymSide: string | null) => { diff --git a/src/state/slices/assetsSlice/selectors.ts b/src/state/slices/assetsSlice/selectors.ts index 12bcdf789bd..d4804d60c38 100644 --- a/src/state/slices/assetsSlice/selectors.ts +++ b/src/state/slices/assetsSlice/selectors.ts @@ -4,6 +4,7 @@ import { fromAssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import { matchSorter } from 'match-sorter' import createCachedSelector from 're-reselect' +import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import type { ReduxState } from 'state/reducer' import { createDeepEqualOutputSelector } from 'state/selector-utils' import { selectAssetIdParamFromFilter, selectSearchQueryFromFilter } from 'state/selectors' @@ -18,15 +19,24 @@ export const selectAssetById = createCachedSelector( (byId, assetId) => byId[assetId] || undefined, )((_state: ReduxState, assetId: AssetId | undefined): AssetId => assetId ?? 'undefined') -export const selectRelatedAssetIds = createSelector( +// selects all related assetIds, inclusive of the asset being queried +export const selectRelatedAssetIdsInclusive = createDeepEqualOutputSelector( (state: ReduxState) => state.assets.relatedAssetIndex, selectAssetById, (relatedAssetIndex, asset): AssetId[] => { - const relatedAssetKey = asset?.relatedAssetKey - if (!relatedAssetKey) return [] - return [relatedAssetKey] - .concat(relatedAssetIndex[relatedAssetKey] ?? []) - .filter(assetId => assetId !== asset.assetId) + if (!asset) return [] + const relatedAssetKey = asset.relatedAssetKey + if (!relatedAssetKey) return [asset.assetId] + return [relatedAssetKey].concat(relatedAssetIndex[relatedAssetKey] ?? []) + }, +) + +// selects all related assetIds, exclusive of the asset being queried +export const selectRelatedAssetIds = createDeepEqualOutputSelector( + selectRelatedAssetIdsInclusive, + selectAssetById, + (relatedAssetIdsInclusive, asset): AssetId[] => { + return relatedAssetIdsInclusive.filter(assetId => assetId !== asset?.assetId) ?? [] }, ) @@ -41,11 +51,18 @@ export const selectAssetNameById = createSelector( (asset): string => asset?.name ?? '', ) +export const selectChainDisplayNameByAssetId = createSelector(selectAssetById, (asset): string => { + if (!asset) return '' + const chainAdapterManager = getChainAdapterManager() + return chainAdapterManager.get(asset.chainId)?.getDisplayName() ?? '' +}) + export const selectAssets = createDeepEqualOutputSelector( (state: ReduxState) => state.assets.byId, byId => byId, ) export const selectAssetIds = (state: ReduxState) => state.assets.ids +export const selectRelatedAssetIndex = (state: ReduxState) => state.assets.relatedAssetIndex export const selectAssetsByMarketCap = createDeepEqualOutputSelector( selectCryptoMarketDataIds, diff --git a/src/state/slices/portfolioSlice/selectors.ts b/src/state/slices/portfolioSlice/selectors.ts index 05b363933ac..e1ad7696a9f 100644 --- a/src/state/slices/portfolioSlice/selectors.ts +++ b/src/state/slices/portfolioSlice/selectors.ts @@ -7,6 +7,7 @@ import type { BIP44Params, PartialRecord, } from '@shapeshiftoss/types' +import { orderBy } from 'lodash' import cloneDeep from 'lodash/cloneDeep' import entries from 'lodash/entries' import keys from 'lodash/keys' @@ -31,7 +32,7 @@ import { selectAssetIdParamFromFilter, selectChainIdParamFromFilter, } from 'state/selectors' -import { selectAssets } from 'state/slices/assetsSlice/selectors' +import { selectAssets, selectRelatedAssetIdsInclusive } from 'state/slices/assetsSlice/selectors' import { selectSelectedCurrencyMarketDataSortedByMarketCap } from 'state/slices/marketDataSlice/selectors' import { selectAllEarnUserLpOpportunitiesByFilter } from 'state/slices/opportunitiesSlice/selectors/lpSelectors' import { @@ -972,3 +973,23 @@ export const selectEquityTotalBalance = createDeepEqualOutputSelector( ) }, ) + +export const selectRelatedAssetIdsInclusiveSorted = createDeepEqualOutputSelector( + selectRelatedAssetIdsInclusive, + selectPortfolioUserCurrencyBalances, + (relatedAssetIds, portfolioUserCurrencyBalances) => { + const chainAdapterManager = getChainAdapterManager() + return orderBy( + relatedAssetIds.map(assetId => { + const { chainId } = fromAssetId(assetId) + return { + assetId, + balance: Number(portfolioUserCurrencyBalances[assetId] ?? '0'), + chainName: chainAdapterManager.get(chainId)?.getDisplayName() ?? '', + } + }), + ['balance', 'chainName'], + ['desc', 'asc'], + ).map(({ assetId }) => assetId) + }, +) From 5e87fd189e0a13b30847c880b9dc68798511af78 Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Thu, 22 Feb 2024 17:09:52 +1100 Subject: [PATCH 44/60] chore: add 'remove liquidity' fees (#6175) * wip: remove liquidity fees * chore: use route account & AssetInput w/balances * chore: use actual lp amounts * chore: rune fees working * chore: post merge fix * fix: add keys to AssetInput * fix: asym asset side amount population * chore: remove commented code * chore: address review feedback * chore: improve comments * chore: fix grammar * chore: fix grammar in existing files * chore: remove explicit state for userLpData * fix: max sell amount doubled --- src/lib/utils/thorchain/lp.ts | 4 +- src/lib/utils/thorchain/lp/types.ts | 18 + src/pages/ThorChainLP/Pool/Pool.tsx | 4 +- src/pages/ThorChainLP/Position/Position.tsx | 17 +- .../RemoveLiquidity/RemoveLiquidity.tsx | 43 +- .../RemoveLiquidity/RemoveLiquidityInput.tsx | 411 +++++++++++++----- .../hooks/useQuoteEstimatedFeesQuery.ts | 24 +- 7 files changed, 398 insertions(+), 123 deletions(-) diff --git a/src/lib/utils/thorchain/lp.ts b/src/lib/utils/thorchain/lp.ts index 77f7bdc09ba..cca23b03d4b 100644 --- a/src/lib/utils/thorchain/lp.ts +++ b/src/lib/utils/thorchain/lp.ts @@ -45,7 +45,7 @@ export const calculateTVL = ( assetDepthCryptoBaseUnit: string, runeDepthCryptoBaseUnit: string, runePrice: string, -): { tvl: string; assetAmountCrytoPrecision: string; runeAmountCryptoPrecision: string } => { +): { tvl: string; assetAmountCryptoPrecision: string; runeAmountCryptoPrecision: string } => { const assetDepthCryptoPrecision = fromThorBaseUnit(assetDepthCryptoBaseUnit) const runeDepthCryptoPrecision = fromThorBaseUnit(runeDepthCryptoBaseUnit) @@ -56,7 +56,7 @@ export const calculateTVL = ( const result = { tvl: tvl.toFixed(), - assetAmountCrytoPrecision: assetDepthCryptoPrecision.toFixed(), + assetAmountCryptoPrecision: assetDepthCryptoPrecision.toFixed(), runeAmountCryptoPrecision: runeDepthCryptoPrecision.toFixed(), } diff --git a/src/lib/utils/thorchain/lp/types.ts b/src/lib/utils/thorchain/lp/types.ts index 7642e9c2d08..c892d9a2fb5 100644 --- a/src/lib/utils/thorchain/lp/types.ts +++ b/src/lib/utils/thorchain/lp/types.ts @@ -205,6 +205,24 @@ export type LpConfirmedDepositQuote = { runeGasFeeFiat: string poolAssetGasFeeFiat: string } + +export type LpConfirmedWithdrawalQuote = { + totalAmountFiat: string + assetCryptoLiquidityAmount: string + assetFiatLiquidityAmount: string + runeCryptoLiquidityAmount: string + runeFiatLiquidityAmount: string + shareOfPoolDecimalPercent: string + slippageRune: string + opportunityId: string + assetAddress?: string + quoteInboundAddress: string + // For informative purposes only at confirm step - to be recalculated before signing + totalGasFeeFiat: string + runeGasFeeFiat: string + poolAssetGasFeeFiat: string +} + export enum AsymSide { Asset = 'asset', Rune = 'rune', diff --git a/src/pages/ThorChainLP/Pool/Pool.tsx b/src/pages/ThorChainLP/Pool/Pool.tsx index d6f4b4c45e6..3585d6fc067 100644 --- a/src/pages/ThorChainLP/Pool/Pool.tsx +++ b/src/pages/ThorChainLP/Pool/Pool.tsx @@ -187,7 +187,7 @@ export const Pool = () => { const tvl = useMemo(() => { if (!foundPool) - return { tvl: '0', assetAmountCrytoPrecision: '0', runeAmountCryptoPrecision: '0' } + return { tvl: '0', assetAmountCryptoPrecision: '0', runeAmountCryptoPrecision: '0' } return calculateTVL(foundPool.assetDepth, foundPool.runeDepth, runeMarketData.price) }, [foundPool, runeMarketData.price]) @@ -244,7 +244,7 @@ export const Pool = () => { apy={foundPool.poolAPY} tvl={tvl.tvl} runeTvl={tvl.runeAmountCryptoPrecision} - assetTvl={tvl.assetAmountCrytoPrecision} + assetTvl={tvl.assetAmountCryptoPrecision} tvl24hChange={tvl24hChange ?? 0} assetIds={poolAssetIds} direction='column' diff --git a/src/pages/ThorChainLP/Position/Position.tsx b/src/pages/ThorChainLP/Position/Position.tsx index 84211013c0d..9be65c1ffca 100644 --- a/src/pages/ThorChainLP/Position/Position.tsx +++ b/src/pages/ThorChainLP/Position/Position.tsx @@ -260,7 +260,7 @@ export const Position = () => { const tvl = useMemo(() => { if (!foundPool) - return { tvl: '0', assetAmountCrytoPrecision: '0', runeAmountCryptoPrecision: '0' } + return { tvl: '0', assetAmountCryptoPrecision: '0', runeAmountCryptoPrecision: '0' } return calculateTVL(foundPool.assetDepth, foundPool.runeDepth, runeMarketData.price) }, [foundPool, runeMarketData.price]) @@ -406,12 +406,15 @@ export const Position = () => { opportunityId={foundPool.opportunityId} /> - - - + {params.poolAccountId && ( + + + + )} diff --git a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx index 964ff63029b..690d8743dc2 100644 --- a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx +++ b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx @@ -1,6 +1,8 @@ +import type { AccountId } from '@shapeshiftoss/caip' import { AnimatePresence } from 'framer-motion' -import React, { Suspense, useCallback } from 'react' +import React, { Suspense, useCallback, useState } from 'react' import { MemoryRouter, Route, Switch, useLocation } from 'react-router' +import type { LpConfirmedWithdrawalQuote } from 'lib/utils/thorchain/lp/types' import { RemoveLiquidityConfirm } from './RemoveLiquidityConfirm' import { RemoveLiquidityInput } from './RemoveLiquidityInput' @@ -16,28 +18,55 @@ const AddLiquidityEntries = [ ] export type RemoveLiquidityProps = { - headerComponent?: JSX.Element - opportunityId?: string + headerComponent: JSX.Element + opportunityId: string + poolAccountId: AccountId } + +export type RemoveLiquidityRoutesProps = RemoveLiquidityProps & { + confirmedQuote: LpConfirmedWithdrawalQuote | null + setConfirmedQuote: (quote: LpConfirmedWithdrawalQuote) => void +} + export const RemoveLiquidity: React.FC = ({ headerComponent, opportunityId, + poolAccountId, }) => { + const [confirmedQuote, setConfirmedQuote] = useState(null) + return ( - + ) } -const RemoveLiquidityRoutes: React.FC = ({ +const RemoveLiquidityRoutes: React.FC = ({ headerComponent, opportunityId, + confirmedQuote, + setConfirmedQuote, + poolAccountId, }) => { const location = useLocation() const renderRemoveLiquidityInput = useCallback( - () => , - [headerComponent, opportunityId], + () => ( + + ), + [confirmedQuote, headerComponent, opportunityId, poolAccountId, setConfirmedQuote], ) const renderRemoveLiquidityConfirm = useCallback(() => , []) const renderRemoveLiquidityStatus = useCallback(() => , []) diff --git a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityInput.tsx b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityInput.tsx index 63b9e6b53f2..30e18c0199d 100644 --- a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityInput.tsx +++ b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityInput.tsx @@ -17,30 +17,38 @@ import { Stack, StackDivider, } from '@chakra-ui/react' -import { thorchainAssetId } from '@shapeshiftoss/caip' +import type { AccountId } from '@shapeshiftoss/caip' +import { thorchainAssetId, thorchainChainId, toAccountId } from '@shapeshiftoss/caip' import type { Asset, MarketData } from '@shapeshiftoss/types' +import { useQuery } from '@tanstack/react-query' import React, { useCallback, useEffect, useMemo, useState } from 'react' import { FaPlus } from 'react-icons/fa6' import { useTranslate } from 'react-polyglot' +import { reactQueries } from 'react-queries' +import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' +import { selectInboundAddressData } from 'react-queries/selectors' import { useHistory } from 'react-router' import { Amount } from 'components/Amount/Amount' +import { AssetInput } from 'components/DeFi/components/AssetInput' import { SlippagePopover } from 'components/MultiHopTrade/components/SlippagePopover' -import { TradeAssetInput } from 'components/MultiHopTrade/components/TradeAssetInput' import { Row } from 'components/Row/Row' import { SlideTransition } from 'components/SlideTransition' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' import { bn, bnOrZero, convertPrecision } from 'lib/bignumber/bignumber' -import { THOR_PRECISION } from 'lib/utils/thorchain/constants' -import { estimateRemoveThorchainLiquidityPosition } from 'lib/utils/thorchain/lp' -import type { UserLpDataPosition } from 'lib/utils/thorchain/lp/types' +import { fromBaseUnit } from 'lib/math' +import { assertUnreachable } from 'lib/utils' +import { THOR_PRECISION, THORCHAIN_POOL_MODULE_ADDRESS } from 'lib/utils/thorchain/constants' +import { + estimateRemoveThorchainLiquidityPosition, + getThorchainLpTransactionType, +} from 'lib/utils/thorchain/lp' +import type { LpConfirmedWithdrawalQuote, UserLpDataPosition } from 'lib/utils/thorchain/lp/types' import { AsymSide } from 'lib/utils/thorchain/lp/types' import { usePools } from 'pages/ThorChainLP/queries/hooks/usePools' import { useUserLpData } from 'pages/ThorChainLP/queries/hooks/useUserLpData' -import { selectAssetById, selectMarketDataById } from 'state/slices/selectors' +import { selectAssetById, selectFeeAssetById, selectMarketDataById } from 'state/slices/selectors' import { useAppSelector } from 'state/store' -import { ReadOnlyAsset } from '../ReadOnlyAsset' -import type { RemoveLiquidityProps } from './RemoveLiquidity' import { RemoveLiquidityRoutePaths } from './types' const formControlProps = { @@ -56,9 +64,20 @@ const dividerStyle = { marginTop: 12, } -export const RemoveLiquidityInput: React.FC = ({ +export type RemoveLiquidityInputProps = { + headerComponent: JSX.Element + opportunityId: string + poolAccountId: AccountId + setConfirmedQuote: (quote: LpConfirmedWithdrawalQuote) => void + confirmedQuote: LpConfirmedWithdrawalQuote | null +} + +export const RemoveLiquidityInput: React.FC = ({ headerComponent, opportunityId, + confirmedQuote, + setConfirmedQuote, + poolAccountId, }) => { const translate = useTranslate() const { history: browserHistory } = useBrowserRouter() @@ -87,28 +106,127 @@ export const RemoveLiquidityInput: React.FC = ({ }, [foundPoolAsset]) const rune = useAppSelector(state => selectAssetById(state, thorchainAssetId)) + const runeAsset = useAppSelector(state => selectAssetById(state, thorchainAssetId)) const [poolAsset, setPoolAsset] = useState(foundPoolAsset) const [userlpData, setUserlpData] = useState() + const [runeAccountId, setRuneAccountId] = useState() const [percentageSelection, setPercentageSelection] = useState(50) + const [shareOfPoolDecimalPercent, setShareOfPoolDecimalPercent] = useState() + + // Virtual as in, these are the amounts if removing symetrically. But a user may remove asymetrically, so these are not the *actual* amounts + // Keeping these as virtual amounts is useful from a UI perspective, as it allows rebalancing to automagically work when switching from sym. type, + // while using the *actual* amounts whenever we do things like checking for asset balance + const [virtualAssetCryptoLiquidityAmount, setVirtualAssetCryptoLiquidityAmount] = useState< + string | undefined + >() + const [virtualAssetFiatLiquidityAmount, setVirtualAssetFiatLiquidityAmount] = useState< + string | undefined + >() + const [virtualRuneCryptoLiquidityAmount, setVirtualRuneCryptoLiquidityAmount] = useState< + string | undefined + >() + const [virtualRuneFiatLiquidityAmount, setVirtualRuneFiatLiquidityAmount] = useState< + string | undefined + >() + const [slippageRune, setSlippageRune] = useState() + const [isSlippageLoading, setIsSlippageLoading] = useState(false) + + const actualAssetCryptoLiquidityAmount = useMemo(() => { + if (isAsymAssetSide) { + // In asym asset side pool, use the virtual amount as is + return virtualAssetCryptoLiquidityAmount + } else if (isAsymRuneSide) { + // In asym rune side pool, the asset amount should be zero + return '0' + } + // For symmetrical pools, use the virtual amount as is + return virtualAssetCryptoLiquidityAmount + }, [isAsymAssetSide, isAsymRuneSide, virtualAssetCryptoLiquidityAmount]) + + const actualRuneCryptoLiquidityAmount = useMemo(() => { + if (isAsymRuneSide) { + // In asym rune side pool, use the virtual amount as is + return virtualRuneCryptoLiquidityAmount + } else if (isAsymAssetSide) { + // In asym asset side pool, the rune amount should be zero + return '0' + } + // For symmetrical pools, use the virtual amount as is + return virtualRuneCryptoLiquidityAmount + }, [isAsymRuneSide, isAsymAssetSide, virtualRuneCryptoLiquidityAmount]) + + const actualAssetFiatLiquidityAmount = useMemo(() => { + if (isAsymAssetSide) { + // In asym asset side pool, use the virtual fiat amount as is + return virtualAssetFiatLiquidityAmount + } else if (isAsymRuneSide) { + // In asym rune side pool, the asset fiat amount should be zero + return '0' + } + // For symmetrical pools, use the virtual fiat amount as is + return virtualAssetFiatLiquidityAmount + }, [isAsymAssetSide, isAsymRuneSide, virtualAssetFiatLiquidityAmount]) + + const actualRuneFiatLiquidityAmount = useMemo(() => { + if (isAsymRuneSide) { + // In asym rune side pool, use the virtual fiat amount as is + return virtualRuneFiatLiquidityAmount + } else if (isAsymAssetSide) { + // In asym asset side pool, the rune fiat amount should be zero + return '0' + } + // For symmetrical pools, use the virtual fiat amount as is + return virtualRuneFiatLiquidityAmount + }, [isAsymRuneSide, isAsymAssetSide, virtualRuneFiatLiquidityAmount]) + + const poolAssetFeeAsset = useAppSelector(state => + selectFeeAssetById(state, poolAsset?.assetId ?? ''), + ) + + const poolAssetFeeAssetMarktData = useAppSelector(state => + selectMarketDataById(state, poolAssetFeeAsset?.assetId ?? ''), + ) + + const assetMarketData = useAppSelector(state => + selectMarketDataById(state, poolAsset?.assetId ?? ''), + ) + const runeMarketData = useAppSelector(state => selectMarketDataById(state, rune?.assetId ?? '')) + + const { data: inboundAddressesData } = useQuery({ + ...reactQueries.thornode.inboundAddresses(), + enabled: !!poolAsset, + select: data => selectInboundAddressData(data, poolAsset?.assetId), + // @lukemorales/query-key-factory only returns queryFn and queryKey - all others will be ignored in the returned object + // Go stale instantly + staleTime: 0, + // Never store queries in cache since we always want fresh data + gcTime: 0, + refetchOnWindowFocus: true, + refetchOnMount: true, + refetchInterval: 60_000, + }) useEffect(() => { if (!userData) return - const _UserlpData: UserLpDataPosition | undefined = userData.find( + const _userlpData: UserLpDataPosition | undefined = userData.find( data => data.opportunityId === opportunityId, ) - if (!_UserlpData) return - setUserlpData(_UserlpData) + if (!_userlpData) return + setUserlpData(_userlpData) + const runeAddress = _userlpData?.runeAddress + if (!runeAddress) return + const runeAccountId = toAccountId({ + chainId: thorchainChainId, + account: runeAddress, + }) + setRuneAccountId(runeAccountId) }, [foundPoolAsset, opportunityId, poolAsset?.assetId, userData]) const handleBackClick = useCallback(() => { browserHistory.push('/pools') }, [browserHistory]) - const handleAccountIdChange = useCallback(() => { - console.info('account change') - }, []) - const handleSubmit = useCallback(() => { history.push(RemoveLiquidityRoutePaths.Confirm) }, [history]) @@ -133,29 +251,77 @@ export const RemoveLiquidityInput: React.FC = ({ setVirtualRuneCryptoLiquidityAmount( bnOrZero(underlyingRuneAmountCryptoPrecision) .times(percentageSelection / 100) - .times(isAsymAssetSide || isAsymRuneSide ? 2 : 1) .toFixed(), ) setVirtualRuneFiatLiquidityAmount( bnOrZero(underlyingRuneValueFiatUserCurrency) .times(percentageSelection / 100) - .times(isAsymAssetSide || isAsymRuneSide ? 2 : 1) .toFixed(), ) setVirtualAssetFiatLiquidityAmount( bnOrZero(underlyingAssetValueFiatUserCurrency) .times(percentageSelection / 100) - .times(isAsymAssetSide || isAsymRuneSide ? 2 : 1) .toFixed(), ) setVirtualAssetCryptoLiquidityAmount( bnOrZero(underlyingAssetAmountCryptoPrecision) .times(percentageSelection / 100) - .times(isAsymAssetSide || isAsymRuneSide ? 2 : 1) .toFixed(), ) }, [isAsymAssetSide, isAsymRuneSide, percentageSelection, userlpData]) + // We reuse lending utils here since all this does is estimating fees for a given withdrawal amount with a memo + // It's not going to be 100% accurate for EVM chains as it doesn't calculate the cost of depositWithExpiry, but rather a simple send, + // however that's fine for now until accurate fees estimation is implemented + const { data: estimatedRuneFeesData, isLoading: isEstimatedRuneFeesDataLoading } = + useQuoteEstimatedFeesQuery({ + collateralAssetId: thorchainAssetId, + collateralAccountId: runeAccountId ?? '', // This will be undefined for asym asset side LPs, and that's ok + repaymentAccountId: runeAccountId ?? '', // This will be undefined for asym asset side LPs, and that's ok + repaymentAsset: runeAsset ?? null, + repaymentAmountCryptoPrecision: actualRuneCryptoLiquidityAmount, + confirmedQuote, + }) + + const { data: estimatedPoolAssetFeesData, isLoading: isEstimatedPoolAssetFeesDataLoading } = + useQuoteEstimatedFeesQuery({ + collateralAssetId: poolAsset?.assetId ?? '', + collateralAccountId: poolAccountId, + repaymentAccountId: poolAccountId, + repaymentAsset: poolAsset ?? null, + confirmedQuote, + repaymentAmountCryptoPrecision: actualAssetCryptoLiquidityAmount, + }) + + const poolAssetTxFeeCryptoPrecision = useMemo( + () => + fromBaseUnit( + estimatedPoolAssetFeesData?.txFeeCryptoBaseUnit ?? 0, + poolAssetFeeAsset?.precision ?? 0, + ), + [estimatedPoolAssetFeesData?.txFeeCryptoBaseUnit, poolAssetFeeAsset?.precision], + ) + + const runeTxFeeCryptoPrecision = useMemo( + () => fromBaseUnit(estimatedRuneFeesData?.txFeeCryptoBaseUnit ?? 0, rune?.precision ?? 0), + [estimatedRuneFeesData?.txFeeCryptoBaseUnit, rune?.precision], + ) + + const poolAssetGasFeeFiat = useMemo( + () => bnOrZero(poolAssetTxFeeCryptoPrecision).times(poolAssetFeeAssetMarktData.price), + [poolAssetFeeAssetMarktData.price, poolAssetTxFeeCryptoPrecision], + ) + + const runeGasFeeFiat = useMemo( + () => bnOrZero(runeTxFeeCryptoPrecision).times(runeMarketData.price), + [runeMarketData.price, runeTxFeeCryptoPrecision], + ) + + const totalGasFeeFiat = useMemo( + () => poolAssetGasFeeFiat.plus(runeGasFeeFiat).toFixed(2), + [poolAssetGasFeeFiat, runeGasFeeFiat], + ) + const handlePercentageClick = useCallback((percentage: number) => { return () => { setPercentageSelection(percentage) @@ -186,6 +352,27 @@ export const RemoveLiquidityInput: React.FC = ({ ) }, []) + const poolAssetInboundAddress = useMemo(() => { + if (!poolAsset) return + const transactionType = getThorchainLpTransactionType(poolAsset.chainId) + + switch (transactionType) { + case 'MsgDeposit': + return THORCHAIN_POOL_MODULE_ADDRESS + + case 'EvmCustomTx': + // TODO: this should really be inboundAddressData?.router, but useQuoteEstimatedFeesQuery doesn't yet handle contract calls + // for the purpose of naively assuming a send, using the inbound address instead of the router is fine + return inboundAddressesData?.address + + case 'Send': + return inboundAddressesData?.address + + default: + assertUnreachable(transactionType as never) + } + }, [poolAsset, inboundAddressesData?.address]) + const renderHeader = useMemo(() => { if (headerComponent) return headerComponent return ( @@ -202,66 +389,6 @@ export const RemoveLiquidityInput: React.FC = ({ ) }, [backIcon, handleBackClick, headerComponent, translate]) - const assetMarketData = useAppSelector(state => - selectMarketDataById(state, poolAsset?.assetId ?? ''), - ) - const runeMarketData = useAppSelector(state => selectMarketDataById(state, rune?.assetId ?? '')) - - // Virtual as in, these are the amounts if removing symetrically. But a user may remove asymetrically, so these are not the *actual* amounts - // Keeping these as virtual amounts is useful from a UI perspective, as it allows rebalancing to automagically work when switching from sym. type, - // while using the *actual* amounts whenever we do things like checking for asset balance - const [virtualAssetCryptoLiquidityAmount, setVirtualAssetCryptoLiquidityAmount] = useState< - string | undefined - >() - const [virtualAssetFiatLiquidityAmount, setVirtualAssetFiatLiquidityAmount] = useState< - string | undefined - >() - const [virtualRuneCryptoLiquidityAmount, setVirtualRuneCryptoLiquidityAmount] = useState< - string | undefined - >() - const [virtualRuneFiatLiquidityAmount, setVirtualRuneFiatLiquidityAmount] = useState< - string | undefined - >() - - const actualAssetCryptoLiquidityAmount = useMemo(() => { - if (isAsymAssetSide) { - // In asym asset side pool, use the virtual amount as is - return virtualAssetCryptoLiquidityAmount - } else if (isAsymRuneSide) { - // In asym rune side pool, the asset amount should be zero - return '0' - } - // For symmetrical pools, use the virtual amount as is - return virtualAssetCryptoLiquidityAmount - }, [isAsymAssetSide, isAsymRuneSide, virtualAssetCryptoLiquidityAmount]) - - const actualRuneCryptoLiquidityAmount = useMemo(() => { - if (isAsymRuneSide) { - // In asym rune side pool, use the virtual amount as is - return virtualRuneCryptoLiquidityAmount - } else if (isAsymAssetSide) { - // In asym asset side pool, the rune amount should be zero - return '0' - } - // For symmetrical pools, use the virtual amount as is - return virtualRuneCryptoLiquidityAmount - }, [isAsymRuneSide, isAsymAssetSide, virtualRuneCryptoLiquidityAmount]) - - const actualRuneFiatLiquidityAmount = useMemo(() => { - if (isAsymRuneSide) { - // In asym rune side pool, use the virtual fiat amount as is - return virtualRuneFiatLiquidityAmount - } else if (isAsymAssetSide) { - // In asym asset side pool, the rune fiat amount should be zero - return '0' - } - // For symmetrical pools, use the virtual fiat amount as is - return virtualRuneFiatLiquidityAmount - }, [isAsymRuneSide, isAsymAssetSide, virtualRuneFiatLiquidityAmount]) - - const [slippageRune, setSlippageRune] = useState() - const [isSlippageLoading, setIsSlippageLoading] = useState(false) - const runePerAsset = useMemo(() => { if (!assetMarketData || !runeMarketData) return undefined return bn(assetMarketData.price).div(bn(runeMarketData.price)).toFixed() @@ -338,8 +465,6 @@ export const RemoveLiquidityInput: React.FC = ({ assetAmountCryptoThorPrecision, }) - console.log('xxx debug estimate', { estimate }) - setIsSlippageLoading(false) setSlippageRune( @@ -349,6 +474,8 @@ export const RemoveLiquidityInput: React.FC = ({ .times(2) .toFixed(), ) + + setShareOfPoolDecimalPercent(estimate.poolShareDecimalPercent) })() }, [ actualAssetCryptoLiquidityAmount, @@ -365,6 +492,56 @@ export const RemoveLiquidityInput: React.FC = ({ userlpData, ]) + useEffect(() => { + if ( + !( + actualAssetCryptoLiquidityAmount && + actualAssetFiatLiquidityAmount && + actualRuneCryptoLiquidityAmount && + actualRuneFiatLiquidityAmount && + shareOfPoolDecimalPercent && + slippageRune && + opportunityId && + poolAssetInboundAddress + ) + ) + return + + const totalAmountFiat = bnOrZero(actualAssetFiatLiquidityAmount) + .times(isAsym ? 1 : 2) + .toFixed() + + setConfirmedQuote({ + assetCryptoLiquidityAmount: actualAssetCryptoLiquidityAmount, + assetFiatLiquidityAmount: actualAssetFiatLiquidityAmount, + runeCryptoLiquidityAmount: actualRuneCryptoLiquidityAmount, + runeFiatLiquidityAmount: actualRuneFiatLiquidityAmount, + shareOfPoolDecimalPercent, + slippageRune, + opportunityId, + totalAmountFiat, + quoteInboundAddress: poolAssetInboundAddress, + runeGasFeeFiat: runeGasFeeFiat.toFixed(2), + poolAssetGasFeeFiat: poolAssetGasFeeFiat.toFixed(2), + totalGasFeeFiat, + }) + }, [ + actualAssetCryptoLiquidityAmount, + actualAssetFiatLiquidityAmount, + actualRuneCryptoLiquidityAmount, + actualRuneFiatLiquidityAmount, + isAsym, + opportunityId, + poolAssetGasFeeFiat, + poolAssetInboundAddress, + runeGasFeeFiat, + runeMarketData.price, + setConfirmedQuote, + shareOfPoolDecimalPercent, + slippageRune, + totalGasFeeFiat, + ]) + const tradeAssetInputs = useMemo(() => { if (!(poolAsset && rune && foundPool)) return null @@ -380,32 +557,55 @@ export const RemoveLiquidityInput: React.FC = ({ {assets.map(asset => { const isRune = asset.assetId === rune.assetId + const isAsym = foundPool.isAsymmetric + console.log('xxx isAsym', isAsym) const marketData = isRune ? runeMarketData : assetMarketData const handleRemoveLiquidityInputChange = createHandleRemoveLiquidityInputChange( marketData, isRune, ) - const cryptoAmount = isRune - ? virtualRuneCryptoLiquidityAmount - : virtualAssetCryptoLiquidityAmount - const fiatAmount = isRune - ? virtualRuneFiatLiquidityAmount - : virtualAssetFiatLiquidityAmount - - // const accountId = accountIdsByChainId[asset.chainId] + const cryptoAmount = bnOrZero( + isRune ? virtualRuneCryptoLiquidityAmount : virtualAssetCryptoLiquidityAmount, + ) + .times(isAsym ? 2 : 1) + .toFixed() + const fiatAmount = bnOrZero( + isRune ? virtualRuneFiatLiquidityAmount : virtualAssetFiatLiquidityAmount, + ) + .times(isAsym ? 2 : 1) + .toFixed() + const cryptoBalance = bnOrZero( + isRune + ? userlpData?.underlyingRuneAmountCryptoPrecision + : userlpData?.underlyingAssetAmountCryptoPrecision, + ) + .times(isAsym ? 2 : 1) + .toFixed() + + const fiatBalance = bnOrZero( + isRune + ? userlpData?.underlyingRuneValueFiatUserCurrency + : userlpData?.underlyingAssetValueFiatUserCurrency, + ) + .times(isAsym ? 2 : 1) + .toFixed() + return ( - ) })} @@ -423,7 +623,11 @@ export const RemoveLiquidityInput: React.FC = ({ virtualAssetCryptoLiquidityAmount, virtualRuneFiatLiquidityAmount, virtualAssetFiatLiquidityAmount, - handleAccountIdChange, + userlpData?.underlyingRuneAmountCryptoPrecision, + userlpData?.underlyingAssetAmountCryptoPrecision, + userlpData?.underlyingRuneValueFiatUserCurrency, + userlpData?.underlyingAssetValueFiatUserCurrency, + poolAccountId, percentOptions, ]) @@ -486,8 +690,10 @@ export const RemoveLiquidityInput: React.FC = ({ {translate('common.gasFee')} - - + + @@ -495,6 +701,7 @@ export const RemoveLiquidityInput: React.FC = ({ {translate('common.fees')} + {/* There are no protocol fees when removing liquidity */} diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 004df1fb3fa..f7fbcbab745 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -8,7 +8,10 @@ import { estimateFees } from 'components/Modals/Send/utils' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { getSupportedEvmChainIds } from 'lib/utils/evm' import type { LendingQuoteClose, LendingQuoteOpen } from 'lib/utils/thorchain/lending/types' -import type { LpConfirmedDepositQuote } from 'lib/utils/thorchain/lp/types' +import type { + LpConfirmedDepositQuote, + LpConfirmedWithdrawalQuote, +} from 'lib/utils/thorchain/lp/types' import { selectFeeAssetById, selectMarketDataById } from 'state/slices/selectors' import { useAppSelector } from 'state/store' @@ -31,6 +34,7 @@ type UseQuoteEstimatedFeesProps = { depositAmountCryptoPrecision: string repaymentAccountId?: never repaymentAsset?: never + repaymentAmountCryptoPrecision?: never } | { confirmedQuote: LendingQuoteClose | null @@ -38,6 +42,7 @@ type UseQuoteEstimatedFeesProps = { depositAmountCryptoPrecision?: never repaymentAccountId: AccountId repaymentAsset: Asset | null + repaymentAmountCryptoPrecision?: never } | { confirmedQuote: LpConfirmedDepositQuote | null @@ -46,6 +51,16 @@ type UseQuoteEstimatedFeesProps = { depositAmountCryptoPrecision: string repaymentAccountId?: never repaymentAsset?: never + repaymentAmountCryptoPrecision?: never + } + | { + confirmedQuote: LpConfirmedWithdrawalQuote | null + // Technically not a collateral, but this avoids weird branching, ternaries or ?? checks for now + collateralAccountId: AccountId + depositAmountCryptoPrecision?: never + repaymentAccountId: AccountId + repaymentAsset: Asset | null + repaymentAmountCryptoPrecision: string | undefined } ) @@ -56,10 +71,13 @@ export const useQuoteEstimatedFeesQuery = ({ repaymentAccountId, repaymentAsset, confirmedQuote, + repaymentAmountCryptoPrecision: _repaymentAmountCryptoPrecision, }: UseQuoteEstimatedFeesProps) => { const repaymentAmountCryptoPrecision = useMemo( - () => (confirmedQuote as LendingQuoteClose)?.repaymentAmountCryptoPrecision, - [confirmedQuote], + () => + _repaymentAmountCryptoPrecision ?? + (confirmedQuote as LendingQuoteClose)?.repaymentAmountCryptoPrecision, + [_repaymentAmountCryptoPrecision, confirmedQuote], ) const feeAsset = useAppSelector(state => selectFeeAssetById(state, collateralAssetId)) const feeAssetMarketData = useAppSelector(state => selectMarketDataById(state, collateralAssetId)) From 4fa2c1048fd1d4dc6cb3e035611121f635b12481 Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Thu, 22 Feb 2024 17:11:17 +1100 Subject: [PATCH 45/60] chore: wire remove liquidity confirm page (#6266) --- src/assets/translations/en/main.json | 2 +- .../RemoveLiquidity/RemoveLiquidity.tsx | 5 ++- .../RemoveLiquidityConfirm.tsx | 33 +++++++++++++++++-- .../components/ReusableLpConfirm.tsx | 24 ++++++++++---- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/assets/translations/en/main.json b/src/assets/translations/en/main.json index 15c5d03e8ff..9addf1a928f 100644 --- a/src/assets/translations/en/main.json +++ b/src/assets/translations/en/main.json @@ -846,7 +846,6 @@ "cantSetSlippage": "We are unable to set a custom slippage (%{userSlippageFormatted}) for %{swapperName}", "slippage": "Slippage: %{slippageFormatted}" } - }, "modals": { "popup": { @@ -2233,6 +2232,7 @@ "chainFee": "%{chain} Fee", "supplying": "Supplying", "confirmAndDeposit": "Confirm and Deposit", + "confirmAndWithdraw": "Confirm and Withdraw", "removeAmounts": "Remove Amount(s)", "yourPositions": { "yourPositions": "Your Positions", diff --git a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx index 690d8743dc2..f3814e24019 100644 --- a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx +++ b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidity.tsx @@ -68,7 +68,10 @@ const RemoveLiquidityRoutes: React.FC = ({ ), [confirmedQuote, headerComponent, opportunityId, poolAccountId, setConfirmedQuote], ) - const renderRemoveLiquidityConfirm = useCallback(() => , []) + const renderRemoveLiquidityConfirm = useCallback( + () => (confirmedQuote ? : <>), + [confirmedQuote], + ) const renderRemoveLiquidityStatus = useCallback(() => , []) return ( diff --git a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityConfirm.tsx b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityConfirm.tsx index 4e618236d43..c3656780bac 100644 --- a/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityConfirm.tsx +++ b/src/pages/ThorChainLP/components/RemoveLiquidity/RemoveLiquidityConfirm.tsx @@ -1,3 +1,32 @@ -export const RemoveLiquidityConfirm = () => { - return

Remove Confirm

+import { thorchainAssetId } from '@shapeshiftoss/caip' +import { useCallback } from 'react' +import { useHistory } from 'react-router' +import type { LpConfirmedWithdrawalQuote } from 'lib/utils/thorchain/lp/types' + +import { ReusableLpConfirm } from '../ReusableLpConfirm' +import { RemoveLiquidityRoutePaths } from './types' + +type RemoveLiquidityConfirmProps = { + confirmedQuote: LpConfirmedWithdrawalQuote +} + +export const RemoveLiquidityConfirm = ({ confirmedQuote }: RemoveLiquidityConfirmProps) => { + const history = useHistory() + + const handleBack = useCallback(() => { + history.push(RemoveLiquidityRoutePaths.Input) + }, [history]) + + const handleConfirm = useCallback(() => { + history.push(RemoveLiquidityRoutePaths.Status) + }, [history]) + + return ( + + ) } diff --git a/src/pages/ThorChainLP/components/ReusableLpConfirm.tsx b/src/pages/ThorChainLP/components/ReusableLpConfirm.tsx index 0a39d8969a1..839c9fd1be0 100644 --- a/src/pages/ThorChainLP/components/ReusableLpConfirm.tsx +++ b/src/pages/ThorChainLP/components/ReusableLpConfirm.tsx @@ -28,6 +28,7 @@ import { Timeline, TimelineItem } from 'components/Timeline/Timeline' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { assertUnreachable } from 'lib/utils' +import type { LpConfirmedWithdrawalQuote } from 'lib/utils/thorchain/lp/types' import { AsymSide, type LpConfirmedDepositQuote } from 'lib/utils/thorchain/lp/types' import { selectAssetById } from 'state/slices/selectors' import { useAppSelector } from 'state/store' @@ -39,7 +40,7 @@ type ReusableLpConfirmProps = { handleBack: () => void handleConfirm: () => void baseAssetId: AssetId - confirmedQuote: LpConfirmedDepositQuote + confirmedQuote: LpConfirmedDepositQuote | LpConfirmedWithdrawalQuote } const dividerStyle = { @@ -191,8 +192,17 @@ export const ReusableLpConfirm: React.FC = ({ const confirmCopy = useMemo(() => { if (isTradingActive === false) return translate('common.poolHalted') - return translate('pools.confirmAndDeposit') - }, [isTradingActive, translate]) + const message = (() => { + if ('feeAmountFiat' in confirmedQuote) { + // 'feeAmountFiat' exists, so confirmedQuote is an instance of LpConfirmedDepositQuote + return translate('pools.confirmAndDeposit') + } else { + // 'feeAmountFiat' does not exist, so confirmedQuote is an instance of LpConfirmedWithdrawalQuote + return translate('pools.confirmAndWithdraw') + } + })() + return message + }, [confirmedQuote, isTradingActive, translate]) if (!(pool && asset && baseAsset)) return null @@ -213,10 +223,12 @@ export const ReusableLpConfirm: React.FC = ({ {translate('pools.chainFee', { chain: 'ShapeShift' })} - {bn(confirmedQuote.feeAmountFiat).isZero() ? ( - 'Free' - ) : ( + {confirmedQuote && + 'feeAmountFiat' in confirmedQuote && + !bn(confirmedQuote.feeAmountFiat).isZero() ? ( + ) : ( + )} From f7add3a12b489384fc706446cbf01ccf14164242 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:38:02 -0700 Subject: [PATCH 46/60] fix: merge --- src/components/Layout/Header/NavBar/Notifications.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index a11a0c6ff89..6731eba9975 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -6,10 +6,6 @@ import { getConfig } from 'config' import { toQuantity, toUtf8Bytes } from 'ethers' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' -<<<<<<< HEAD -======= -import { stringToBytes, toHex } from 'viem' ->>>>>>> 214c676c9c (feat: cleanup) import { KeyManager } from 'context/WalletProvider/KeyManager' import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from 'hooks/useWallet/useWallet' From 043cbbfc7f388a359509c35aaeeaa1ad4f24c0c9 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:27:23 -0700 Subject: [PATCH 47/60] remove remaining copy pasta mocks --- __mocks__/ethers.ts | 91 +++++++++--------- packages/chain-adapters/src/evm/utils.ts | 4 +- .../parser/__tests__/arbitrum.test.ts | 93 ------------------- .../parser/__tests__/arbitrumNova.test.ts | 93 ------------------- .../parser/__tests__/avalanche.test.ts | 93 ------------------- .../parser/__tests__/bnbsmartchain.test.ts | 93 ------------------- .../parser/__tests__/ethereum.test.ts | 93 ------------------- .../gnosis/parser/__tests__/gnosis.test.ts | 93 ------------------- .../parser/__tests__/optimism.test.ts | 93 ------------------- .../polygon/parser/__tests__/polygon.test.ts | 93 ------------------- 10 files changed, 50 insertions(+), 789 deletions(-) diff --git a/__mocks__/ethers.ts b/__mocks__/ethers.ts index 9abe6aede49..248a5277331 100644 --- a/__mocks__/ethers.ts +++ b/__mocks__/ethers.ts @@ -1,49 +1,54 @@ -import ethers from 'ethers' +import { ethers } from 'ethers' import { vi } from 'vitest' +const Contract = vi.fn().mockImplementation(address => ({ + decimals: () => { + switch (address as string) { + case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': + return 6 + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 18 + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 18 + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 18 + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + name: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'Uniswap V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'Wrapped Ether' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, + symbol: () => { + switch (address as string) { + case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': + return 'FOX' + case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': + return 'UNI-V2' + case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': + return 'WETH' + default: + throw new Error(`no decimals mock for address: ${address}`) + } + }, +})) + +const JsonRpcProvider = vi.fn() + const ethersMock = { ...ethers, - JsonRpcProvider: vi.fn(), - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), + JsonRpcProvider, + Contract, } -export { ethersMock as ethers } +export * from 'ethers' +export { ethersMock as ethers, Contract, JsonRpcProvider } diff --git a/packages/chain-adapters/src/evm/utils.ts b/packages/chain-adapters/src/evm/utils.ts index cd7779c73d5..4a8344ef4ee 100644 --- a/packages/chain-adapters/src/evm/utils.ts +++ b/packages/chain-adapters/src/evm/utils.ts @@ -1,4 +1,4 @@ -import { Contract } from 'ethers' +import { Contract } from '@ethersproject/contracts' import erc20Abi from './erc20Abi.json' @@ -9,6 +9,6 @@ export const getErc20Data = async ( ): Promise => { if (!contractAddress) return '' const erc20Contract = new Contract(contractAddress, erc20Abi) - const { data: callData } = await erc20Contract.transfer.populateTransaction(to, value) + const { data: callData } = await erc20Contract.populateTransaction.transfer(to, value) return callData || '' } diff --git a/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts b/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts index eb1e14244f8..39832308dec 100644 --- a/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts +++ b/packages/unchained-client/src/evm/arbitrum/parser/__tests__/arbitrum.test.ts @@ -1,6 +1,5 @@ import { arbitrumAssetId, arbitrumChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -22,98 +21,6 @@ import zrxTradeUsdcToWbtc from './mockData/zrxTradeUsdcToWbtc' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts b/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts index 591b168573f..60331600c59 100644 --- a/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts +++ b/packages/unchained-client/src/evm/arbitrumNova/parser/__tests__/arbitrumNova.test.ts @@ -1,6 +1,5 @@ import { arbitrumNovaAssetId, arbitrumNovaChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import { TransferType, TxStatus } from '../../../../types' @@ -18,98 +17,6 @@ import tokenStandard from './mockData/tokenStandard' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts b/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts index 4b744477719..0bc2dd8ba70 100644 --- a/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts +++ b/packages/unchained-client/src/evm/avalanche/parser/__tests__/avalanche.test.ts @@ -1,6 +1,5 @@ import { avalancheAssetId, avalancheChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -22,98 +21,6 @@ import zrxTradeWethToWbtc from './mockData/zrxTradeWethToWbtc' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts index 7ffb09e5322..2c37ac1e20d 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/__tests__/bnbsmartchain.test.ts @@ -1,6 +1,5 @@ import { bscAssetId, bscChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -22,98 +21,6 @@ import zrxTradeUsdtToBusd from './mockData/zrxTradeUsdtToBusd' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts b/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts index 82ba5ec135c..338e92d3379 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/__tests__/ethereum.test.ts @@ -1,6 +1,5 @@ import { ethAssetId, ethChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type ethers from 'ethers' import { beforeAll, describe, expect, it, vi } from 'vitest' import type { Trade } from '../../../../types' @@ -87,98 +86,6 @@ import zrxTradeEthToMatic from './mockData/zrxTradeEthToMatic' import zrxTradeTetherToKishu from './mockData/zrxTradeTetherToKishu' import zrxTradeTribeToEth from './mockData/zrxTradeTribeToEth' -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const mocks = vi.hoisted(() => { const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', diff --git a/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts b/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts index c0fc66d7581..515fa18044b 100644 --- a/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts +++ b/packages/unchained-client/src/evm/gnosis/parser/__tests__/gnosis.test.ts @@ -1,6 +1,5 @@ import { gnosisAssetId, gnosisChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import { TransferType, TxStatus } from '../../../../types' @@ -18,98 +17,6 @@ import xdaiStandard from './mockData/xdaiStandard' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts b/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts index a3197836ed2..389c60dbb09 100644 --- a/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts +++ b/packages/unchained-client/src/evm/optimism/parser/__tests__/optimism.test.ts @@ -1,6 +1,5 @@ import { optimismAssetId, optimismChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -22,98 +21,6 @@ import zrxTradeUsdcToOp from './mockData/zrxTradeUsdcToOp' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', diff --git a/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts b/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts index 81ffaef0c75..d6536c0692b 100644 --- a/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts +++ b/packages/unchained-client/src/evm/polygon/parser/__tests__/polygon.test.ts @@ -1,6 +1,5 @@ import { polygonAssetId, polygonChainId } from '@shapeshiftoss/caip' import type { evm } from '@shapeshiftoss/common-api' -import type { ethers } from 'ethers' import { describe, expect, it, vi } from 'vitest' import type { Trade, Transfer } from '../../../../types' @@ -22,98 +21,6 @@ import zrxTradeUsdcToUsdt from './mockData/zrxTradeUsdcToUsdt' const mockedApi = vi.mocked(new V1Api()) -vi.mock('ethers', async importActual => { - const actual: typeof ethers = await importActual() - return { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - - JsonRpcProvider: vi.fn(), - default: { - ...actual, - Contract: vi.fn().mockImplementation(address => ({ - decimals: () => { - switch (address as string) { - case '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48': - return 6 - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 18 - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 18 - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 18 - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - name: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'Uniswap V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'Wrapped Ether' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - symbol: () => { - switch (address as string) { - case '0xc770EEfAd204B5180dF6a14Ee197D99d808ee52d': - return 'FOX' - case '0x470e8de2eBaef52014A47Cb5E6aF86884947F08c': - return 'UNI-V2' - case '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2': - return 'WETH' - default: - throw new Error(`no decimals mock for address: ${address}`) - } - }, - })), - }, - } -}) - const tokenMetadata: evm.TokenMetadata = { name: 'Foxy', description: 'The foxiest Fox', From ceca8eb7ee8b2286f226d844bb3de5440c585f09 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:08:24 -0700 Subject: [PATCH 48/60] unchained-client cleanup --- packages/unchained-client/package.json | 4 ---- .../src/evm/bnbsmartchain/parser/bep20.ts | 2 +- .../unchained-client/src/evm/ethereum/parser/foxy.ts | 8 ++++---- .../unchained-client/src/evm/ethereum/parser/uniV2.ts | 8 ++++---- .../unchained-client/src/evm/ethereum/parser/weth.ts | 4 ++-- packages/unchained-client/src/evm/parser/erc20.ts | 2 +- packages/unchained-client/src/evm/parser/index.ts | 2 +- packages/unchained-client/src/evm/parser/thorchain.ts | 11 +++++------ 8 files changed, 18 insertions(+), 23 deletions(-) diff --git a/packages/unchained-client/package.json b/packages/unchained-client/package.json index 3867028de15..f1c2371ac00 100644 --- a/packages/unchained-client/package.json +++ b/packages/unchained-client/package.json @@ -20,14 +20,10 @@ "dependencies": { "@shapeshiftoss/caip": "workspace:^", "@shapeshiftoss/common-api": "^9.3.0", - "ethers": "^6.11.1", "isomorphic-ws": "^4.0.1", "ws": "^8.3.0" }, "devDependencies": { "@openapitools/openapi-generator-cli": "^2.5.1" - }, - "resolutions": { - "ethers": "^6.11.1" } } diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts index f4813153eac..136d0e8f43d 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts @@ -25,7 +25,7 @@ export class Parser implements SubParser { readonly abiInterface = new ethers.Interface(bep20) readonly supportedFunctions = { - approveSigHash: this.abiInterface.getFunction('approve')?.selector, + approveSigHash: this.abiInterface.getFunction('approve')!.selector, } constructor(args: ParserArgs) { diff --git a/packages/unchained-client/src/evm/ethereum/parser/foxy.ts b/packages/unchained-client/src/evm/ethereum/parser/foxy.ts index 3751a3f5cb6..b902685fbe0 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/foxy.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/foxy.ts @@ -15,10 +15,10 @@ export class Parser implements SubParser { readonly abiInterface = new ethers.Interface(FOXY_STAKING_ABI) readonly supportedFunctions = { - stakeSigHash: this.abiInterface.getFunction('stake(uint256,address)')?.selector, - unstakeSigHash: this.abiInterface.getFunction('unstake')?.selector, - instantUnstakeSigHash: this.abiInterface.getFunction('instantUnstake')?.selector, - claimWithdrawSigHash: this.abiInterface.getFunction('claimWithdraw')?.selector, + stakeSigHash: this.abiInterface.getFunction('stake(uint256,address)')!.selector, + unstakeSigHash: this.abiInterface.getFunction('unstake')!.selector, + instantUnstakeSigHash: this.abiInterface.getFunction('instantUnstake')!.selector, + claimWithdrawSigHash: this.abiInterface.getFunction('claimWithdraw')!.selector, } async parse(tx: Tx): Promise { diff --git a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts index dfe877efd28..b244e39fd1f 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/uniV2.ts @@ -35,13 +35,13 @@ export class Parser implements SubParser { readonly stakingRewardsInterface = new Interface(UNIV2_STAKING_REWARDS_ABI) readonly supportedFunctions = { - addLiquidityEthSigHash: this.abiInterface.getFunction('addLiquidityETH')?.selector, - removeLiquidityEthSigHash: this.abiInterface.getFunction('removeLiquidityETH')?.selector, + addLiquidityEthSigHash: this.abiInterface.getFunction('addLiquidityETH')!.selector, + removeLiquidityEthSigHash: this.abiInterface.getFunction('removeLiquidityETH')!.selector, } readonly supportedStakingRewardsFunctions = { - stakeSigHash: this.stakingRewardsInterface.getFunction('stake')?.selector, - exitSigHash: this.stakingRewardsInterface.getFunction('exit')?.selector, + stakeSigHash: this.stakingRewardsInterface.getFunction('stake')!.selector, + exitSigHash: this.stakingRewardsInterface.getFunction('exit')!.selector, } constructor(args: ParserArgs) { diff --git a/packages/unchained-client/src/evm/ethereum/parser/weth.ts b/packages/unchained-client/src/evm/ethereum/parser/weth.ts index 5fda25f2121..7294c354cbe 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/weth.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/weth.ts @@ -26,8 +26,8 @@ export class Parser implements SubParser { readonly abiInterface = new ethers.Interface(WETH_ABI) readonly supportedFunctions = { - depositSigHash: this.abiInterface.getFunction('deposit')?.selector, - withdrawalSigHash: this.abiInterface.getFunction('withdraw')?.selector, + depositSigHash: this.abiInterface.getFunction('deposit')!.selector, + withdrawalSigHash: this.abiInterface.getFunction('withdraw')!.selector, } constructor(args: ParserArgs) { diff --git a/packages/unchained-client/src/evm/parser/erc20.ts b/packages/unchained-client/src/evm/parser/erc20.ts index 0327263ed9c..710f48d593c 100644 --- a/packages/unchained-client/src/evm/parser/erc20.ts +++ b/packages/unchained-client/src/evm/parser/erc20.ts @@ -25,7 +25,7 @@ export class Parser implements SubParser { readonly abiInterface = new ethers.Interface(ERC20_ABI) readonly supportedFunctions = { - approveSigHash: this.abiInterface.getFunction('approve')?.selector ?? '', + approveSigHash: this.abiInterface.getFunction('approve')!.selector, } constructor(args: ParserArgs) { diff --git a/packages/unchained-client/src/evm/parser/index.ts b/packages/unchained-client/src/evm/parser/index.ts index ca8cd7e78a4..0a1d582476f 100644 --- a/packages/unchained-client/src/evm/parser/index.ts +++ b/packages/unchained-client/src/evm/parser/index.ts @@ -34,7 +34,7 @@ export class BaseTransactionParser { this.chainId = args.chainId this.assetId = args.assetId this.api = args.api - this.provider = new JsonRpcProvider(args.rpcUrl) + this.provider = new JsonRpcProvider(args.rpcUrl, undefined, { staticNetwork: true }) } /** diff --git a/packages/unchained-client/src/evm/parser/thorchain.ts b/packages/unchained-client/src/evm/parser/thorchain.ts index 6632e175c0d..f4892f107b1 100644 --- a/packages/unchained-client/src/evm/parser/thorchain.ts +++ b/packages/unchained-client/src/evm/parser/thorchain.ts @@ -40,12 +40,11 @@ export class Parser implements SubParser { constructor(args: ParserArgs) { this.abiInterface = new ethers.Interface(routerAbi) this.supportedFunctions = { - depositSigHash: this.abiInterface.getFunction('deposit')?.selector ?? '', - depositWithExpirySigHash: this.abiInterface.getFunction('depositWithExpiry')?.selector ?? '', - transferOutSigHash: this.abiInterface.getFunction('transferOut')?.selector ?? '', - transferOutAndCallSigHash: - this.abiInterface.getFunction('transferOutAndCall')?.selector ?? '', - swapInSigHash: this.abiInterface.getFunction('swapIn')?.selector ?? '', + depositSigHash: this.abiInterface.getFunction('deposit')!.selector, + depositWithExpirySigHash: this.abiInterface.getFunction('depositWithExpiry')!.selector, + transferOutSigHash: this.abiInterface.getFunction('transferOut')!.selector, + transferOutAndCallSigHash: this.abiInterface.getFunction('transferOutAndCall')!.selector, + swapInSigHash: this.abiInterface.getFunction('swapIn')!.selector, } this.thorchainParser = new ThorchainParser({ midgardUrl: args.midgardUrl }) this.chainId = args.chainId From 486af284c770db5c83b203aece50317ab2b62aa6 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:08:39 -0700 Subject: [PATCH 49/60] use v5 alias for yearn --- packages/caip/src/adapters/yearn/utils.ts | 6 ++---- scripts/generateAssetData/ethereum/yearnVaults.ts | 8 ++------ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/caip/src/adapters/yearn/utils.ts b/packages/caip/src/adapters/yearn/utils.ts index 4549c1e779a..4de04ea8830 100644 --- a/packages/caip/src/adapters/yearn/utils.ts +++ b/packages/caip/src/adapters/yearn/utils.ts @@ -1,6 +1,6 @@ import type { Token, Vault } from '@yfi/sdk' import { Yearn } from '@yfi/sdk' -import { ethers } from 'ethers' +import { ethers } from 'ethers5' import fs from 'fs' import toLower from 'lodash/toLower' import uniqBy from 'lodash/uniqBy' @@ -10,9 +10,7 @@ import { toChainId } from '../../chainId/chainId' import { CHAIN_NAMESPACE, CHAIN_REFERENCE } from '../../constants' const network = 1 // 1 for mainnet -const provider = new ethers.JsonRpcProvider(process.env.REACT_APP_ETHEREUM_NODE_URL) -// @ts-ignore types are drunk here as yearn expects the v5 flavor of ethers JsonRpcProvider, -// but yearn usage is nuked from the codebase so meh +const provider = new ethers.providers.StaticJsonRpcProvider(process.env.REACT_APP_ETHEREUM_NODE_URL) const yearnSdk = new Yearn(network, { provider }) export const writeFiles = async (data: Record>) => { diff --git a/scripts/generateAssetData/ethereum/yearnVaults.ts b/scripts/generateAssetData/ethereum/yearnVaults.ts index cd5583ecda1..62df72e4d0e 100644 --- a/scripts/generateAssetData/ethereum/yearnVaults.ts +++ b/scripts/generateAssetData/ethereum/yearnVaults.ts @@ -2,18 +2,14 @@ import { ethChainId as chainId, toAssetId } from '@shapeshiftoss/caip' import type { Asset } from '@shapeshiftoss/types' import type { Token, Vault } from '@yfi/sdk' import { Yearn } from '@yfi/sdk' -import { ethers } from 'ethers' +import { ethers } from 'ethers5' import toLower from 'lodash/toLower' import { ethereum } from '../baseAssets' import { colorMap } from '../colorMap' const network = 1 // 1 for mainnet -// This is wrong, but this doesn't matter since yearn is nuked -// 1. we should not instantiate a provider at module scope, which will make an XHR for nothing when this module gets evaluated -// 2. we should pass the provider in as a dependency, since it is cached in web -const provider = new ethers.JsonRpcProvider(process.env.ETHEREUM_NODE_URL) -// @ts-ignore @yfi/sdk expects an ethers v5 provider, but we're now using v6 +const provider = new ethers.providers.StaticJsonRpcProvider(process.env.ETHEREUM_NODE_URL) export const yearnSdk = new Yearn(network, { provider }) const explorerData = { From fcfde46fa368f4208ffa67b51dc4d38fb252302b Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:15:38 -0700 Subject: [PATCH 50/60] remove extra getAddress calls --- .../Deposit/components/Deposit.tsx | 8 ++---- .../Withdraw/components/Approve.tsx | 2 +- .../Withdraw/components/Withdraw.tsx | 2 +- .../univ2/hooks/useUniV2LiquidityPool.ts | 28 +++++++++---------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx index df6c5404876..b9b0ffb36fa 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Deposit/components/Deposit.tsx @@ -195,14 +195,10 @@ export const Deposit: React.FC = ({ // e.g https://github.com/Uniswap/governance/blob/eabd8c71ad01f61fb54ed6945162021ee419998e/contracts/Uni.sol#L119 const asset0ApprovalFee = asset0ContractAddress && - bnOrZero( - (await getApproveFees(getAddress(asset0ContractAddress)))?.networkFeeCryptoBaseUnit, - ) + bnOrZero((await getApproveFees(asset0ContractAddress))?.networkFeeCryptoBaseUnit) const asset1ApprovalFee = asset1ContractAddress && - bnOrZero( - (await getApproveFees(getAddress(asset1ContractAddress)))?.networkFeeCryptoBaseUnit, - ) + bnOrZero((await getApproveFees(asset1ContractAddress))?.networkFeeCryptoBaseUnit) if (!(asset0ApprovalFee || asset1ApprovalFee)) return diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx index a4b06d7ab1b..5d88657aab4 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Approve.tsx @@ -113,7 +113,7 @@ export const Approve: React.FC = ({ accountId, onNext }) => { try { dispatch({ type: UniV2WithdrawActionType.SET_LOADING, payload: true }) const lpAssetContractAddress = getAddress(fromAssetId(lpAssetId).assetReference) - await approveAsset(getAddress(lpAssetContractAddress)) + await approveAsset(lpAssetContractAddress) await poll({ fn: () => lpAllowance(), validate: (result: string) => { diff --git a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx index 6d95c9f57ba..4090cddffa6 100644 --- a/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/univ2/components/UniV2Manager/Withdraw/components/Withdraw.tsx @@ -202,7 +202,7 @@ export const Withdraw: React.FC = ({ } else { const lpAssetContractAddress = getAddress(fromAssetId(lpAssetId).assetReference) - const fees = await getApproveFees(getAddress(lpAssetContractAddress)) + const fees = await getApproveFees(lpAssetContractAddress) if (!fees) return dispatch({ diff --git a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts index 806ccdc440a..3ceb9ef9db0 100644 --- a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts +++ b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts @@ -11,7 +11,8 @@ import { getOrCreateContractByAddress, getOrCreateContractByType } from 'contrac import { ContractType } from 'contracts/types' import isNumber from 'lodash/isNumber' import { useCallback, useMemo } from 'react' -import { type Address, encodeFunctionData, getAddress } from 'viem' +import type { Address } from 'viem' +import { encodeFunctionData, getAddress } from 'viem' import { useWallet } from 'hooks/useWallet/useWallet' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { fromBaseUnit, toBaseUnit } from 'lib/math' @@ -148,7 +149,7 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidityETH', args: [ - getAddress(otherAssetContractAddress), + otherAssetContractAddress, BigInt(toBaseUnit(otherAssetAmount, otherAsset.precision)), BigInt(amountOtherAssetMin), BigInt(amountEthMin), @@ -165,8 +166,8 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidity', args: [ - getAddress(asset0ContractAddress), - getAddress(asset1ContractAddress), + asset0ContractAddress, + asset1ContractAddress, BigInt(toBaseUnit(token0Amount, asset0.precision)), BigInt(toBaseUnit(token1Amount, asset1.precision)), BigInt(amountAsset0Min), @@ -243,8 +244,8 @@ export const useUniV2LiquidityPool = ({ asset1Amount, asset0Amount, }: { - asset0ContractAddress: string - asset1ContractAddress: string + asset0ContractAddress: Address + asset1ContractAddress: Address lpAmount: string asset1Amount: string asset0Amount: string @@ -255,9 +256,8 @@ export const useUniV2LiquidityPool = ({ const to = getAddress(fromAccountId(accountId).account) if ([assetId0OrWeth, assetId1OrWeth].includes(wethAssetId)) { - const otherAssetContractAddress = getAddress( - assetId0OrWeth === wethAssetId ? asset1ContractAddress : asset0ContractAddress, - ) + const otherAssetContractAddress = + assetId0OrWeth === wethAssetId ? asset1ContractAddress : asset0ContractAddress const otherAsset = assetId0OrWeth === wethAssetId ? asset1 : asset0 const ethAmount = assetId0OrWeth === wethAssetId ? asset0Amount : asset1Amount const otherAssetAmount = assetId0OrWeth === wethAssetId ? asset1Amount : asset0Amount @@ -281,8 +281,8 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'removeLiquidity', args: [ - getAddress(asset0ContractAddress), - getAddress(asset1ContractAddress), + asset0ContractAddress, + asset1ContractAddress, BigInt(toBaseUnit(lpAmount, lpAsset.precision)), BigInt(calculateSlippageMargin(asset0Amount, asset0.precision)), BigInt(calculateSlippageMargin(asset1Amount, asset1.precision)), @@ -493,7 +493,7 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidityETH', args: [ - getAddress(otherAssetContractAddress), + otherAssetContractAddress, BigInt(toBaseUnit(otherAssetAmount, otherAsset.precision)), BigInt(amountOtherAssetMin), BigInt(amountEthMin), @@ -518,8 +518,8 @@ export const useUniV2LiquidityPool = ({ abi: uniswapRouterContract.abi, functionName: 'addLiquidity', args: [ - getAddress(asset0ContractAddress), - getAddress(asset1ContractAddress), + asset0ContractAddress, + asset1ContractAddress, BigInt(toBaseUnit(token0Amount, asset0.precision)), BigInt(toBaseUnit(token1Amount, asset1.precision)), BigInt(amountAsset0Min), From dfc95115666cb26696ede90d970cdd20159a022a Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:19:56 -0700 Subject: [PATCH 51/60] static provider --- src/lib/ethersProviderSingleton.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/ethersProviderSingleton.ts b/src/lib/ethersProviderSingleton.ts index a1f43e3dfd2..086d435b45b 100644 --- a/src/lib/ethersProviderSingleton.ts +++ b/src/lib/ethersProviderSingleton.ts @@ -37,7 +37,9 @@ export const getEthersProvider = ( chainId: EvmChainId = KnownChainIds.EthereumMainnet, ): JsonRpcProvider => { if (!ethersProviders.has(chainId)) { - const provider = new JsonRpcProvider(rpcUrlByChainId(chainId)) + const provider = new JsonRpcProvider(rpcUrlByChainId(chainId), undefined, { + staticNetwork: true, + }) ethersProviders.set(chainId, provider) return provider } else { From ba37703797bdcae396cdac8a1732bdd1088b9e68 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:39:29 -0700 Subject: [PATCH 52/60] mock works now --- .../getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts | 2 -- .../swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts b/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts index 3b8dd0a578a..e25fac85020 100644 --- a/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts +++ b/src/lib/swapper/swappers/CowSwapper/getCowSwapTradeQuote/getCowSwapTradeQuote.test.ts @@ -25,8 +25,6 @@ const mocks = vi.hoisted(() => ({ post: vi.fn(), })) -vi.unmock('ethers') - vi.mock('../utils/cowService', () => { const mockAxios = { default: { diff --git a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts index 0a76a4846f8..f80b30c8fc9 100644 --- a/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts +++ b/src/lib/swapper/swappers/CowSwapper/utils/helpers/helpers.test.ts @@ -14,8 +14,6 @@ vi.mock('../cowService', async () => { } }) -vi.unmock('ethers') - describe('utils', () => { describe('getNowPlusThirtyMinutesTimestamp', () => { const mockDay = '2020-12-31' From 1ed5765ef960beddf5fd1e732600d3f371e37ea9 Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:39:42 -0700 Subject: [PATCH 53/60] use viem cleanup --- src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx | 1 - src/plugins/walletConnectToDapps/utils.ts | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx index 7ac06bc5d02..6b8bb78651c 100644 --- a/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx +++ b/src/plugins/walletConnectToDapps/hooks/useGetAbi.tsx @@ -49,7 +49,6 @@ export const useGetAbi = (transactionParams: TransactionParams): ethers.Interfac // check for proxy methods on the root interface let proxyFunctionNameIfExists: string | undefined if (rootContractInterface) { - // TODO(gomes): how to do this with v6? looks like we should probably map over fragments, and then map over functions const rootFunctions = rootContractInterface.fragments.filter(Fragment.isFunction) proxyFunctionNameIfExists = Object.values(PROXY_CONTRACT_METHOD_NAME).find(x => rootFunctions.find(y => y.name === x), diff --git a/src/plugins/walletConnectToDapps/utils.ts b/src/plugins/walletConnectToDapps/utils.ts index f903daa9e38..19dc680ff80 100644 --- a/src/plugins/walletConnectToDapps/utils.ts +++ b/src/plugins/walletConnectToDapps/utils.ts @@ -8,7 +8,6 @@ import type { GetFeeDataInput, } from '@shapeshiftoss/chain-adapters' import type { SessionTypes } from '@walletconnect/types' -import { toBeHex, toUtf8String } from 'ethers' import type { ConfirmData, CosmosSignAminoCallRequestParams, @@ -18,7 +17,7 @@ import type { TransactionParams, WalletConnectState, } from 'plugins/walletConnectToDapps/types' -import { isAddress, isHex } from 'viem' +import { hexToString, isAddress, isHex, toHex } from 'viem' import { bnOrZero } from 'lib/bignumber/bignumber' import { isSome } from 'lib/utils' @@ -27,7 +26,7 @@ import { isSome } from 'lib/utils' */ export const maybeConvertHexEncodedMessageToUtf8 = (value: string) => { try { - return isHex(value) ? toUtf8String(value) : value + return isHex(value) ? hexToString(value) : value } catch (e) { // use raw hex string if unable to convert to utf8 (ex. keccak256) return value @@ -35,7 +34,7 @@ export const maybeConvertHexEncodedMessageToUtf8 = (value: string) => { } export const convertNumberToHex = (value: number | string): string => - typeof value === 'number' ? toBeHex(value) : toBeHex(parseInt(value)) + typeof value === 'number' ? toHex(value) : toHex(parseInt(value)) export const convertHexToNumber = (value: string): number => parseInt(value, 16) From 772b1adf14fd9bab7d0e08e9f56c83da3d51668d Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:01:37 -0700 Subject: [PATCH 54/60] final ethers -> viem updates --- .../src/evm/bnbsmartchain/parser/abi/bep20.ts | 4 ++-- .../src/evm/ethereum/parser/abi/foxyStaking.ts | 4 ++-- .../src/evm/ethereum/parser/abi/shapeShiftRouter.ts | 4 ++-- .../src/evm/ethereum/parser/abi/thorAvalanche.ts | 4 ++-- .../src/evm/ethereum/parser/abi/thorEthereum.ts | 4 ++-- .../src/evm/ethereum/parser/abi/uniV2.ts | 4 ++-- .../src/evm/ethereum/parser/abi/uniV2StakingRewards.ts | 4 ++-- .../src/evm/ethereum/parser/abi/weth.ts | 4 ++-- .../src/evm/ethereum/parser/abi/yearnVault.ts | 4 ++-- packages/unchained-client/src/evm/parser/abi/erc20.ts | 4 ++-- src/components/TransactionHistoryRows/utils.test.ts | 4 ++-- src/components/TransactionHistoryRows/utils.ts | 4 ++-- .../defi/providers/fox-farming/hooks/useFoxFarming.ts | 7 +++---- .../Deposit/components/Deposit.tsx | 5 ++--- .../providers/univ2/hooks/useUniV2LiquidityPool.ts | 10 +++------- 15 files changed, 32 insertions(+), 38 deletions(-) diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/abi/bep20.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/abi/bep20.ts index ffc32c1a580..9e93f6130e5 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/abi/bep20.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/abi/bep20.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -const bep20: JsonFragment[] = [ +const bep20: InterfaceAbi = [ { anonymous: false, inputs: [ diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/foxyStaking.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/foxyStaking.ts index 8d972140a3d..0dbb9d480ce 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/foxyStaking.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/foxyStaking.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const FOXY_STAKING_ABI: JsonFragment[] = [ +export const FOXY_STAKING_ABI: InterfaceAbi = [ { inputs: [ { diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/shapeShiftRouter.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/shapeShiftRouter.ts index 6ca4c0c2cf2..bc07f0b3c6f 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/shapeShiftRouter.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/shapeShiftRouter.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const SHAPESHIFT_ROUTER_ABI: JsonFragment[] = [ +export const SHAPESHIFT_ROUTER_ABI: InterfaceAbi = [ { inputs: [ { diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/thorAvalanche.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/thorAvalanche.ts index 9a8ae0c8db6..e02b59678ab 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/thorAvalanche.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/thorAvalanche.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const THOR_AVALANCHE_ABI: JsonFragment[] = [ +export const THOR_AVALANCHE_ABI: InterfaceAbi = [ { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/thorEthereum.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/thorEthereum.ts index 8ddff380ae8..53845c851bb 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/thorEthereum.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/thorEthereum.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const THOR_ETHEREUM_ABI: JsonFragment[] = [ +export const THOR_ETHEREUM_ABI: InterfaceAbi = [ { inputs: [], stateMutability: 'nonpayable', type: 'constructor' }, { anonymous: false, diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2.ts index 00956eb3565..d9f917623d1 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const UNIV2_ABI: JsonFragment[] = [ +export const UNIV2_ABI: InterfaceAbi = [ { inputs: [ { internalType: 'address', name: '_factory', type: 'address' }, diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2StakingRewards.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2StakingRewards.ts index bddf6646d70..0cbce381741 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2StakingRewards.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/uniV2StakingRewards.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const UNIV2_STAKING_REWARDS_ABI: JsonFragment[] = [ +export const UNIV2_STAKING_REWARDS_ABI: InterfaceAbi = [ { inputs: [ { diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/weth.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/weth.ts index 99458c96386..7cfecdecd57 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/weth.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/weth.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const WETH_ABI: JsonFragment[] = [ +export const WETH_ABI: InterfaceAbi = [ { constant: true, inputs: [], diff --git a/packages/unchained-client/src/evm/ethereum/parser/abi/yearnVault.ts b/packages/unchained-client/src/evm/ethereum/parser/abi/yearnVault.ts index 11b333f2b9b..e2cda5b22ee 100644 --- a/packages/unchained-client/src/evm/ethereum/parser/abi/yearnVault.ts +++ b/packages/unchained-client/src/evm/ethereum/parser/abi/yearnVault.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const YEARN_VAULT_ABI: JsonFragment[] = [ +export const YEARN_VAULT_ABI: InterfaceAbi = [ { name: 'Transfer', inputs: [ diff --git a/packages/unchained-client/src/evm/parser/abi/erc20.ts b/packages/unchained-client/src/evm/parser/abi/erc20.ts index ac5981b2719..95bfb666c95 100644 --- a/packages/unchained-client/src/evm/parser/abi/erc20.ts +++ b/packages/unchained-client/src/evm/parser/abi/erc20.ts @@ -1,6 +1,6 @@ -import type { JsonFragment } from '@ethersproject/abi/lib/fragments' +import type { InterfaceAbi } from 'ethers' -export const ERC20_ABI: JsonFragment[] = [ +export const ERC20_ABI: InterfaceAbi = [ { inputs: [ { internalType: 'string', name: 'name_', type: 'string' }, diff --git a/src/components/TransactionHistoryRows/utils.test.ts b/src/components/TransactionHistoryRows/utils.test.ts index d4e07eccd40..f558192bb54 100644 --- a/src/components/TransactionHistoryRows/utils.test.ts +++ b/src/components/TransactionHistoryRows/utils.test.ts @@ -1,8 +1,8 @@ -import { MaxUint256 } from '@ethersproject/constants' import { ethChainId, foxAssetId } from '@shapeshiftoss/caip' import type { TxMetadata } from '@shapeshiftoss/chain-adapters' import type { Asset, MarketData } from '@shapeshiftoss/types' import { mockMarketData } from 'test/mocks/marketData' +import { maxUint256 } from 'viem' import { describe, expect, it } from 'vitest' import { makeAmountOrDefault } from './utils' @@ -69,7 +69,7 @@ describe('TransactionHistoryRow/utils', () => { it('can parse erc20 infinite (max solidity uint256) approvals', () => { const args = makeRestArgsTuple({ - value: MaxUint256.toString(), + value: maxUint256.toString(), marketData: foxMarketData, asset: foxAsset, parser: 'erc20', diff --git a/src/components/TransactionHistoryRows/utils.ts b/src/components/TransactionHistoryRows/utils.ts index 5cfccf71d68..61503cf8e45 100644 --- a/src/components/TransactionHistoryRows/utils.ts +++ b/src/components/TransactionHistoryRows/utils.ts @@ -1,7 +1,7 @@ -import { MaxUint256 } from '@ethersproject/constants' import type { TransferType, TxMetadata } from '@shapeshiftoss/chain-adapters' import type { Asset, MarketData } from '@shapeshiftoss/types' import { memoize } from 'lodash' +import { maxUint256 } from 'viem' import type { Transfer } from 'hooks/useTxDetails/useTxDetails' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { priceAtDate } from 'lib/charts' @@ -93,7 +93,7 @@ export const makeAmountOrDefault = ( (approvedAssetMarketData.maxSupply && bn(approvedAssetMarketData.maxSupply).gte(0) && bn(approvedAmount).gte(approvedAssetMarketData.maxSupply)) || - bn(value).isEqualTo(MaxUint256.toString()) + bn(value).isEqualTo(maxUint256.toString()) ) return `transactionRow.parser.${parser}.infinite` // We don't have market data for that asset thus can't know whether or not it's infinite diff --git a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts index 2bfb66c8dc2..c29190026ea 100644 --- a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts +++ b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts @@ -1,11 +1,10 @@ -import { MaxUint256 } from '@ethersproject/constants' import { ethAssetId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip' import { CONTRACT_INTERACTION } from '@shapeshiftoss/chain-adapters' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import { ETH_FOX_POOL_CONTRACT_ADDRESS } from 'contracts/constants' import { getOrCreateContractByAddress } from 'contracts/contractManager' import { useCallback, useMemo } from 'react' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, maxUint256 } from 'viem' import { useFoxEth } from 'context/FoxEthProvider/FoxEthProvider' import { useWallet } from 'hooks/useWallet/useWallet' import { toBaseUnit } from 'lib/math' @@ -148,7 +147,7 @@ export const useFoxFarming = ( const data = encodeFunctionData({ abi: uniV2LPContract.abi, functionName: 'approve', - args: [contractAddress, BigInt(MaxUint256.toString())], + args: [contractAddress, BigInt(maxUint256.toString())], }) return getFeesWithWallet({ @@ -232,7 +231,7 @@ export const useFoxFarming = ( const data = encodeFunctionData({ abi: uniV2LPContract.abi, functionName: 'approve', - args: [contractAddress, BigInt(MaxUint256.toString())], + args: [contractAddress, BigInt(maxUint256.toString())], }) const fees = await getApproveFees() diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Deposit.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Deposit.tsx index 58fc6c1339f..5bed0c4a2aa 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Deposit.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Deposit.tsx @@ -1,5 +1,4 @@ import { Skeleton, useToast } from '@chakra-ui/react' -import { MaxUint256 } from '@ethersproject/constants' import type { AccountId } from '@shapeshiftoss/caip' import { fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import type { FeeDataEstimate } from '@shapeshiftoss/chain-adapters' @@ -24,7 +23,7 @@ import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import type { EstimatedFeesQueryKey } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router-dom' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, maxUint256 } from 'viem' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import { Amount } from 'components/Amount/Amount' import type { StepComponentProps } from 'components/DeFi/components/Steps' @@ -489,7 +488,7 @@ export const Deposit: React.FC = ({ const data = encodeFunctionData({ abi: contract.abi, functionName: 'approve', - args: [getAddress(saversRouterContractAddress), BigInt(MaxUint256.toString())], + args: [getAddress(saversRouterContractAddress), maxUint256], }) const adapter = assertGetEvmChainAdapter(chainId) diff --git a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts index 3ceb9ef9db0..199e09314dc 100644 --- a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts +++ b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts @@ -1,4 +1,3 @@ -import { MaxUint256 } from '@ethersproject/constants' import type { AccountId, AssetId } from '@shapeshiftoss/caip' import { ethAssetId, ethChainId, fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' import { CONTRACT_INTERACTION } from '@shapeshiftoss/chain-adapters' @@ -12,7 +11,7 @@ import { ContractType } from 'contracts/types' import isNumber from 'lodash/isNumber' import { useCallback, useMemo } from 'react' import type { Address } from 'viem' -import { encodeFunctionData, getAddress } from 'viem' +import { encodeFunctionData, getAddress, maxUint256 } from 'viem' import { useWallet } from 'hooks/useWallet/useWallet' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { fromBaseUnit, toBaseUnit } from 'lib/math' @@ -451,10 +450,7 @@ export const useUniV2LiquidityPool = ({ const data = encodeFunctionData({ abi: contract.abi, functionName: 'approve', - args: [ - getAddress(fromAssetId(uniswapV2Router02AssetId).assetReference), - BigInt(MaxUint256.toString()), - ], + args: [getAddress(fromAssetId(uniswapV2Router02AssetId).assetReference), maxUint256], }) return getFeesWithWallet({ @@ -605,7 +601,7 @@ export const useUniV2LiquidityPool = ({ const data = encodeFunctionData({ abi: contract.abi, functionName: 'approve', - args: [uniV2ContractAddress, BigInt(MaxUint256.toString())], + args: [uniV2ContractAddress, maxUint256], }) const fees = await getApproveFees(contractAddress) From e40efe1210af380f28992dc6dfd9871ce2a8358a Mon Sep 17 00:00:00 2001 From: kaladinlight <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:31:47 -0700 Subject: [PATCH 55/60] update yarn lock --- yarn.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index a92b42a9ca5..6dceb1f3712 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9951,7 +9951,6 @@ __metadata: "@openapitools/openapi-generator-cli": ^2.5.1 "@shapeshiftoss/caip": "workspace:^" "@shapeshiftoss/common-api": ^9.3.0 - ethers: ^6.11.1 isomorphic-ws: ^4.0.1 ws: ^8.3.0 languageName: unknown From 009a04ae5acbf0eed5710ef7c90dfa8fa6708128 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:00:37 -0700 Subject: [PATCH 56/60] feat: toHex from string without intermediary bytes --- src/components/Layout/Header/NavBar/Notifications.tsx | 2 +- .../ThorchainSaversManager/Deposit/components/Confirm.tsx | 8 ++------ .../Lending/Pool/components/Borrow/BorrowConfirm.tsx | 2 +- src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx | 4 ++-- src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index 83496753202..e8ca27b564e 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -92,7 +92,7 @@ export const Notifications = memo(() => { try { const signedMsg = await wallet.ethSignMessage({ addressNList, - message: toHex(stringToBytes(message)), + message: toHex(message), }) return signedMsg?.signature diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index ae4ef606328..0aa3b706dd7 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -256,9 +256,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { assetId, from: maybeFromUTXOAccountAddress, to: quote.inbound_address, - memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toHex(stringToBytes(memoUtf8)) - : memoUtf8, + memo: supportedEvmChainIds.includes(chainId as KnownChainIds) ? toHex(memoUtf8) : memoUtf8, sendMax: Boolean(!isUtxoChainId(chainId) && state?.deposit.sendMax), accountId, contractAddress: tokenOrUndefined(fromAssetId(asset.assetId).assetReference), @@ -475,9 +473,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { from: maybeFromUTXOAccountAddress, sendMax: Boolean(state?.deposit.sendMax), accountId, - memo: supportedEvmChainIds.includes(chainId as KnownChainIds) - ? toHex(stringToBytes(memoUtf8)) - : memoUtf8, + memo: supportedEvmChainIds.includes(chainId as KnownChainIds) ? toHex(memoUtf8) : memoUtf8, amountFieldError: '', estimatedFees, feeType: FeeDataKey.Fast, diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx index 4867b875c27..ba6f56fc77e 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx @@ -299,7 +299,7 @@ export const BorrowConfirm = ({ sendMax: false, accountId: collateralAccountId, memo: supportedEvmChainIds.includes(fromAssetId(collateralAssetId).chainId as KnownChainIds) - ? toHex(stringToBytes(confirmedQuote.quoteMemo)) + ? toHex(confirmedQuote.quoteMemo) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index 63385d3be3f..05a971b1173 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -290,7 +290,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset.assetId).chainId as KnownChainIds, ) - ? toHex(stringToBytes(confirmedQuote.quoteMemo)) + ? toHex(confirmedQuote.quoteMemo) : confirmedQuote.quoteMemo, to: confirmedQuote.quoteInboundAddress, sendMax: false, @@ -342,7 +342,7 @@ export const RepayConfirm = ({ memo: supportedEvmChainIds.includes( fromAssetId(repaymentAsset?.assetId).chainId as KnownChainIds, ) - ? toHex(stringToBytes(confirmedQuote.quoteMemo)) + ? toHex(confirmedQuote.quoteMemo) : confirmedQuote.quoteMemo, amountFieldError: '', estimatedFees, diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 919a9212ce5..974a7142bb0 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -89,7 +89,7 @@ export const useQuoteEstimatedFeesQuery = ({ confirmedQuote && 'quoteMemo' in confirmedQuote ? confirmedQuote.quoteMemo : '' const memo = assetId && supportedEvmChainIds.includes(fromAssetId(assetId).chainId as KnownChainIds) - ? toHex(stringToBytes(quoteMemo)) + ? toHex(quoteMemo) : quoteMemo const to = confirmedQuote && 'quoteInboundAddress' in confirmedQuote From fbb0f62ee7a40b9cdc5e67b4bab5135af9b91345 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:08:18 -0700 Subject: [PATCH 57/60] feat: big brain no-useless-cast --- .../defi/providers/fox-farming/hooks/useFoxFarming.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts index c29190026ea..d3e705fa398 100644 --- a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts +++ b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts @@ -147,7 +147,7 @@ export const useFoxFarming = ( const data = encodeFunctionData({ abi: uniV2LPContract.abi, functionName: 'approve', - args: [contractAddress, BigInt(maxUint256.toString())], + args: [contractAddress, maxUint256], }) return getFeesWithWallet({ @@ -231,7 +231,7 @@ export const useFoxFarming = ( const data = encodeFunctionData({ abi: uniV2LPContract.abi, functionName: 'approve', - args: [contractAddress, BigInt(maxUint256.toString())], + args: [contractAddress, maxUint256], }) const fees = await getApproveFees() From 48323359c2944cf965684d204408985a10b8c368 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:11:03 -0700 Subject: [PATCH 58/60] feat: 0n shorthand without BigInt constructor --- packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts | 2 +- packages/unchained-client/src/evm/parser/erc20.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts index 136d0e8f43d..0b6ca29a340 100644 --- a/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts +++ b/packages/unchained-client/src/evm/bnbsmartchain/parser/bep20.ts @@ -59,7 +59,7 @@ export class Parser implements SubParser { case this.supportedFunctions.approveSigHash: { const amount = decoded.args.amount as BigInt const value = amount.toString() - if (amount === BigInt(0)) { + if (amount === 0n) { return await Promise.resolve({ data: { ...data, method: 'revoke', value } }) } return await Promise.resolve({ data: { ...data, value } }) diff --git a/packages/unchained-client/src/evm/parser/erc20.ts b/packages/unchained-client/src/evm/parser/erc20.ts index 710f48d593c..f0c575061ab 100644 --- a/packages/unchained-client/src/evm/parser/erc20.ts +++ b/packages/unchained-client/src/evm/parser/erc20.ts @@ -59,7 +59,7 @@ export class Parser implements SubParser { case this.supportedFunctions.approveSigHash: { const amount = decoded.args.amount as BigInt const value = amount.toString() - if (amount === BigInt(0)) { + if (amount === 0n) { return await Promise.resolve({ data: { ...data, method: 'revoke', value } }) } return await Promise.resolve({ data: { ...data, value: value.toString() } }) From 576b69ac3476a3837df2a32b892a85604493e9c6 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:12:05 -0700 Subject: [PATCH 59/60] feat: no-useless-getAddress on zeroAddress --- .../ThorchainSaversManager/Withdraw/components/Confirm.tsx | 2 +- .../ThorchainSaversManager/Withdraw/components/Withdraw.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx index 6aaebf947ea..41e584dc2ae 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Confirm.tsx @@ -414,7 +414,7 @@ export const Confirm: React.FC = ({ accountId, onNext }) => { getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - getAddress(zeroAddress), + zeroAddress, BigInt(amount), quote.memo, BigInt(quote.expiry), diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx index 6b0248ce5df..c65fe541750 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Withdraw/components/Withdraw.tsx @@ -273,7 +273,7 @@ export const Withdraw: React.FC = ({ accountId, fromAddress, onNe getAddress(quote.inbound_address), // This looks incorrect according to https://dev.thorchain.org/thorchain-dev/concepts/sending-transactions#evm-chains // But this is how THORSwap does it, and it actually works - using the actual asset address as "asset" will result in reverts - getAddress(zeroAddress), + zeroAddress, BigInt(amountCryptoBaseUnit), quote.memo, BigInt(quote.expiry), From c5010e1d2542fb858288ea36c715cfc22daceb73 Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Mon, 26 Feb 2024 08:16:42 -0700 Subject: [PATCH 60/60] fix: lint --- src/components/Layout/Header/NavBar/Notifications.tsx | 2 +- .../ThorchainSaversManager/Deposit/components/Confirm.tsx | 2 +- src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx | 2 +- src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx | 2 +- src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Layout/Header/NavBar/Notifications.tsx b/src/components/Layout/Header/NavBar/Notifications.tsx index e8ca27b564e..b4ccf4dd58f 100644 --- a/src/components/Layout/Header/NavBar/Notifications.tsx +++ b/src/components/Layout/Header/NavBar/Notifications.tsx @@ -5,7 +5,7 @@ import type { CustomTheme, ThemeMode as ThemeModeType } from '@wherever/react-no import { getConfig } from 'config' import { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' -import { stringToBytes, toHex } from 'viem' +import { toHex } from 'viem' import { KeyManager } from 'context/WalletProvider/KeyManager' import { useFeatureFlag } from 'hooks/useFeatureFlag/useFeatureFlag' import { useWallet } from 'hooks/useWallet/useWallet' diff --git a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx index 0aa3b706dd7..84bd1062439 100644 --- a/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx +++ b/src/features/defi/providers/thorchain-savers/components/ThorchainSaversManager/Deposit/components/Confirm.tsx @@ -28,7 +28,7 @@ import { DefiStep } from 'features/defi/contexts/DefiManagerProvider/DefiCommon' import { useCallback, useContext, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useIsTradingActive } from 'react-queries/hooks/useIsTradingActive' -import { encodeFunctionData, getAddress, stringToBytes, toHex } from 'viem' +import { encodeFunctionData, getAddress, toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetIcon } from 'components/AssetIcon' import type { StepComponentProps } from 'components/DeFi/components/Steps' diff --git a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx index ba6f56fc77e..1b886684d02 100644 --- a/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx +++ b/src/pages/Lending/Pool/components/Borrow/BorrowConfirm.tsx @@ -26,7 +26,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' -import { stringToBytes, toHex } from 'viem' +import { toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index 05a971b1173..bf5113de1d6 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -28,7 +28,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useTranslate } from 'react-polyglot' import { useQuoteEstimatedFeesQuery } from 'react-queries/hooks/useQuoteEstimatedFeesQuery' import { useHistory } from 'react-router' -import { stringToBytes, toHex } from 'viem' +import { toHex } from 'viem' import { Amount } from 'components/Amount/Amount' import { AssetToAsset } from 'components/AssetToAsset/AssetToAsset' import { HelperTooltip } from 'components/HelperTooltip/HelperTooltip' diff --git a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts index 974a7142bb0..be1346ac31d 100644 --- a/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts +++ b/src/react-queries/hooks/useQuoteEstimatedFeesQuery.ts @@ -2,7 +2,7 @@ import { type AccountId, type AssetId, fromAssetId } from '@shapeshiftoss/caip' import type { Asset, KnownChainIds, MarketData } from '@shapeshiftoss/types' import { useQuery } from '@tanstack/react-query' import { useMemo } from 'react' -import { stringToBytes, toHex } from 'viem' +import { toHex } from 'viem' import type { EstimateFeesInput } from 'components/Modals/Send/utils' import { estimateFees } from 'components/Modals/Send/utils' import { bn, bnOrZero } from 'lib/bignumber/bignumber'