From f35c04d7313b18df76f5c7a349ed442118289bea Mon Sep 17 00:00:00 2001 From: gomes <17035424+gomesalexandre@users.noreply.github.com> Date: Tue, 12 Dec 2023 01:02:49 +0400 Subject: [PATCH 1/6] feat: turn thorchain lending on (#5827) --- .env.base | 2 +- .env.dev | 1 - .env.develop | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.env.base b/.env.base index 8c70a3e0e55..0b8119760c5 100644 --- a/.env.base +++ b/.env.base @@ -26,7 +26,7 @@ REACT_APP_FEATURE_ADVANCED_SLIPPAGE=true REACT_APP_FEATURE_LEDGER_WALLET=true REACT_APP_FEATURE_WALLET_CONNECT_V2=true REACT_APP_FEATURE_FOX_DISCOUNTS=true -REACT_APP_FEATURE_THORCHAIN_LENDING=false +REACT_APP_FEATURE_THORCHAIN_LENDING=true REACT_APP_FEATURE_MULTI_HOP_TRADES=false REACT_APP_FEATURE_THORCHAINSWAP_LONGTAIL=false diff --git a/.env.dev b/.env.dev index df62d32f3e7..1f1557ec580 100644 --- a/.env.dev +++ b/.env.dev @@ -1,5 +1,4 @@ # feature flags -REACT_APP_FEATURE_THORCHAIN_LENDING=true REACT_APP_FEATURE_ARBITRUM_NOVA=true # logging diff --git a/.env.develop b/.env.develop index 57429b0930f..86d24afdd5a 100644 --- a/.env.develop +++ b/.env.develop @@ -1,6 +1,5 @@ # feature flags REACT_APP_FEATURE_CHATWOOT=true -REACT_APP_FEATURE_THORCHAIN_LENDING=true REACT_APP_FEATURE_ARBITRUM_NOVA=true # mixpanel From 5fc4742416e5228039c572d42c8ed3992f94a32d Mon Sep 17 00:00:00 2001 From: reallybeard <89934888+reallybeard@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:26:46 -0600 Subject: [PATCH 2/6] fix: show full date stamp on tx (#5831) * Update TransactionGenericRow.tsx * Update TransactionGenericRow.tsx * Update TransactionGenericRow.tsx --- .../TransactionHistoryRows/TransactionGenericRow.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/TransactionHistoryRows/TransactionGenericRow.tsx b/src/components/TransactionHistoryRows/TransactionGenericRow.tsx index 0706501caf9..f8f3ddad9e8 100644 --- a/src/components/TransactionHistoryRows/TransactionGenericRow.tsx +++ b/src/components/TransactionHistoryRows/TransactionGenericRow.tsx @@ -29,17 +29,16 @@ const stackDivider = ( ) +const dateFormat = 'L LT' export const GetTxLayoutFormats = ({ parentWidth }: { parentWidth: number }) => { const isLargerThanSm = parentWidth > parseInt(breakpoints['sm'], 10) const isLargerThanMd = parentWidth > parseInt(breakpoints['md'], 10) const isLargerThanLg = parentWidth > parseInt(breakpoints['lg'], 10) let columns = '1fr' - let dateFormat = 'L LT' if (isLargerThanSm) { columns = '1fr 2fr' - dateFormat = 'LT' } if (isLargerThanMd) { columns = '1fr 2fr' From cb0eb71a47ecd55df33c38cb8a5559bd79228d69 Mon Sep 17 00:00:00 2001 From: woody <125113430+woodenfurniture@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:35:39 +1100 Subject: [PATCH 3/6] chore: cleanup unknown double assertions relating to chain adapters (#5833) * chore: cleanup unknown double assertions relating to chain adapters * fix: tests * fix: remove un-needed double assertion --- packages/chain-adapters/src/api.ts | 4 +- src/components/AuroraBackground.tsx | 11 +++-- .../Layout/Header/NavBar/ChainMenu.tsx | 12 ++--- .../useSendDetails/useSendDetails.test.tsx | 20 ++++---- .../hooks/useSendDetails/useSendDetails.tsx | 12 ++--- src/components/Modals/Send/utils.ts | 42 +++++++--------- .../useGetTradeQuotes/getTradeQuoteArgs.ts | 12 ++--- .../hooks/useTradeExecution/helpers.ts | 16 ++----- src/components/Sweep.tsx | 7 ++- src/context/PluginProvider/PluginProvider.tsx | 2 +- .../CosmosManager/Claim/CosmosClaim.tsx | 8 +--- .../fox-farming/hooks/useFoxFarming.ts | 48 ++++++------------- .../Withdraw/components/Withdraw.tsx | 8 ++-- .../univ2/hooks/useUniV2LiquidityPool.ts | 35 ++++---------- src/lib/account/cosmosSdk.ts | 8 +--- src/lib/account/evm.ts | 9 +--- src/lib/account/utxo.ts | 8 ++-- .../utils/test-data/setupThorswapDeps.ts | 2 +- src/lib/utils/cosmosSdk.ts | 12 ++++- src/lib/utils/evm.ts | 25 +--------- src/lib/utils/index.ts | 33 +++++++++++-- src/lib/utils/thorchain/index.ts | 6 +-- .../Pool/components/Repay/RepayConfirm.tsx | 5 +- src/plugins/arbitrum/index.ts | 4 +- src/plugins/arbitrumNova/index.ts | 4 +- src/plugins/avalanche/index.tsx | 4 +- src/plugins/bitcoin/index.tsx | 4 +- src/plugins/bitcoincash/index.tsx | 4 +- src/plugins/bnbsmartchain/index.tsx | 4 +- src/plugins/cosmos/index.tsx | 4 +- src/plugins/cosmos/utils.ts | 8 +--- src/plugins/dogecoin/index.tsx | 4 +- src/plugins/ethereum/index.tsx | 4 +- src/plugins/gnosis/index.tsx | 4 +- src/plugins/litecoin/index.tsx | 4 +- src/plugins/optimism/index.tsx | 4 +- src/plugins/polygon/index.ts | 4 +- src/plugins/thorchain/index.tsx | 4 +- src/plugins/types.ts | 3 +- .../WalletConnectModalManager.tsx | 46 ++++++------------ .../hooks/useCallRequestEvmFees.ts | 19 ++++---- .../hooks/useWalletConnectState.ts | 3 -- src/state/apis/foxy/foxyApiSingleton.ts | 6 +-- .../resolvers/cosmosSdk/index.ts | 17 ++----- 44 files changed, 193 insertions(+), 310 deletions(-) diff --git a/packages/chain-adapters/src/api.ts b/packages/chain-adapters/src/api.ts index 3053fd700f9..4157004f7fb 100644 --- a/packages/chain-adapters/src/api.ts +++ b/packages/chain-adapters/src/api.ts @@ -1,5 +1,5 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' -import type { BIP44Params, UtxoAccountType } from '@shapeshiftoss/types' +import type { BIP44Params, KnownChainIds, UtxoAccountType } from '@shapeshiftoss/types' import type { Account, @@ -23,7 +23,7 @@ import type { /** * Type alias for a Map that can be used to manage instances of ChainAdapters */ -export type ChainAdapterManager = Map> +export type ChainAdapterManager = Map> export type ChainAdapter = { /** diff --git a/src/components/AuroraBackground.tsx b/src/components/AuroraBackground.tsx index c035275fe06..e0c125fea4c 100644 --- a/src/components/AuroraBackground.tsx +++ b/src/components/AuroraBackground.tsx @@ -38,7 +38,7 @@ const canvasStyle: CSSProperties = { } export const AuroraBackground: React.FC = props => { - const canvasRefB = useRef(null) + const canvasRefB = useRef(null) useEffect(() => { let center = [0, 0] @@ -47,9 +47,12 @@ export const AuroraBackground: React.FC = props => { let rayProps: Float32Array let animationFrameId: number const canvasA = document.createElement('canvas') - const canvasB: HTMLCanvasElement = canvasRefB.current as unknown as HTMLCanvasElement - const ctxA = canvasA.getContext('2d') as unknown as CanvasRenderingContext2D - const ctxB = canvasB.getContext('2d') as unknown as CanvasRenderingContext2D + const canvasB: HTMLCanvasElement | null = canvasRefB.current + const ctxA: CanvasRenderingContext2D | null = canvasA.getContext('2d') + const ctxB: CanvasRenderingContext2D | null = + canvasB !== null ? canvasB.getContext('2d') : canvasB + + if (canvasB === null || ctxA === null || ctxB === null) return const setup = () => { resize() diff --git a/src/components/Layout/Header/NavBar/ChainMenu.tsx b/src/components/Layout/Header/NavBar/ChainMenu.tsx index 02c496441f5..1d93965b347 100644 --- a/src/components/Layout/Header/NavBar/ChainMenu.tsx +++ b/src/components/Layout/Header/NavBar/ChainMenu.tsx @@ -15,7 +15,6 @@ import { } from '@chakra-ui/react' import type { ChainId } from '@shapeshiftoss/caip' import { fromChainId, gnosisChainId } from '@shapeshiftoss/caip' -import type { EvmBaseAdapter, EvmChainId } from '@shapeshiftoss/chain-adapters' import type { ETHWallet } from '@shapeshiftoss/hdwallet-core' import { supportsEthSwitchChain } from '@shapeshiftoss/hdwallet-core' import { utils } from 'ethers' @@ -26,6 +25,7 @@ import { CircleIcon } from 'components/Icons/Circle' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useEvm } from 'hooks/useEvm/useEvm' import { useWallet } from 'hooks/useWallet/useWallet' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' import { selectAssetById, selectAssets } from 'state/slices/selectors' import { useAppSelector } from 'state/store' @@ -92,13 +92,7 @@ export const ChainMenu = memo((props: ChainMenuProps) => { throw new Error(`Unsupported EVM network: ${requestedEthNetwork}`) } - const requestedChainChainAdapter = chainAdapterManager.get(requestedChainId) as unknown as - | EvmBaseAdapter - | undefined - - if (!requestedChainChainAdapter) { - throw new Error(`No chain adapter found for: ${requestedChainId}`) - } + const requestedChainChainAdapter = assertGetEvmChainAdapter(requestedChainId) const requestedChainFeeAssetId = requestedChainChainAdapter.getFeeAssetId() const requestedChainFeeAsset = assets[requestedChainFeeAssetId] @@ -128,7 +122,7 @@ export const ChainMenu = memo((props: ChainMenuProps) => { console.error(e) } }, - [assets, chainAdapterManager, getChainIdFromEthNetwork, load, setEthNetwork, state.wallet], + [assets, getChainIdFromEthNetwork, load, setEthNetwork, state.wallet], ) const currentChainNativeAssetId = useMemo( diff --git a/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.test.tsx b/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.test.tsx index 662248c8fab..a830d8a2a2c 100644 --- a/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.test.tsx +++ b/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.test.tsx @@ -1,6 +1,5 @@ import { btcAssetId, cosmosAssetId } from '@shapeshiftoss/caip' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' -import { KnownChainIds } from '@shapeshiftoss/types' import { act, renderHook, waitFor } from '@testing-library/react' import { mocked } from 'jest-mock' import type { PropsWithChildren } from 'react' @@ -8,10 +7,12 @@ import { useFormContext, useWatch } from 'react-hook-form' import { useHistory } from 'react-router-dom' import { ethereum as mockEthereum, rune as mockRune } from 'test/mocks/assets' import { TestProviders } from 'test/TestProviders' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' import { ensLookup } from 'lib/address/ens' import { fromBaseUnit } from 'lib/math' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import type { AssetBalancesById } from 'state/slices/portfolioSlice/portfolioSliceCommon' import { selectFeeAssetById, @@ -35,7 +36,9 @@ jest.mock('react-hook-form') jest.mock('react-router-dom', () => ({ useHistory: jest.fn() })) jest.mock('hooks/useWallet/useWallet') jest.mock('context/PluginProvider/PluginProvider') -jest.mock('context/PluginProvider/chainAdapterSingleton') +jest.mock('lib/utils/cosmosSdk') +jest.mock('lib/utils/evm') +jest.mock('lib/utils/utxo') jest.mock('lib/address/ens', () => ({ ensLookup: jest.fn() })) jest.mock('state/slices/selectors', () => ({ @@ -141,14 +144,11 @@ describe('useSendDetails', () => { beforeEach(() => { ;(useWallet as jest.Mock).mockImplementation(() => ({ state: { wallet: {} } })) ;(useHistory as jest.Mock).mockImplementation(() => ({ push: jest.fn() })) - ;(getChainAdapterManager as jest.Mock).mockImplementation( - () => - new Map([ - [KnownChainIds.BitcoinMainnet, mockAdapterBtc], - [KnownChainIds.CosmosMainnet, mockAdapterAtom], - [KnownChainIds.EthereumMainnet, mockAdapterEth], - ]), + ;(assertGetCosmosSdkChainAdapter as jest.Mock).mockImplementation( + () => mockAdapterAtom, ) + ;(assertGetEvmChainAdapter as jest.Mock).mockImplementation(() => mockAdapterEth) + ;(assertGetUtxoChainAdapter as jest.Mock).mockImplementation(() => mockAdapterBtc) ;(ensLookup as unknown as jest.Mock).mockImplementation(() => ({ address: '0x05A1ff0a32bc24265BCB39499d0c5D9A6cb2011c', error: false, diff --git a/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx b/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx index 5c935bf135b..5322a727e8b 100644 --- a/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx +++ b/src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx @@ -2,11 +2,9 @@ import type { ChainId } from '@shapeshiftoss/caip' import { CHAIN_NAMESPACE, fromAccountId, fromAssetId } from '@shapeshiftoss/caip' import type { CosmosSdkChainId, - EvmBaseAdapter, EvmChainId, FeeDataEstimate, GetFeeDataInput, - UtxoBaseAdapter, UtxoChainId, } from '@shapeshiftoss/chain-adapters' import { debounce } from 'lodash' @@ -19,6 +17,9 @@ import { useWallet } from 'hooks/useWallet/useWallet' import type { BigNumber } from 'lib/bignumber/bignumber' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { tokenOrUndefined } from 'lib/utils' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { selectAssetById, selectFeeAssetById, @@ -225,19 +226,18 @@ export const useSendDetails = (): UseSendDetailsReturnType => { try { const { chainId, chainNamespace, account } = fromAccountId(accountId) - const adapter = chainAdapterManager.get(chainId) - if (!adapter) throw new Error(`No adapter available for ${chainId}`) const { fastFee, adapterFees } = await (async () => { switch (chainNamespace) { case CHAIN_NAMESPACE.CosmosSdk: { + const adapter = assertGetCosmosSdkChainAdapter(chainId) const getFeeDataInput: Partial> = {} const adapterFees = await adapter.getFeeData(getFeeDataInput) const fastFee = adapterFees.fast.txFee return { adapterFees, fastFee } } case CHAIN_NAMESPACE.Evm: { - const evmAdapter = adapter as unknown as EvmBaseAdapter + const evmAdapter = assertGetEvmChainAdapter(chainId) const getFeeDataInput: GetFeeDataInput = { to, value: assetBalance, @@ -249,7 +249,7 @@ export const useSendDetails = (): UseSendDetailsReturnType => { return { adapterFees, fastFee } } case CHAIN_NAMESPACE.Utxo: { - const utxoAdapter = adapter as unknown as UtxoBaseAdapter + const utxoAdapter = assertGetUtxoChainAdapter(chainId) const getFeeDataInput: GetFeeDataInput = { to, value: assetBalance, diff --git a/src/components/Modals/Send/utils.ts b/src/components/Modals/Send/utils.ts index 1f364d2f504..80cf2db8e32 100644 --- a/src/components/Modals/Send/utils.ts +++ b/src/components/Modals/Send/utils.ts @@ -1,26 +1,23 @@ import type { AssetId, ChainId } from '@shapeshiftoss/caip' import { CHAIN_NAMESPACE, fromAccountId, fromAssetId, fromChainId } from '@shapeshiftoss/caip' import type { - ChainAdapter, - CosmosSdkBaseAdapter, CosmosSdkChainId, - EvmBaseAdapter, EvmChainId, FeeData, FeeDataEstimate, GetFeeDataInput, - UtxoBaseAdapter, UtxoChainId, } from '@shapeshiftoss/chain-adapters' import { utxoChainIds } from '@shapeshiftoss/chain-adapters' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { KnownChainIds } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { getSupportedEvmChainIds } from 'hooks/useEvm/useEvm' import { checkIsMetaMask, checkIsSnapInstalled } from 'hooks/useIsSnapInstalled/useIsSnapInstalled' import { bn, bnOrZero } from 'lib/bignumber/bignumber' -import { tokenOrUndefined } from 'lib/utils' +import { assertGetChainAdapter, tokenOrUndefined } from 'lib/utils' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { selectAssetById, selectPortfolioAccountMetadataByAccountId } from 'state/slices/selectors' import { store } from 'state/store' @@ -49,26 +46,22 @@ export const estimateFees = ({ accountId, contractAddress, }: EstimateFeesInput): Promise> => { - const chainAdapterManager = getChainAdapterManager() const { account } = fromAccountId(accountId) const state = store.getState() const asset = selectAssetById(state, assetId) if (!asset) throw new Error(`Asset not found for ${assetId}`) const value = bnOrZero(cryptoAmount).times(bn(10).exponentiatedBy(asset.precision)).toFixed(0) - const adapter = chainAdapterManager.get(asset.chainId) - if (!adapter) throw new Error(`No adapter available for ${asset.chainId}`) - const { chainNamespace } = fromChainId(asset.chainId) switch (chainNamespace) { case CHAIN_NAMESPACE.CosmosSdk: { + const adapter = assertGetCosmosSdkChainAdapter(asset.chainId) const getFeeDataInput: Partial> = {} - return (adapter as unknown as CosmosSdkBaseAdapter).getFeeData( - getFeeDataInput, - ) + return adapter.getFeeData(getFeeDataInput) } case CHAIN_NAMESPACE.Evm: { + const adapter = assertGetEvmChainAdapter(asset.chainId) const getFeeDataInput: GetFeeDataInput = { to, value, @@ -79,16 +72,17 @@ export const estimateFees = ({ }, sendMax, } - return (adapter as unknown as EvmBaseAdapter).getFeeData(getFeeDataInput) + return adapter.getFeeData(getFeeDataInput) } case CHAIN_NAMESPACE.Utxo: { + const adapter = assertGetUtxoChainAdapter(asset.chainId) const getFeeDataInput: GetFeeDataInput = { to, value, chainSpecific: { from, pubkey: account }, sendMax, } - return (adapter as unknown as UtxoBaseAdapter).getFeeData(getFeeDataInput) + return adapter.getFeeData(getFeeDataInput) } default: throw new Error(`${chainNamespace} not supported`) @@ -102,7 +96,6 @@ export const handleSend = async ({ sendInput: SendInput wallet: HDWallet }): Promise => { - const chainAdapterManager = getChainAdapterManager() const supportedEvmChainIds = getSupportedEvmChainIds() const state = store.getState() @@ -119,14 +112,11 @@ export const handleSend = async ({ throw new Error(`unsupported wallet: ${await wallet.getModel()}`) } - const adapter = chainAdapterManager.get(asset.chainId) as ChainAdapter - if (!adapter) throw new Error(`useFormSend: no adapter available for ${asset.chainId}`) - const value = bnOrZero(sendInput.cryptoAmount) .times(bn(10).exponentiatedBy(asset.precision)) .toFixed(0) - const chainId = adapter.getChainId() + const chainId = asset.chainId const { estimatedFees, feeType, to, memo, from } = sendInput @@ -153,7 +143,8 @@ export const handleSend = async ({ } const contractAddress = tokenOrUndefined(fromAssetId(asset.assetId).assetReference) const { accountNumber } = bip44Params - return await (adapter as unknown as EvmBaseAdapter).buildSendTransaction({ + const adapter = assertGetEvmChainAdapter(chainId) + return await adapter.buildSendTransaction({ to, value, wallet, @@ -178,7 +169,8 @@ export const handleSend = async ({ ) } const { accountNumber } = bip44Params - return (adapter as unknown as UtxoBaseAdapter).buildSendTransaction({ + const adapter = assertGetUtxoChainAdapter(chainId) + return adapter.buildSendTransaction({ to, value, wallet, @@ -205,7 +197,7 @@ export const handleSend = async ({ chainSpecific: { gas: fees.chainSpecific.gasLimit, fee: fees.txFee }, sendMax: sendInput.sendMax, } - + const adapter = assertGetCosmosSdkChainAdapter(chainId) return adapter.buildSendTransaction(params) } @@ -214,6 +206,8 @@ export const handleSend = async ({ const txToSign = result.txToSign + const adapter = assertGetChainAdapter(chainId) + const senderAddress = await adapter.getAddress({ accountNumber: accountMetadata.bip44Params.accountNumber, accountType: accountMetadata.accountType, diff --git a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteArgs.ts b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteArgs.ts index f79efc92ba3..649ca643668 100644 --- a/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteArgs.ts +++ b/src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteArgs.ts @@ -1,4 +1,3 @@ -import type { EvmChainAdapter, UtxoChainAdapter } from '@shapeshiftoss/chain-adapters' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' import type { GetTradeQuoteInput } from '@shapeshiftoss/swapper' @@ -9,8 +8,9 @@ import { isUtxoSwap, } from 'components/MultiHopTrade/hooks/useGetTradeQuotes/typeGuards' import type { TradeQuoteInputCommonArgs } from 'components/MultiHopTrade/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { toBaseUnit } from 'lib/math' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' export type GetTradeQuoteInputArgs = { sellAsset: Asset @@ -64,9 +64,7 @@ export const getTradeQuoteArgs = async ({ } if (isEvmSwap(sellAsset?.chainId) || isCosmosSdkSwap(sellAsset?.chainId)) { const supportsEIP1559 = supportsETH(wallet) && (await wallet.ethSupportsEIP1559()) - const sellAssetChainAdapter = getChainAdapterManager().get( - sellAsset.chainId, - ) as unknown as EvmChainAdapter + const sellAssetChainAdapter = assertGetEvmChainAdapter(sellAsset.chainId) const sendAddress = await sellAssetChainAdapter.getAddress({ accountNumber: sellAccountNumber, wallet, @@ -81,9 +79,7 @@ export const getTradeQuoteArgs = async ({ } } else if (isUtxoSwap(sellAsset?.chainId)) { if (!sellAccountType) return - const sellAssetChainAdapter = getChainAdapterManager().get( - sellAsset.chainId, - ) as unknown as UtxoChainAdapter + const sellAssetChainAdapter = assertGetUtxoChainAdapter(sellAsset.chainId) const sendAddress = await sellAssetChainAdapter.getAddress({ accountNumber: sellAccountNumber, wallet, diff --git a/src/components/MultiHopTrade/hooks/useTradeExecution/helpers.ts b/src/components/MultiHopTrade/hooks/useTradeExecution/helpers.ts index 598b2fe4751..74f063ff159 100644 --- a/src/components/MultiHopTrade/hooks/useTradeExecution/helpers.ts +++ b/src/components/MultiHopTrade/hooks/useTradeExecution/helpers.ts @@ -1,9 +1,9 @@ import type { ChainId } from '@shapeshiftoss/caip' -import type { UtxoChainAdapter } from '@shapeshiftoss/chain-adapters' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import type { FromOrXpub } from '@shapeshiftoss/swapper' import type { AccountMetadata } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' +import { assertGetChainAdapter } from 'lib/utils' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { isUtxoChainId } from 'state/slices/portfolioSlice/utils' export type WithFromOrXpubParams = { @@ -19,23 +19,17 @@ export const withFromOrXpub = { chainId, accountMetadata, wallet }: WithFromOrXpubParams, fnParams: Omit, ): Promise => { - const chainAdapterManager = getChainAdapterManager() - const adapter = chainAdapterManager.get(chainId) - if (!adapter) throw new Error(`No adapter for ChainId: ${chainId}`) - const accountNumber = accountMetadata.bip44Params.accountNumber if (isUtxoChainId(chainId)) { const accountType = accountMetadata.accountType if (!accountType) throw new Error('Account number required') - const { xpub } = await (adapter as unknown as UtxoChainAdapter).getPublicKey( - wallet, - accountNumber, - accountType, - ) + const adapter = assertGetUtxoChainAdapter(chainId) + const { xpub } = await adapter.getPublicKey(wallet, accountNumber, accountType) return wrappedFunction({ ...fnParams, xpub } as P) } else { + const adapter = assertGetChainAdapter(chainId) const from = await adapter.getAddress({ wallet, accountNumber }) return wrappedFunction({ ...fnParams, from } as P) } diff --git a/src/components/Sweep.tsx b/src/components/Sweep.tsx index 2c6c71abd13..b5f65069135 100644 --- a/src/components/Sweep.tsx +++ b/src/components/Sweep.tsx @@ -1,14 +1,13 @@ import { Box, Button, Divider, Flex, Skeleton, Stack, Text as CText } from '@chakra-ui/react' import { type AccountId, type AssetId, fromAssetId } from '@shapeshiftoss/caip' -import type { UtxoBaseAdapter, UtxoChainId } from '@shapeshiftoss/chain-adapters' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' import { useCallback, useEffect, useState } from 'react' import { useTranslate } from 'react-polyglot' import { Row } from 'components/Row/Row' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' import { fromBaseUnit } from 'lib/math' import { sleep } from 'lib/poll/poll' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { useGetEstimatedFeesQuery } from 'pages/Lending/hooks/useGetEstimatedFeesQuery' import { selectAssetById } from 'state/slices/selectors' import { useAppSelector } from 'state/store' @@ -90,7 +89,7 @@ export const Sweep = ({ } }, [accountId, assetId, estimatedFeesData, fromAddress, wallet]) - const adapter = getChainAdapterManager().get(fromAssetId(assetId).chainId) + const adapter = assertGetUtxoChainAdapter(fromAssetId(assetId).chainId) useEffect(() => { if (!adapter || !fromAddress) return @@ -99,7 +98,7 @@ export const Sweep = ({ if (!txId) return ;(async () => { await sleep(15_000) - const utxos = await (adapter as unknown as UtxoBaseAdapter).getUtxos({ + const utxos = await adapter.getUtxos({ pubkey: fromAddress, }) if (utxos.some(utxo => utxo.txid === txId)) handleSwepSeen() diff --git a/src/context/PluginProvider/PluginProvider.tsx b/src/context/PluginProvider/PluginProvider.tsx index 7de8edc722f..34da47aa585 100644 --- a/src/context/PluginProvider/PluginProvider.tsx +++ b/src/context/PluginProvider/PluginProvider.tsx @@ -59,7 +59,7 @@ export const PluginProvider = ({ children }: PluginProviderProps): JSX.Element = let pluginRoutes: Route[] = [] // newly registered will be default + what comes from plugins - const newChainAdapters: { [k in ChainId]?: () => ChainAdapter } = {} + const newChainAdapters: { [k in ChainId]?: () => ChainAdapter } = {} // register providers from each plugin for (const plugin of pluginManager.values()) { diff --git a/src/features/defi/providers/cosmos/components/CosmosManager/Claim/CosmosClaim.tsx b/src/features/defi/providers/cosmos/components/CosmosManager/Claim/CosmosClaim.tsx index a8e3d7f884b..218fc057ae4 100644 --- a/src/features/defi/providers/cosmos/components/CosmosManager/Claim/CosmosClaim.tsx +++ b/src/features/defi/providers/cosmos/components/CosmosManager/Claim/CosmosClaim.tsx @@ -1,7 +1,6 @@ import { Center, CircularProgress } from '@chakra-ui/react' import type { AccountId } from '@shapeshiftoss/caip' import { toAssetId } from '@shapeshiftoss/caip' -import type { CosmosSdkBaseAdapter, CosmosSdkChainId } from '@shapeshiftoss/chain-adapters' import { DefiModalContent } from 'features/defi/components/DefiModal/DefiModalContent' import { DefiModalHeader } from 'features/defi/components/DefiModal/DefiModalHeader' import type { @@ -15,9 +14,9 @@ import { useTranslate } from 'react-polyglot' import type { AccountDropdownProps } from 'components/AccountDropdown/AccountDropdown' import type { DefiStepProps } from 'components/DeFi/components/Steps' import { Steps } from 'components/DeFi/components/Steps' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' import { useWallet } from 'hooks/useWallet/useWallet' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' import { serializeUserStakingId, toValidatorId } from 'state/slices/opportunitiesSlice/utils' import { selectAssetById, @@ -69,10 +68,7 @@ export const CosmosClaim: React.FC = ({ try { if (!earnOpportunityData) return - const chainAdapterManager = getChainAdapterManager() - const chainAdapter = chainAdapterManager.get( - chainId, - ) as unknown as CosmosSdkBaseAdapter + const chainAdapter = assertGetCosmosSdkChainAdapter(chainId) if (!(walletState.wallet && validatorAddress && chainAdapter)) return dispatch({ type: CosmosClaimActionType.SET_OPPORTUNITY, diff --git a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts index 041a1458b8e..0de40656ba4 100644 --- a/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts +++ b/src/features/defi/providers/fox-farming/hooks/useFoxFarming.ts @@ -1,17 +1,20 @@ import { MaxUint256 } from '@ethersproject/constants' -import { ethAssetId, fromAccountId } from '@shapeshiftoss/caip' -import type { ethereum } from '@shapeshiftoss/chain-adapters' +import { ethAssetId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip' 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 { useFoxEth } from 'context/FoxEthProvider/FoxEthProvider' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' import { toBaseUnit } from 'lib/math' import { isValidAccountNumber } from 'lib/utils' -import { buildAndBroadcast, createBuildCustomTxInput, getFees } from 'lib/utils/evm' +import { + assertGetEvmChainAdapter, + buildAndBroadcast, + createBuildCustomTxInput, + getFees, +} from 'lib/utils/evm' import type { FoxEthStakingContractAddress } from 'state/slices/opportunitiesSlice/constants' import { foxEthLpAssetId } from 'state/slices/opportunitiesSlice/constants' import { selectAccountNumberByAccountId, selectAssetById } from 'state/slices/selectors' @@ -45,10 +48,7 @@ export const useFoxFarming = ( const wallet = useWallet().state.wallet - const chainAdapterManager = getChainAdapterManager() - const adapter = chainAdapterManager.get(ethAsset.chainId) as unknown as - | ethereum.ChainAdapter - | undefined + const adapter = useMemo(() => assertGetEvmChainAdapter(fromAssetId(ethAssetId).chainId), []) const foxFarmingContract = useMemo( () => getOrCreateContractByAddress(contractAddress), @@ -60,8 +60,6 @@ export const useFoxFarming = ( try { if (skip || !isValidAccountNumber(accountNumber) || !wallet) return - if (!adapter) throw new Error(`no adapter available for ${ethAsset.chainId}`) - const data = encodeFunctionData({ abi: foxFarmingContract.abi, functionName: 'stake', @@ -93,7 +91,6 @@ export const useFoxFarming = ( accountNumber, wallet, adapter, - ethAsset.chainId, foxFarmingContract.abi, lpAsset.precision, contractAddress, @@ -105,8 +102,6 @@ export const useFoxFarming = ( try { if (skip || !isValidAccountNumber(accountNumber) || !wallet) return - if (!adapter) throw new Error(`no adapter available for ${ethAsset.chainId}`) - const data = encodeFunctionData({ abi: foxFarmingContract.abi, functionName: isExiting ? 'exit' : 'withdraw', @@ -133,16 +128,7 @@ export const useFoxFarming = ( console.error(err) } }, - [ - adapter, - accountNumber, - contractAddress, - ethAsset.chainId, - foxFarmingContract, - lpAsset.precision, - wallet, - skip, - ], + [adapter, accountNumber, contractAddress, foxFarmingContract, lpAsset.precision, wallet, skip], ) const allowance = useCallback(async () => { @@ -155,7 +141,7 @@ export const useFoxFarming = ( }, [farmingAccountId, contractAddress, skip]) const getApproveFees = useCallback(() => { - if (!adapter || !isValidAccountNumber(accountNumber) || !wallet) return + if (!isValidAccountNumber(accountNumber) || !wallet) return const data = encodeFunctionData({ abi: uniV2LPContract.abi, @@ -175,7 +161,7 @@ export const useFoxFarming = ( const getStakeFees = useCallback( (lpAmount: string) => { - if (skip || !adapter || !isValidAccountNumber(accountNumber) || !wallet) return + if (skip || !isValidAccountNumber(accountNumber) || !wallet) return const data = encodeFunctionData({ abi: foxFarmingContract.abi, @@ -197,7 +183,7 @@ export const useFoxFarming = ( const getUnstakeFees = useCallback( (lpAmount: string, isExiting: boolean) => { - if (skip || !adapter || !isValidAccountNumber(accountNumber) || !wallet) return + if (skip || !isValidAccountNumber(accountNumber) || !wallet) return const data = encodeFunctionData({ abi: foxFarmingContract.abi, @@ -219,7 +205,7 @@ export const useFoxFarming = ( const getClaimFees = useCallback( async (userAddress: string) => { - if (!adapter || !userAddress || !wallet) return + if (!userAddress || !wallet) return const data = encodeFunctionData({ abi: foxFarmingContract.abi, @@ -241,8 +227,6 @@ export const useFoxFarming = ( const approve = useCallback(async () => { if (!wallet || !isValidAccountNumber(accountNumber)) return - if (!adapter) throw new Error(`no adapter available for ${ethAsset.chainId}`) - const data = encodeFunctionData({ abi: uniV2LPContract.abi, functionName: 'approve', @@ -266,13 +250,11 @@ export const useFoxFarming = ( }) return txid - }, [accountNumber, adapter, ethAsset.chainId, contractAddress, getApproveFees, wallet]) + }, [accountNumber, adapter, contractAddress, getApproveFees, wallet]) const claimRewards = useCallback(async () => { if (skip || !isValidAccountNumber(accountNumber) || !wallet) return - if (!adapter) throw new Error(`no adapter available for ${ethAsset.chainId}`) - const data = encodeFunctionData({ abi: foxFarmingContract.abi, functionName: 'getReward', @@ -294,7 +276,7 @@ export const useFoxFarming = ( }) return txid - }, [accountNumber, adapter, ethAsset.chainId, contractAddress, foxFarmingContract, skip, wallet]) + }, [accountNumber, adapter, contractAddress, foxFarmingContract, skip, wallet]) return { allowance, 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 3228a5a37b1..7e0517004a8 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 @@ -2,7 +2,7 @@ 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 { GetFeeDataInput, UtxoBaseAdapter, UtxoChainId } from '@shapeshiftoss/chain-adapters' +import type { GetFeeDataInput, UtxoChainId } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' import { Err, Ok, type Result } from '@sniptt/monads' import { useQueryClient } from '@tanstack/react-query' @@ -24,7 +24,6 @@ import type { StepComponentProps } from 'components/DeFi/components/Steps' import { Row } from 'components/Row/Row' import { Text } from 'components/Text' import type { TextPropTypes } from 'components/Text/Text' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useBrowserRouter } from 'hooks/useBrowserRouter/useBrowserRouter' import { getSupportedEvmChainIds } from 'hooks/useEvm/useEvm' import { useWallet } from 'hooks/useWallet/useWallet' @@ -43,6 +42,7 @@ import { queryFn as getThorchainSaversWithdrawQuoteQueryFn, useGetThorchainSaversWithdrawQuoteQuery, } from 'lib/utils/thorchain/hooks/useGetThorchainSaversWithdrawQuoteQuery' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import { useGetEstimatedFeesQuery } from 'pages/Lending/hooks/useGetEstimatedFeesQuery' import { useIsSweepNeededQuery } from 'pages/Lending/hooks/useIsSweepNeededQuery' import type { ThorchainSaversWithdrawQuoteResponseSuccess } from 'state/slices/opportunitiesSlice/resolvers/thorchainsavers/types' @@ -245,8 +245,6 @@ export const Withdraw: React.FC = ({ accountId, fromAddress, onNe // re-returning the outbound fee error, which should take precedence over the withdraw gas estimation one if (maybeOutboundFeeCryptoBaseUnit.isErr()) return maybeOutboundFeeCryptoBaseUnit - const chainAdapters = getChainAdapterManager() - if (isTokenWithdraw) { if (!saversRouterContractAddress) return Err(`No router contract address found for feeAsset: ${feeAsset.assetId}`) @@ -310,7 +308,7 @@ export const Withdraw: React.FC = ({ accountId, fromAddress, onNe const quote = maybeQuote.unwrap() // We're lying to Ts, this isn't always an UtxoBaseAdapter // But typing this as any chain-adapter won't narrow down its type and we'll have errors at `chainSpecific` property - const adapter = chainAdapters.get(chainId) as unknown as UtxoBaseAdapter + const adapter = assertGetUtxoChainAdapter(chainId) const getFeeDataInput: GetFeeDataInput = { to: quote.inbound_address, value: dustAmountCryptoBaseUnit, diff --git a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts index e6380005e4a..ff903724b56 100644 --- a/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts +++ b/src/features/defi/providers/univ2/hooks/useUniV2LiquidityPool.ts @@ -1,7 +1,6 @@ import { MaxUint256 } from '@ethersproject/constants' import type { AccountId, AssetId } from '@shapeshiftoss/caip' import { ethAssetId, ethChainId, fromAccountId, fromAssetId, toAssetId } from '@shapeshiftoss/caip' -import type { ethereum } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import { UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS, @@ -13,11 +12,15 @@ import { ethers } from 'ethers' import isNumber from 'lodash/isNumber' import { useCallback, useMemo } from 'react' import { type Address, encodeFunctionData, getAddress } from 'viem' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { useWallet } from 'hooks/useWallet/useWallet' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { fromBaseUnit, toBaseUnit } from 'lib/math' -import { buildAndBroadcast, createBuildCustomTxInput, getFees } from 'lib/utils/evm' +import { + assertGetEvmChainAdapter, + buildAndBroadcast, + createBuildCustomTxInput, + getFees, +} from 'lib/utils/evm' import { uniswapV2Router02AssetId } from 'state/slices/opportunitiesSlice/constants' import { selectAccountNumberByAccountId, @@ -68,10 +71,7 @@ export const useUniV2LiquidityPool = ({ const wallet = useWallet().state.wallet const asset0Price = useAppSelector(state => selectMarketDataById(state, assetId0OrWeth)).price - const chainAdapterManager = getChainAdapterManager() - const adapter = chainAdapterManager.get(ethChainId) as unknown as - | ethereum.ChainAdapter - | undefined + const adapter = useMemo(() => assertGetEvmChainAdapter(ethChainId), []) const uniswapRouterContract = useMemo( () => (skip ? null : getOrCreateContractByAddress(UNISWAP_V2_ROUTER_02_CONTRACT_ADDRESS)), @@ -196,8 +196,6 @@ export const useUniV2LiquidityPool = ({ try { if (skip || !isNumber(accountNumber) || !uniswapRouterContract || !wallet) return - if (!adapter) throw new Error(`no adapter available for ${asset0.chainId}`) - const maybeEthAmount = (() => { if (assetId0OrWeth === wethAssetId) return token0Amount if (assetId1OrWeth === wethAssetId) return token1Amount @@ -227,7 +225,6 @@ export const useUniV2LiquidityPool = ({ [ accountNumber, adapter, - asset0, assetId0OrWeth, assetId1OrWeth, makeAddLiquidityData, @@ -321,8 +318,6 @@ export const useUniV2LiquidityPool = ({ try { if (skip || !isNumber(accountNumber) || !uniswapRouterContract || !wallet) return - if (!adapter) throw new Error(`no adapter available for ${asset0.chainId}`) - const data = makeRemoveLiquidityData({ asset0ContractAddress, asset1ContractAddress, @@ -357,7 +352,6 @@ export const useUniV2LiquidityPool = ({ accountNumber, uniswapRouterContract, wallet, - asset0.chainId, makeRemoveLiquidityData, asset0ContractAddress, asset1ContractAddress, @@ -444,7 +438,7 @@ export const useUniV2LiquidityPool = ({ const getApproveFees = useCallback( (contractAddress: Address) => { - if (skip || !adapter || !isNumber(accountNumber) || !wallet) return + if (skip || !isNumber(accountNumber) || !wallet) return const contract = getOrCreateContractByType({ address: contractAddress, @@ -477,14 +471,7 @@ export const useUniV2LiquidityPool = ({ const getDepositFees = useCallback( ({ token0Amount, token1Amount }: { token0Amount: string; token1Amount: string }) => { - if ( - skip || - !adapter || - !accountId || - !isNumber(accountNumber) || - !uniswapRouterContract || - !wallet - ) + if (skip || !accountId || !isNumber(accountNumber) || !uniswapRouterContract || !wallet) return // https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02#addliquidityeth @@ -571,7 +558,7 @@ export const useUniV2LiquidityPool = ({ const getWithdrawFees = useCallback( (lpAmount: string, asset0Amount: string, asset1Amount: string) => { - if (skip || !adapter || !isNumber(accountNumber) || !uniswapRouterContract || !wallet) return + if (skip || !isNumber(accountNumber) || !uniswapRouterContract || !wallet) return const data = makeRemoveLiquidityData({ lpAmount, @@ -606,8 +593,6 @@ export const useUniV2LiquidityPool = ({ async (contractAddress: Address) => { if (skip || !wallet || !isNumber(accountNumber)) return - if (!adapter) throw new Error(`no adapter available for ${ethChainId}`) - const contract = getOrCreateContractByType({ address: contractAddress, type: ContractType.ERC20, diff --git a/src/lib/account/cosmosSdk.ts b/src/lib/account/cosmosSdk.ts index c25ce7b215b..085f761a7e1 100644 --- a/src/lib/account/cosmosSdk.ts +++ b/src/lib/account/cosmosSdk.ts @@ -1,9 +1,7 @@ import { CHAIN_REFERENCE, fromChainId, toAccountId } from '@shapeshiftoss/caip' -import type { CosmosSdkChainId } from '@shapeshiftoss/chain-adapters' -import { cosmosSdkChainIds } from '@shapeshiftoss/chain-adapters' import { supportsCosmos, supportsThorchain } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadataById } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' import type { DeriveAccountIdsAndMetadata } from './account' @@ -12,10 +10,8 @@ export const deriveCosmosSdkAccountIdsAndMetadata: DeriveAccountIdsAndMetadata = const result = await (async () => { let acc: AccountMetadataById = {} for (const chainId of chainIds) { - if (!cosmosSdkChainIds.includes(chainId as CosmosSdkChainId)) - throw new Error(`${chainId} does not exist in ${cosmosSdkChainIds}`) const { chainReference } = fromChainId(chainId) - const adapter = getChainAdapterManager().get(chainId)! + const adapter = assertGetCosmosSdkChainAdapter(chainId) if (chainReference === CHAIN_REFERENCE.CosmosHubMainnet) { if (!supportsCosmos(wallet)) continue } diff --git a/src/lib/account/evm.ts b/src/lib/account/evm.ts index e07f88fb62f..a3aeca114e5 100644 --- a/src/lib/account/evm.ts +++ b/src/lib/account/evm.ts @@ -1,6 +1,4 @@ import { CHAIN_REFERENCE, fromChainId, toAccountId } from '@shapeshiftoss/caip' -import type { EvmChainId } from '@shapeshiftoss/chain-adapters' -import { evmChainIds } from '@shapeshiftoss/chain-adapters' import { supportsArbitrum, supportsArbitrumNova, @@ -12,7 +10,7 @@ import { supportsPolygon, } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadataById } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' import type { DeriveAccountIdsAndMetadata } from './account' @@ -22,11 +20,8 @@ export const deriveEvmAccountIdsAndMetadata: DeriveAccountIdsAndMetadata = async const result = await (async () => { let acc: AccountMetadataById = {} for (const chainId of chainIds) { - if (!evmChainIds.includes(chainId as EvmChainId)) - throw new Error(`${chainId} does not exist in ${evmChainIds}`) - const { chainReference } = fromChainId(chainId) - const adapter = getChainAdapterManager().get(chainId)! + const adapter = assertGetEvmChainAdapter(chainId) if (chainReference === CHAIN_REFERENCE.EthereumMainnet) { if (!supportsETH(wallet)) continue diff --git a/src/lib/account/utxo.ts b/src/lib/account/utxo.ts index 38992cffe5f..6e9e5f5214d 100644 --- a/src/lib/account/utxo.ts +++ b/src/lib/account/utxo.ts @@ -1,5 +1,5 @@ import { toAccountId } from '@shapeshiftoss/caip' -import type { UtxoBaseAdapter, UtxoChainId } from '@shapeshiftoss/chain-adapters' +import type { UtxoChainId } from '@shapeshiftoss/chain-adapters' import { convertXpubVersion, toRootDerivationPath, @@ -10,7 +10,7 @@ import { bip32ToAddressNList, supportsBTC } from '@shapeshiftoss/hdwallet-core' import { MetaMaskShapeShiftMultiChainHDWallet } from '@shapeshiftoss/hdwallet-shapeshift-multichain' import type { AccountMetadataById } from '@shapeshiftoss/types' import { UtxoAccountType } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' +import { assertGetUtxoChainAdapter } from 'lib/utils/utxo' import type { DeriveAccountIdsAndMetadata } from './account' @@ -22,9 +22,7 @@ export const deriveUtxoAccountIdsAndMetadata: DeriveAccountIdsAndMetadata = asyn for (const chainId of chainIds) { if (!utxoChainIds.includes(chainId as UtxoChainId)) throw new Error(`${chainId} does not exist in ${utxoChainIds}`) - const adapter = getChainAdapterManager().get( - chainId, - ) as unknown as UtxoBaseAdapter + const adapter = assertGetUtxoChainAdapter(chainId) let supportedAccountTypes = adapter.getSupportedAccountTypes() if (wallet instanceof MetaMaskShapeShiftMultiChainHDWallet) { diff --git a/src/lib/swapper/swappers/ThorchainSwapper/utils/test-data/setupThorswapDeps.ts b/src/lib/swapper/swappers/ThorchainSwapper/utils/test-data/setupThorswapDeps.ts index 3661746bd83..e7971c9bdc5 100644 --- a/src/lib/swapper/swappers/ThorchainSwapper/utils/test-data/setupThorswapDeps.ts +++ b/src/lib/swapper/swappers/ThorchainSwapper/utils/test-data/setupThorswapDeps.ts @@ -38,6 +38,6 @@ export const mockChainAdapterManager: ChainAdapterManager = new Map([ }, }), ), - } as unknown as ChainAdapter<'eip155'>, + } as unknown as ChainAdapter, ], ]) diff --git a/src/lib/utils/cosmosSdk.ts b/src/lib/utils/cosmosSdk.ts index 3500999e2de..8ba0c0f7fd7 100644 --- a/src/lib/utils/cosmosSdk.ts +++ b/src/lib/utils/cosmosSdk.ts @@ -1,7 +1,11 @@ import type { ChainId } from '@shapeshiftoss/caip' -import type { CosmosSdkChainAdapter, CosmosSdkChainId } from '@shapeshiftoss/chain-adapters' +import type { + CosmosSdkChainAdapter, + CosmosSdkChainId, + thorchain, +} from '@shapeshiftoss/chain-adapters' import { cosmosSdkChainIds } from '@shapeshiftoss/chain-adapters' -import type { KnownChainIds } from '@shapeshiftoss/types' +import { KnownChainIds } from '@shapeshiftoss/types' import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' export const isCosmosSdkChainAdapter = ( @@ -24,3 +28,7 @@ export const assertGetCosmosSdkChainAdapter = ( return adapter } + +export const assertGetThorchainChainAdapter = (): thorchain.ChainAdapter => { + return assertGetCosmosSdkChainAdapter(KnownChainIds.ThorchainMainnet) as thorchain.ChainAdapter +} diff --git a/src/lib/utils/evm.ts b/src/lib/utils/evm.ts index e13972e0e9a..8d4b5067c49 100644 --- a/src/lib/utils/evm.ts +++ b/src/lib/utils/evm.ts @@ -7,13 +7,9 @@ import type { SignTx, } from '@shapeshiftoss/chain-adapters' import { evmChainIds } from '@shapeshiftoss/chain-adapters' -import type { ETHSignTx, HDWallet } from '@shapeshiftoss/hdwallet-core' +import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import { supportsETH } from '@shapeshiftoss/hdwallet-core' -import type { - EvmTransactionExecutionProps, - EvmTransactionRequest, - ExecuteTradeArgs, -} from '@shapeshiftoss/swapper' +import type { EvmTransactionExecutionProps, EvmTransactionRequest } from '@shapeshiftoss/swapper' import type { KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' import { getTxStatus } from '@shapeshiftoss/unchained-client/dist/evm' @@ -272,23 +268,6 @@ export const assertGetEvmChainAdapter = (chainId: ChainId | KnownChainIds): EvmC return adapter } -export const executeEvmTrade = ({ - txToSign, - wallet, - chainId, - senderAddress, - receiverAddress, -}: ExecuteTradeArgs) => { - const adapter = assertGetEvmChainAdapter(chainId) - return signAndBroadcast({ - adapter, - wallet, - txToSign: txToSign as ETHSignTx, - senderAddress, - receiverAddress, - }) -} - export const executeEvmTransaction = ( txToSign: EvmTransactionRequest, callbacks: EvmTransactionExecutionProps, diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index e8590a4757e..947bc953dce 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1,12 +1,13 @@ import { skipToken } from '@reduxjs/toolkit/dist/query' -import type { AssetReference } from '@shapeshiftoss/caip' -import { ASSET_REFERENCE } from '@shapeshiftoss/caip' +import type { AssetReference, ChainId, ChainNamespace } from '@shapeshiftoss/caip' +import { ASSET_REFERENCE, fromChainId } from '@shapeshiftoss/caip' +import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import type { KeepKeyHDWallet } from '@shapeshiftoss/hdwallet-keepkey' import type { KeplrHDWallet } from '@shapeshiftoss/hdwallet-keplr' import type { NativeHDWallet } from '@shapeshiftoss/hdwallet-native' import type { WalletConnectV2HDWallet } from '@shapeshiftoss/hdwallet-walletconnectv2' -import type { NestedArray } from '@shapeshiftoss/types' +import type { KnownChainIds, NestedArray } from '@shapeshiftoss/types' import type { Result } from '@sniptt/monads' import { Err, Ok } from '@sniptt/monads' import crypto from 'crypto-browserify' @@ -15,6 +16,7 @@ import difference from 'lodash/difference' import intersection from 'lodash/intersection' import isUndefined from 'lodash/isUndefined' import union from 'lodash/union' +import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' export const isKeepKeyHDWallet = (wallet: HDWallet): wallet is KeepKeyHDWallet => { return wallet.getVendor() === 'KeepKey' @@ -217,3 +219,28 @@ export const timeout = ( ), ]) } + +export const getSupportedChainIdsByChainNamespace = () => { + return Array.from(getChainAdapterManager().keys()).reduce>( + (acc, chainId) => { + const { chainNamespace } = fromChainId(chainId) + if (!acc[chainNamespace]) acc[chainNamespace] = [] + acc[chainNamespace].push(chainId) + return acc + }, + {} as Record, + ) +} + +export const assertGetChainAdapter = ( + chainId: ChainId | KnownChainIds, +): ChainAdapter => { + const chainAdapterManager = getChainAdapterManager() + const adapter = chainAdapterManager.get(chainId) + + if (adapter === undefined) { + throw Error(`chain adapter not found for chain id ${chainId}`) + } + + return adapter +} diff --git a/src/lib/utils/thorchain/index.ts b/src/lib/utils/thorchain/index.ts index d26f279137d..4a2492b77bb 100644 --- a/src/lib/utils/thorchain/index.ts +++ b/src/lib/utils/thorchain/index.ts @@ -1,6 +1,5 @@ import type { AccountId } from '@shapeshiftoss/caip' import { type AssetId, bchChainId, fromAccountId, fromAssetId } from '@shapeshiftoss/caip' -import type { UtxoBaseAdapter, UtxoChainId } from '@shapeshiftoss/chain-adapters' import type { HDWallet } from '@shapeshiftoss/hdwallet-core' import type { AccountMetadata, Asset } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' @@ -21,6 +20,7 @@ import { thorService } from 'lib/swapper/swappers/ThorchainSwapper/utils/thorSer import type { getThorchainSaversPosition } from 'state/slices/opportunitiesSlice/resolvers/thorchainsavers/utils' import { isUtxoAccountId, isUtxoChainId } from 'state/slices/portfolioSlice/utils' +import { assertGetUtxoChainAdapter } from '../utxo' import { THOR_PRECISION } from './constants' import type { getThorchainLendingPosition } from './lending' @@ -185,9 +185,7 @@ const getAccountAddressesWithBalances = async ( ): Promise<{ address: string; balance: string }[]> => { if (isUtxoAccountId(accountId)) { const { chainId, account: pubkey } = fromAccountId(accountId) - const chainAdapters = getChainAdapterManager() - const adapter = chainAdapters.get(chainId) as unknown as UtxoBaseAdapter - if (!adapter) throw new Error(`no adapter for ${chainId} not available`) + const adapter = assertGetUtxoChainAdapter(chainId) const { chainSpecific: { addresses }, diff --git a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx index ba4c4c0efee..0f1e4fd15bd 100644 --- a/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx +++ b/src/pages/Lending/Pool/components/Repay/RepayConfirm.tsx @@ -12,7 +12,7 @@ import { } from '@chakra-ui/react' import type { AccountId, AssetId } from '@shapeshiftoss/caip' import { fromAccountId, fromAssetId, thorchainAssetId } from '@shapeshiftoss/caip' -import type { FeeDataEstimate, thorchain } from '@shapeshiftoss/chain-adapters' +import type { FeeDataEstimate } from '@shapeshiftoss/chain-adapters' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' import type { Asset, KnownChainIds } from '@shapeshiftoss/types' import { TxStatus } from '@shapeshiftoss/unchained-client' @@ -37,6 +37,7 @@ import { queryClient } from 'context/QueryClientProvider/queryClient' import { getSupportedEvmChainIds } from 'hooks/useEvm/useEvm' import { useWallet } from 'hooks/useWallet/useWallet' import { bn, bnOrZero } from 'lib/bignumber/bignumber' +import { assertGetThorchainChainAdapter } from 'lib/utils/cosmosSdk' import { waitForThorchainUpdate } from 'lib/utils/thorchain' import type { LendingQuoteClose } from 'lib/utils/thorchain/lending/types' import { useLendingQuoteCloseQuery } from 'pages/Lending/hooks/useLendingCloseQuery' @@ -236,7 +237,7 @@ export const RepayConfirm = ({ return (async () => { const { account } = fromAccountId(repaymentAccountId) - const adapter = chainAdapter as unknown as thorchain.ChainAdapter + const adapter = assertGetThorchainChainAdapter() // repayment using THOR is a MsgDeposit tx const { txToSign } = await adapter.buildDepositTransaction({ diff --git a/src/plugins/arbitrum/index.ts b/src/plugins/arbitrum/index.ts index 370904ca860..4822c15d9c5 100644 --- a/src/plugins/arbitrum/index.ts +++ b/src/plugins/arbitrum/index.ts @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { arbitrum } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -34,7 +32,7 @@ export default function register(): Plugins { return new arbitrum.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_ARBITRUM_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/arbitrumNova/index.ts b/src/plugins/arbitrumNova/index.ts index af7d2552b98..61db46d087a 100644 --- a/src/plugins/arbitrumNova/index.ts +++ b/src/plugins/arbitrumNova/index.ts @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { arbitrumNova } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -34,7 +32,7 @@ export default function register(): Plugins { return new arbitrumNova.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_ARBITRUM_NOVA_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/avalanche/index.tsx b/src/plugins/avalanche/index.tsx index cf2ec972af2..f4dbeb46757 100644 --- a/src/plugins/avalanche/index.tsx +++ b/src/plugins/avalanche/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { avalanche } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -33,7 +31,7 @@ export default function register(): Plugins { return new avalanche.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_AVALANCHE_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/bitcoin/index.tsx b/src/plugins/bitcoin/index.tsx index 81fe51fb2cf..95349eb7f33 100644 --- a/src/plugins/bitcoin/index.tsx +++ b/src/plugins/bitcoin/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { bitcoin } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -31,7 +29,7 @@ export default function register(): Plugins { return new bitcoin.ChainAdapter({ providers: { http, ws }, coinName: 'Bitcoin', - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/bitcoincash/index.tsx b/src/plugins/bitcoincash/index.tsx index e5421c6042c..cee6ad35f24 100644 --- a/src/plugins/bitcoincash/index.tsx +++ b/src/plugins/bitcoincash/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { bitcoincash } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -31,7 +29,7 @@ export default function register(): Plugins { return new bitcoincash.ChainAdapter({ providers: { http, ws }, coinName: 'BitcoinCash', - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/bnbsmartchain/index.tsx b/src/plugins/bnbsmartchain/index.tsx index 616f41ad207..582c9cfe2e2 100644 --- a/src/plugins/bnbsmartchain/index.tsx +++ b/src/plugins/bnbsmartchain/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { bnbsmartchain } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -34,7 +32,7 @@ export default function register(): Plugins { return new bnbsmartchain.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_BNBSMARTCHAIN_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/cosmos/index.tsx b/src/plugins/cosmos/index.tsx index cc6777267c3..e8d5b5a3b19 100644 --- a/src/plugins/cosmos/index.tsx +++ b/src/plugins/cosmos/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { cosmos } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -33,7 +31,7 @@ export default function register(): Plugins { return new cosmos.ChainAdapter({ providers: { http, ws }, coinName: 'Cosmos', - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/cosmos/utils.ts b/src/plugins/cosmos/utils.ts index 5ee7654ad30..fa969b111b8 100644 --- a/src/plugins/cosmos/utils.ts +++ b/src/plugins/cosmos/utils.ts @@ -1,14 +1,13 @@ import { fromAssetId } from '@shapeshiftoss/caip' import type { cosmossdk, - CosmosSdkBaseAdapter, CosmosSdkChainId, FeeDataKey, GetFeeDataInput, } from '@shapeshiftoss/chain-adapters' import type { Asset } from '@shapeshiftoss/types' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bnOrZero } from 'lib/bignumber/bignumber' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' export type FeePriceValueHuman = { fiatFee: string @@ -45,10 +44,7 @@ export const getFormFees = async (asset: Asset, userCurrencyRate: string) => { }, } - const chainAdapterManager = getChainAdapterManager() - const adapter = chainAdapterManager.get( - fromAssetId(asset.assetId).chainId, - ) as unknown as CosmosSdkBaseAdapter + const adapter = assertGetCosmosSdkChainAdapter(fromAssetId(asset.assetId).chainId) const getFeeDataInput: Partial> = {} const feeData = await adapter.getFeeData(getFeeDataInput) diff --git a/src/plugins/dogecoin/index.tsx b/src/plugins/dogecoin/index.tsx index ddfb71f6292..2a193011d9c 100644 --- a/src/plugins/dogecoin/index.tsx +++ b/src/plugins/dogecoin/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { dogecoin } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -31,7 +29,7 @@ export default function register(): Plugins { return new dogecoin.ChainAdapter({ providers: { http, ws }, coinName: 'Dogecoin', - }) as unknown as ChainAdapter + }) }, ], ], diff --git a/src/plugins/ethereum/index.tsx b/src/plugins/ethereum/index.tsx index 7aa84cd05bd..ad79dd88138 100644 --- a/src/plugins/ethereum/index.tsx +++ b/src/plugins/ethereum/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { ethereum } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -33,7 +31,7 @@ export default function register(): Plugins { return new ethereum.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_ETHEREUM_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/gnosis/index.tsx b/src/plugins/gnosis/index.tsx index afa5549bf42..2f7bb9f2440 100644 --- a/src/plugins/gnosis/index.tsx +++ b/src/plugins/gnosis/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { gnosis } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -33,7 +31,7 @@ export default function register(): Plugins { return new gnosis.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_GNOSIS_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/litecoin/index.tsx b/src/plugins/litecoin/index.tsx index 31fcfbeca6c..5ebc8213788 100644 --- a/src/plugins/litecoin/index.tsx +++ b/src/plugins/litecoin/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { litecoin } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -31,7 +29,7 @@ export default function register(): Plugins { return new litecoin.ChainAdapter({ providers: { http, ws }, coinName: 'Litecoin', - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/optimism/index.tsx b/src/plugins/optimism/index.tsx index 20e2873b3b5..fb6602bc220 100644 --- a/src/plugins/optimism/index.tsx +++ b/src/plugins/optimism/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { optimism } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -34,7 +32,7 @@ export default function register(): Plugins { return new optimism.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_OPTIMISM_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/polygon/index.ts b/src/plugins/polygon/index.ts index 6fc77ad21d0..e55d201bde7 100644 --- a/src/plugins/polygon/index.ts +++ b/src/plugins/polygon/index.ts @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { polygon } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -34,7 +32,7 @@ export default function register(): Plugins { return new polygon.ChainAdapter({ providers: { http, ws }, rpcUrl: getConfig().REACT_APP_POLYGON_NODE_URL, - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/thorchain/index.tsx b/src/plugins/thorchain/index.tsx index 3e15a409833..124f885a80d 100644 --- a/src/plugins/thorchain/index.tsx +++ b/src/plugins/thorchain/index.tsx @@ -1,5 +1,3 @@ -import type { ChainId } from '@shapeshiftoss/caip' -import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' import { thorchain } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import * as unchained from '@shapeshiftoss/unchained-client' @@ -31,7 +29,7 @@ export default function register(): Plugins { return new thorchain.ChainAdapter({ providers: { http, ws }, coinName: 'Thorchain', - }) as unknown as ChainAdapter // FIXME: this is silly + }) }, ], ], diff --git a/src/plugins/types.ts b/src/plugins/types.ts index 008e70545fc..92f0fa66124 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -1,5 +1,6 @@ import type { ChainId } from '@shapeshiftoss/caip' import type { ChainAdapter } from '@shapeshiftoss/chain-adapters' +import type { KnownChainIds } from '@shapeshiftoss/types' import type { Route } from 'Routes/helpers' import type { FeatureFlags } from 'state/slices/preferencesSlice/preferencesSlice' @@ -11,7 +12,7 @@ export interface Plugin { featureFlag?: (keyof FeatureFlags)[] onLoad?: () => void providers?: { - chainAdapters?: [ChainId, () => ChainAdapter][] + chainAdapters?: [ChainId, () => ChainAdapter][] } routes?: Route[] } diff --git a/src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx b/src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx index c237cf919ae..f3cbd70c4b1 100644 --- a/src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx +++ b/src/plugins/walletConnectToDapps/WalletConnectModalManager.tsx @@ -9,12 +9,6 @@ import { VStack, } from '@chakra-ui/react' import { formatJsonRpcError } from '@json-rpc-tools/utils' -import type { - ChainAdapter, - CosmosSdkChainId, - EvmBaseAdapter, - EvmChainId, -} from '@shapeshiftoss/chain-adapters' import type { SessionTypes } from '@walletconnect/types' import { getSdkError } from '@walletconnect/utils' import { CosmosSignMessageConfirmationModal } from 'plugins/walletConnectToDapps/components/modals/CosmosSignMessageConfirmation' @@ -44,6 +38,8 @@ import { WalletConnectIcon } from 'components/Icons/WalletConnectIcon' import { Text } from 'components/Text' import { useWallet } from 'hooks/useWallet/useWallet' import { assertUnreachable } from 'lib/utils' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' type WalletConnectModalManagerProps = WalletConnectContextType @@ -79,7 +75,7 @@ export const WalletConnectModalManager: FC = ({ }) => { const { wallet, isConnected } = useWallet().state const sessionProposalRef = useRef(null) - const { chainAdapter, requestEvent, accountMetadata, accountId } = useWalletConnectState(state) + const { chainId, requestEvent, accountMetadata, accountId } = useWalletConnectState(state) const { activeModal, web3wallet } = state @@ -92,13 +88,16 @@ export const WalletConnectModalManager: FC = ({ const handleConfirmEIP155Request = useCallback( async (customTransactionData?: CustomTransactionData) => { - if (!requestEvent || !chainAdapter || !wallet || !chainAdapter || !web3wallet || !topic) + if (!requestEvent || !chainId || !wallet || !web3wallet || !topic) { return + } + + const chainAdapter = assertGetEvmChainAdapter(chainId) const response = await approveEIP155Request({ wallet, requestEvent, - chainAdapter: chainAdapter as unknown as EvmBaseAdapter, + chainAdapter, accountMetadata, customTransactionData, accountId, @@ -109,27 +108,21 @@ export const WalletConnectModalManager: FC = ({ }) handleClose() }, - [ - accountId, - accountMetadata, - chainAdapter, - handleClose, - requestEvent, - topic, - wallet, - web3wallet, - ], + [accountId, accountMetadata, chainId, handleClose, requestEvent, topic, wallet, web3wallet], ) const handleConfirmCosmosRequest = useCallback( async (customTransactionData?: CustomTransactionData) => { - if (!requestEvent || !chainAdapter || !wallet || !chainAdapter || !web3wallet || !topic) + if (!requestEvent || !chainId || !wallet || !web3wallet || !topic) { return + } + + const chainAdapter = assertGetCosmosSdkChainAdapter(chainId) const response = await approveCosmosRequest({ wallet, requestEvent, - chainAdapter: chainAdapter as ChainAdapter, + chainAdapter, accountMetadata, customTransactionData, accountId, @@ -140,16 +133,7 @@ export const WalletConnectModalManager: FC = ({ }) handleClose() }, - [ - accountId, - accountMetadata, - chainAdapter, - handleClose, - requestEvent, - topic, - wallet, - web3wallet, - ], + [accountId, accountMetadata, chainId, handleClose, requestEvent, topic, wallet, web3wallet], ) const handleRejectRequest = useCallback(async () => { diff --git a/src/plugins/walletConnectToDapps/hooks/useCallRequestEvmFees.ts b/src/plugins/walletConnectToDapps/hooks/useCallRequestEvmFees.ts index 9dad0c0ae91..ce582454b57 100644 --- a/src/plugins/walletConnectToDapps/hooks/useCallRequestEvmFees.ts +++ b/src/plugins/walletConnectToDapps/hooks/useCallRequestEvmFees.ts @@ -1,47 +1,44 @@ import { fromAccountId } from '@shapeshiftoss/caip' -import type { EvmBaseAdapter, EvmChainId } from '@shapeshiftoss/chain-adapters' import { FeeDataKey } from '@shapeshiftoss/chain-adapters' import { useWalletConnectState } from 'plugins/walletConnectToDapps/hooks/useWalletConnectState' import type { WalletConnectState } from 'plugins/walletConnectToDapps/types' import { getFeesForTx } from 'plugins/walletConnectToDapps/utils' import { useEffect, useMemo, useState } from 'react' import type { FeePrice } from 'components/Modals/Send/views/Confirm' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' +import { assertGetChainAdapter } from 'lib/utils' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' import { selectAssets, selectMarketDataById } from 'state/slices/selectors' import { useAppSelector } from 'state/store' export function useCallRequestEvmFees(state: WalletConnectState) { const [fees, setFees] = useState() const [isLoading, setIsLoading] = useState(false) - const { chainAdapter, chainId, accountId, transaction } = useWalletConnectState(state) + const { chainId, accountId, transaction } = useWalletConnectState(state) const assets = useAppSelector(selectAssets) const feeAsset = useMemo(() => { + const chainAdapter = chainId ? assertGetChainAdapter(chainId) : undefined const feeAssetId = chainAdapter?.getFeeAssetId() if (!feeAssetId) return null // TODO(Q): this shouldn't be feeAsset, get the real asset from request const feeAsset = assets[feeAssetId] if (!feeAsset) return null return feeAsset - }, [assets, chainAdapter]) + }, [assets, chainId]) const feeAssetPrice = useAppSelector(state => selectMarketDataById(state, feeAsset?.assetId ?? ''))?.price ?? '0' useEffect(() => { if (!transaction || !accountId || !chainId) return const { account: address } = fromAccountId(accountId) - const adapter = getChainAdapterManager().get(chainId) - if (!(address && chainId && feeAsset && feeAssetPrice && adapter)) return + if (!(address && chainId && feeAsset && feeAssetPrice)) return ;(async () => { + const adapter = assertGetEvmChainAdapter(chainId) setIsLoading(true) - const estimatedFees = await getFeesForTx( - transaction, - adapter as unknown as EvmBaseAdapter, - accountId, - ) + const estimatedFees = await getFeesForTx(transaction, adapter, accountId) const initialFees: FeePrice = { slow: { diff --git a/src/plugins/walletConnectToDapps/hooks/useWalletConnectState.ts b/src/plugins/walletConnectToDapps/hooks/useWalletConnectState.ts index 8d191f522b7..77f9281c04f 100644 --- a/src/plugins/walletConnectToDapps/hooks/useWalletConnectState.ts +++ b/src/plugins/walletConnectToDapps/hooks/useWalletConnectState.ts @@ -15,7 +15,6 @@ import { getWalletAddressFromEthSignParams, } from 'plugins/walletConnectToDapps/utils' import { useMemo } from 'react' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { selectPortfolioAccountMetadata } from 'state/slices/portfolioSlice/selectors' import { useAppSelector } from 'state/store' @@ -68,7 +67,6 @@ export const useWalletConnectState = (state: WalletConnectState) => { ? getSignParamsMessage(request.params, true) : undefined const method: KnownSigningMethod | undefined = requestEvent?.params.request.method - const chainAdapter = chainId && getChainAdapterManager().get(chainId) return { isInteractingWithContract, @@ -76,7 +74,6 @@ export const useWalletConnectState = (state: WalletConnectState) => { transaction, message, method, - chainAdapter, requestEvent, connectedAccounts, accountId, diff --git a/src/state/apis/foxy/foxyApiSingleton.ts b/src/state/apis/foxy/foxyApiSingleton.ts index 9b2ae5962ba..97d35bc547f 100644 --- a/src/state/apis/foxy/foxyApiSingleton.ts +++ b/src/state/apis/foxy/foxyApiSingleton.ts @@ -1,8 +1,8 @@ import type { EvmBaseAdapter } from '@shapeshiftoss/chain-adapters' import { KnownChainIds } from '@shapeshiftoss/types' import { getConfig } from 'config' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { foxyAddresses, FoxyApi } from 'lib/investor/investor-foxy' +import { assertGetEvmChainAdapter } from 'lib/utils/evm' // don't export me, access me through the getter let _foxyApi: FoxyApi | undefined = undefined @@ -14,9 +14,9 @@ export const getFoxyApi = (): FoxyApi => { if (_foxyApi) return _foxyApi const foxyApi = new FoxyApi({ - adapter: getChainAdapterManager().get( + adapter: assertGetEvmChainAdapter( KnownChainIds.EthereumMainnet, - ) as unknown as EvmBaseAdapter, + ) as EvmBaseAdapter, providerUrl: getConfig()[RPC_PROVIDER_ENV], foxyAddresses, }) diff --git a/src/state/slices/opportunitiesSlice/resolvers/cosmosSdk/index.ts b/src/state/slices/opportunitiesSlice/resolvers/cosmosSdk/index.ts index c45a14cd151..121c1c69232 100644 --- a/src/state/slices/opportunitiesSlice/resolvers/cosmosSdk/index.ts +++ b/src/state/slices/opportunitiesSlice/resolvers/cosmosSdk/index.ts @@ -1,8 +1,7 @@ import { cosmosChainId, fromAccountId } from '@shapeshiftoss/caip' -import type { CosmosSdkBaseAdapter, CosmosSdkChainId } from '@shapeshiftoss/chain-adapters' -import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton' import { bn, bnOrZero } from 'lib/bignumber/bignumber' import { isFulfilled, isRejected, isSome } from 'lib/utils' +import { assertGetCosmosSdkChainAdapter } from 'lib/utils/cosmosSdk' import type { ReduxState } from 'state/reducer' import { selectAssetById } from 'state/slices/assetsSlice/selectors' import { selectWalletAccountIds } from 'state/slices/common-selectors' @@ -32,7 +31,6 @@ export const cosmosSdkOpportunityIdsResolver = async ({ }> => { const state = reduxApi.getState() as ReduxState - const chainAdapters = getChainAdapterManager() const portfolioAccountIds = selectWalletAccountIds(state) const cosmosSdkChainIdsWhitelist = [cosmosChainId] @@ -44,9 +42,7 @@ export const cosmosSdkOpportunityIdsResolver = async ({ const cosmosSdkAccounts = await Promise.allSettled( cosmosSdkAccountIds.map(accountId => { const { account: pubKey, chainId } = fromAccountId(accountId) - const adapter = chainAdapters.get( - chainId, - ) as unknown as CosmosSdkBaseAdapter + const adapter = assertGetCosmosSdkChainAdapter(chainId) return adapter.getAccount(pubKey) }), ).then(settledAccountsPromises => @@ -85,10 +81,7 @@ export const cosmosSdkStakingOpportunitiesMetadataResolver = async ({ const { account: validatorAddress, chainId } = fromAccountId(validatorId) try { - const chainAdapters = getChainAdapterManager() - const adapter = chainAdapters.get( - chainId, - ) as unknown as CosmosSdkBaseAdapter + const adapter = assertGetCosmosSdkChainAdapter(chainId) const data = await adapter.getValidator(validatorAddress) @@ -183,8 +176,8 @@ export const cosmosSdkStakingOpportunitiesUserDataResolver = async ({ data: { byId: emptyStakingOpportunitiesUserDataByUserStakingId, type: defiType }, }) } - const chainAdapters = getChainAdapterManager() - const adapter = chainAdapters.get(chainId) as unknown as CosmosSdkBaseAdapter + + const adapter = assertGetCosmosSdkChainAdapter(chainId) const cosmosAccount = await adapter.getAccount(pubKey) const assetId = accountIdToFeeAssetId(accountId) From b6c9b8875a8b29ab2fe59011e276d98ce83a83e4 Mon Sep 17 00:00:00 2001 From: woody <125113430+woodenfurniture@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:38:52 +1100 Subject: [PATCH 4/6] fix: several multi-hop fixes and improvements (#5836) --- .../components/HopTransactionStep.tsx | 10 ++++++++-- .../MultiHopTradeConfirm/hooks/useTradeExecution.tsx | 6 +++++- src/lib/swapper/constants.ts | 2 +- src/lib/swapper/swappers/LifiSwapper/endpoints.ts | 12 +++++++++--- src/state/slices/tradeQuoteSlice/tradeQuoteSlice.ts | 8 ++++++++ src/state/slices/tradeQuoteSlice/types.ts | 1 + 6 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx index d84412457c6..0c11e671de4 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/components/HopTransactionStep.tsx @@ -1,5 +1,5 @@ import { CheckCircleIcon } from '@chakra-ui/icons' -import { Button, Card, CardBody, Link, VStack } from '@chakra-ui/react' +import { Button, Card, CardBody, Link, Tooltip, VStack } from '@chakra-ui/react' import type { SwapperName, TradeQuoteStep } from '@shapeshiftoss/swapper' import type { KnownChainIds } from '@shapeshiftoss/types' import type Polyglot from 'node-polyglot' @@ -45,7 +45,7 @@ export const HopTransactionStep = ({ const translate = useTranslate() const { - swap: { state: swapTxState, sellTxHash, buyTxHash }, + swap: { state: swapTxState, sellTxHash, buyTxHash, message }, } = useAppSelector(state => selectHopExecutionMetadata(state, hopIndex)) const isError = useMemo(() => swapTxState === TransactionExecutionState.Failed, [swapTxState]) @@ -168,6 +168,11 @@ export const HopTransactionStep = ({ {`${sellAmountCryptoFormatted}.${sellChainSymbol} -> ${buyAmountCryptoFormatted}.${buyChainSymbol}`} {isError && } + {Boolean(message) && ( + + {message} + + )} {txLink && ( @@ -178,6 +183,7 @@ export const HopTransactionStep = ({ }, [ errorTranslation, isError, + message, toCrypto, tradeQuoteStep.buyAmountBeforeFeesCryptoBaseUnit, tradeQuoteStep.buyAsset.chainId, diff --git a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx index ec8fd629840..42f4fcbda26 100644 --- a/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx +++ b/src/components/MultiHopTrade/components/MultiHopTradeConfirm/hooks/useTradeExecution.tsx @@ -61,6 +61,8 @@ export const useTradeExecution = (hopIndex: number) => { dispatch(tradeQuoteSlice.actions.setSwapTxPending({ hopIndex })) const onFail = (e: unknown) => { + const { message } = (e ?? { message: undefined }) as { message?: string } + dispatch(tradeQuoteSlice.actions.setSwapTxMessage({ hopIndex, message })) dispatch(tradeQuoteSlice.actions.setSwapTxFailed({ hopIndex })) showErrorToast(e) resolve() @@ -71,10 +73,12 @@ export const useTradeExecution = (hopIndex: number) => { execution.on(TradeExecutionEvent.SellTxHash, ({ sellTxHash }) => { dispatch(tradeQuoteSlice.actions.setSwapSellTxHash({ hopIndex, sellTxHash })) }) - execution.on(TradeExecutionEvent.Status, ({ buyTxHash }) => { + execution.on(TradeExecutionEvent.Status, ({ buyTxHash, message }) => { + dispatch(tradeQuoteSlice.actions.setSwapTxMessage({ hopIndex, message })) buyTxHash && tradeQuoteSlice.actions.setSwapBuyTxHash({ hopIndex, buyTxHash }) }) execution.on(TradeExecutionEvent.Success, () => { + dispatch(tradeQuoteSlice.actions.setSwapTxMessage({ hopIndex, message: undefined })) dispatch(tradeQuoteSlice.actions.setSwapTxComplete({ hopIndex })) resolve() }) diff --git a/src/lib/swapper/constants.ts b/src/lib/swapper/constants.ts index 46e07dd67ca..af19a2cdc0f 100644 --- a/src/lib/swapper/constants.ts +++ b/src/lib/swapper/constants.ts @@ -11,7 +11,7 @@ import { thorchainSwapper } from 'lib/swapper/swappers/ThorchainSwapper/Thorchai import { zrxApi } from 'lib/swapper/swappers/ZrxSwapper/endpoints' import { zrxSwapper } from 'lib/swapper/swappers/ZrxSwapper/ZrxSwapper' -export const QUOTE_TIMEOUT_MS = 10_000 +export const QUOTE_TIMEOUT_MS = 60_000 export const QUOTE_TIMEOUT_ERROR = makeSwapErrorRight({ message: `quote timed out after ${QUOTE_TIMEOUT_MS / 1000}s`, diff --git a/src/lib/swapper/swappers/LifiSwapper/endpoints.ts b/src/lib/swapper/swappers/LifiSwapper/endpoints.ts index 9b724596e09..205aae6198d 100644 --- a/src/lib/swapper/swappers/LifiSwapper/endpoints.ts +++ b/src/lib/swapper/swappers/LifiSwapper/endpoints.ts @@ -130,6 +130,7 @@ export const lifiApi: SwapperApi = { checkTradeStatus: async ({ quoteId, txHash, + stepIndex, }): Promise<{ status: TxStatus; buyTxHash: string | undefined; message: string | undefined }> => { const lifiRoute = tradeQuoteMetadata.get(quoteId) if (!lifiRoute) throw Error(`missing trade quote metadata for quoteId ${quoteId}`) @@ -141,14 +142,19 @@ export const lifiApi: SwapperApi = { // url: 'https://li.quest/v1/status', // }) + const { + action: { fromChainId, toChainId }, + tool, + } = lifiRoute.steps[stepIndex] + // don't use lifi sdk here because all status responses are cached, negating the usefulness of polling // i.e don't do `await getLifi().getStatus(getStatusRequest)` const url = new URL('https://li.quest/v1/status') const getStatusRequestParams: { [Key in keyof GetStatusRequest]: string } = { txHash, - bridge: lifiRoute.steps[0].tool, - fromChain: lifiRoute.fromChainId.toString(), - toChain: lifiRoute.toChainId.toString(), + bridge: tool, + fromChain: fromChainId.toString(), + toChain: toChainId.toString(), } url.search = new URLSearchParams(getStatusRequestParams).toString() const response = await fetch(url, { cache: 'no-store' }) // don't cache! diff --git a/src/state/slices/tradeQuoteSlice/tradeQuoteSlice.ts b/src/state/slices/tradeQuoteSlice/tradeQuoteSlice.ts index 36bf4a63af0..19e4f14a093 100644 --- a/src/state/slices/tradeQuoteSlice/tradeQuoteSlice.ts +++ b/src/state/slices/tradeQuoteSlice/tradeQuoteSlice.ts @@ -97,6 +97,14 @@ export const tradeQuoteSlice = createSlice({ const key = hopIndex === 0 ? 'firstHop' : 'secondHop' state.tradeExecution[key].swap.state = TransactionExecutionState.Failed }, + setSwapTxMessage: ( + state, + action: PayloadAction<{ hopIndex: number; message: string | undefined }>, + ) => { + const { hopIndex, message } = action.payload + const key = hopIndex === 0 ? 'firstHop' : 'secondHop' + state.tradeExecution[key].swap.message = message + }, setSwapTxComplete: (state, action: PayloadAction<{ hopIndex: number }>) => { const { hopIndex } = action.payload const isMultiHopTrade = diff --git a/src/state/slices/tradeQuoteSlice/types.ts b/src/state/slices/tradeQuoteSlice/types.ts index 84c95b9f19b..b5fe7006a5a 100644 --- a/src/state/slices/tradeQuoteSlice/types.ts +++ b/src/state/slices/tradeQuoteSlice/types.ts @@ -49,6 +49,7 @@ export type SwapExecutionMetadata = { sellTxHash?: string buyTxHash?: string streamingSwap?: StreamingSwapMetadata + message?: string } export type HopExecutionMetadata = { From 6d964eb767d5ba96ee6b3dc9c8083beaa628bec5 Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Tue, 12 Dec 2023 20:26:17 +1100 Subject: [PATCH 5/6] feat: add cross-account trading for 1inch (#5834) --- src/lib/swapper/swappers/OneInchSwapper/endpoints.ts | 1 + .../OneInchSwapper/getTradeQuote/getTradeQuote.ts | 1 + .../swappers/OneInchSwapper/utils/fetchOneInchSwap.ts | 8 ++++---- src/lib/swapper/swappers/OneInchSwapper/utils/types.ts | 1 + src/state/helpers.ts | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/lib/swapper/swappers/OneInchSwapper/endpoints.ts b/src/lib/swapper/swappers/OneInchSwapper/endpoints.ts index 6de09f12e1f..f11ff091504 100644 --- a/src/lib/swapper/swappers/OneInchSwapper/endpoints.ts +++ b/src/lib/swapper/swappers/OneInchSwapper/endpoints.ts @@ -53,6 +53,7 @@ export const oneInchApi: SwapperApi = { sellAmountIncludingProtocolFeesCryptoBaseUnit, sellAsset, maximumSlippageDecimalPercentage: slippageTolerancePercentageDecimal, + sendAddress: from, }) return { diff --git a/src/lib/swapper/swappers/OneInchSwapper/getTradeQuote/getTradeQuote.ts b/src/lib/swapper/swappers/OneInchSwapper/getTradeQuote/getTradeQuote.ts index 5e4420d0bd8..07a4cadca1a 100644 --- a/src/lib/swapper/swappers/OneInchSwapper/getTradeQuote/getTradeQuote.ts +++ b/src/lib/swapper/swappers/OneInchSwapper/getTradeQuote/getTradeQuote.ts @@ -52,6 +52,7 @@ export async function getTradeQuote( const params: OneInchQuoteApiInput = { fromTokenAddress: getOneInchTokenAddress(sellAsset), toTokenAddress: getOneInchTokenAddress(buyAsset), + receiver: receiveAddress, amount: sellAmountIncludingProtocolFeesCryptoBaseUnit, ...(maybeTreasuryAddress && { fee: buyTokenPercentageFee, diff --git a/src/lib/swapper/swappers/OneInchSwapper/utils/fetchOneInchSwap.ts b/src/lib/swapper/swappers/OneInchSwapper/utils/fetchOneInchSwap.ts index c2ddd8a4914..7ac14564df5 100644 --- a/src/lib/swapper/swappers/OneInchSwapper/utils/fetchOneInchSwap.ts +++ b/src/lib/swapper/swappers/OneInchSwapper/utils/fetchOneInchSwap.ts @@ -16,6 +16,7 @@ export type FetchOneInchSwapInput = { sellAmountIncludingProtocolFeesCryptoBaseUnit: string sellAsset: Asset maximumSlippageDecimalPercentage: string + sendAddress: string } export const fetchOneInchSwap = async ({ @@ -25,6 +26,7 @@ export const fetchOneInchSwap = async ({ sellAmountIncludingProtocolFeesCryptoBaseUnit, sellAsset, maximumSlippageDecimalPercentage, + sendAddress, }: FetchOneInchSwapInput) => { const apiUrl = getConfig().REACT_APP_ONE_INCH_API_URL @@ -46,10 +48,8 @@ export const fetchOneInchSwap = async ({ const params: OneInchSwapApiInput = { fromTokenAddress: getOneInchTokenAddress(sellAsset), toTokenAddress: getOneInchTokenAddress(buyAsset), - // HACK: use the receive address as the send address - // 1inch uses this to check allowance on their side - // this swapper is not cross-account so this works - fromAddress: receiveAddress, + receiver: receiveAddress, + fromAddress: sendAddress, amount: sellAmountIncludingProtocolFeesCryptoBaseUnit, slippage: maximumSlippagePercentage, allowPartialFill: false, diff --git a/src/lib/swapper/swappers/OneInchSwapper/utils/types.ts b/src/lib/swapper/swappers/OneInchSwapper/utils/types.ts index 0d39378f214..55fe2b53703 100644 --- a/src/lib/swapper/swappers/OneInchSwapper/utils/types.ts +++ b/src/lib/swapper/swappers/OneInchSwapper/utils/types.ts @@ -15,6 +15,7 @@ export type OneInchQuoteApiInput = { fromTokenAddress: string toTokenAddress: string amount: string + receiver: string fee?: number // fee as a percentage, e.g. to set a fee to 1.5%: fee=1.5, paid to the referrerAddress } diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 58b64755f12..9a84bd0d355 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -5,12 +5,12 @@ import { assertUnreachable } from '../lib/utils' export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { switch (swapperName) { case SwapperName.Thorchain: + case SwapperName.OneInch: return true // NOTE: Before enabling cross-account for LIFI and OneInch - we must pass the sending address // to the swappers up so allowance checks work. They're currently using the receive address // assuming it's the same address as the sending address. case SwapperName.LIFI: - case SwapperName.OneInch: case SwapperName.Zrx: case SwapperName.CowSwap: case SwapperName.Test: From 10fca9c25b2a41f62e493f08594a2932ee94d08c Mon Sep 17 00:00:00 2001 From: Apotheosis <0xapotheosis@gmail.com> Date: Tue, 12 Dec 2023 22:37:35 +1100 Subject: [PATCH 6/6] feat: enable lifi cross-account trades (#5835) --- .../swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts | 3 --- src/state/helpers.ts | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/lib/swapper/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts b/src/lib/swapper/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts index 1ddad399b1b..a5cda27948e 100644 --- a/src/lib/swapper/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts +++ b/src/lib/swapper/swappers/LifiSwapper/getTradeQuote/getTradeQuote.ts @@ -72,9 +72,6 @@ export async function getTradeQuote( toChainId: Number(fromChainId(buyAsset.chainId).chainReference), fromTokenAddress: getLifiEvmAssetAddress(sellAsset), toTokenAddress: getLifiEvmAssetAddress(buyAsset), - // HACK: use the receive address as the send address - // lifi's exchanges may use this to check allowance on their side - // this swapper is not cross-account so this works fromAddress: sendAddress, toAddress: receiveAddress, fromAmount: sellAmountIncludingProtocolFeesCryptoBaseUnit, diff --git a/src/state/helpers.ts b/src/state/helpers.ts index 9a84bd0d355..7c83b5184fb 100644 --- a/src/state/helpers.ts +++ b/src/state/helpers.ts @@ -5,12 +5,9 @@ import { assertUnreachable } from '../lib/utils' export const isCrossAccountTradeSupported = (swapperName: SwapperName) => { switch (swapperName) { case SwapperName.Thorchain: + case SwapperName.LIFI: case SwapperName.OneInch: return true - // NOTE: Before enabling cross-account for LIFI and OneInch - we must pass the sending address - // to the swappers up so allowance checks work. They're currently using the receive address - // assuming it's the same address as the sending address. - case SwapperName.LIFI: case SwapperName.Zrx: case SwapperName.CowSwap: case SwapperName.Test: