From 4654b18bcdb747d5bc90af93fe60a87a9b2f14d8 Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 19 Aug 2024 19:14:44 -0400 Subject: [PATCH 01/26] Switch out JSON provider for default provider to auto switch to a better network --- centrifuge-app/src/components/Root.tsx | 2 ++ centrifuge-app/src/utils/useLiquidityPools.ts | 26 ++++++++------ centrifuge-js/src/modules/liquidityPools.ts | 4 +-- centrifuge-js/src/utils/evmMulticall.ts | 6 ++-- .../WalletProvider/WalletProvider.tsx | 35 ++++++++++++++----- .../components/WalletProvider/evm/chains.ts | 5 --- 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/centrifuge-app/src/components/Root.tsx b/centrifuge-app/src/components/Root.tsx index 3d1798c806..e5183d9c22 100644 --- a/centrifuge-app/src/components/Root.tsx +++ b/centrifuge-app/src/components/Root.tsx @@ -85,6 +85,8 @@ export function Root() { showAdvancedAccounts={debugState.showAdvancedAccounts} showTestNets={debugState.showTestNets} showFinoa={debugState.showFinoa} + alchemyKey={import.meta.env.REACT_APP_ALCHEMY_KEY} + infuraKey={import.meta.env.REACT_APP_INFURA_KEY} > diff --git a/centrifuge-app/src/utils/useLiquidityPools.ts b/centrifuge-app/src/utils/useLiquidityPools.ts index e92a9477ae..58508fce01 100644 --- a/centrifuge-app/src/utils/useLiquidityPools.ts +++ b/centrifuge-app/src/utils/useLiquidityPools.ts @@ -25,17 +25,21 @@ export function useActiveDomains(poolId: string, suspense?: boolean) { ['activeDomains', poolId, routers?.length], async () => { const results = await Promise.allSettled( - routers!.map((r) => { - async function getManager() { - const rpcProvider = getProvider(r.chainId) - const manager = await cent.liquidityPools.getManagerFromRouter([r.router], { - rpcProvider, - }) - const pool = await cent.liquidityPools.getPool([r.chainId, manager, poolId], { rpcProvider }) - return [manager, pool] as const - } - return withTimeout(getManager(), 15000) - }) + routers! + // remove all goerli networks since providers don't support goerli anymore + .filter((r) => r.chainId !== 5) + .filter((r) => r.chainId !== 84531) + .map((r) => { + async function getManager() { + const rpcProvider = getProvider(r.chainId) + const manager = await cent.liquidityPools.getManagerFromRouter([r.router], { + rpcProvider, + }) + const pool = await cent.liquidityPools.getPool([r.chainId, manager, poolId], { rpcProvider }) + return [manager, pool] as const + } + return withTimeout(getManager(), 15000) + }) ) return results .map((result, i) => { diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index c5d0b34b04..9dc84f7e82 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,6 +1,6 @@ import { BigNumber } from '@ethersproject/bignumber' import { Contract, ContractInterface } from '@ethersproject/contracts' -import type { JsonRpcProvider, TransactionRequest, TransactionResponse } from '@ethersproject/providers' +import type { BaseProvider, TransactionRequest, TransactionResponse } from '@ethersproject/providers' import BN from 'bn.js' import { signERC2612Permit } from 'eth-permit' import set from 'lodash/set' @@ -16,7 +16,7 @@ const PERMIT_TYPEHASH = '0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c6 const NULL_ADDRESS = '0x0000000000000000000000000000000000000000' type EvmQueryOptions = { - rpcProvider?: JsonRpcProvider + rpcProvider?: BaseProvider } export type Permit = { diff --git a/centrifuge-js/src/utils/evmMulticall.ts b/centrifuge-js/src/utils/evmMulticall.ts index 0cb8b2e8a7..96129f7320 100644 --- a/centrifuge-js/src/utils/evmMulticall.ts +++ b/centrifuge-js/src/utils/evmMulticall.ts @@ -1,6 +1,6 @@ import { Interface } from '@ethersproject/abi' import { Contract } from '@ethersproject/contracts' -import { JsonRpcProvider } from '@ethersproject/providers' +import { BaseProvider } from '@ethersproject/providers' import set from 'lodash/set' const MULTICALL_ABI = [ @@ -25,7 +25,7 @@ const MULTICALL_ABI = [ const MULTICALL_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11' type AggregateOptions = { - rpcProvider: JsonRpcProvider + rpcProvider: BaseProvider allowFailure?: boolean } @@ -41,7 +41,7 @@ export type Call = { } const identity = (v: any) => v -const multicallContracts = new WeakMap() +const multicallContracts = new WeakMap() export async function multicall>(calls: Call[], options: AggregateOptions) { let contract = multicallContracts.get(options.rpcProvider) diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index ed32897722..8423189fbb 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -1,5 +1,5 @@ import { addressToHex, ComputedMultisig, evmToSubstrateAddress, Multisig } from '@centrifuge/centrifuge-js' -import { JsonRpcProvider } from '@ethersproject/providers' +import { BaseProvider, getDefaultProvider, Networkish } from '@ethersproject/providers' import { isWeb3Injected } from '@polkadot/extension-dapp' import { getWallets } from '@subwallet/wallet-connect/dotsama/wallets' import { Wallet } from '@subwallet/wallet-connect/types' @@ -63,7 +63,7 @@ export type WalletContextType = { selectedWallet: EvmConnectorMeta | null isSmartContractWallet: boolean selectedAddress: string | null - getProvider(chainId: number): JsonRpcProvider + getProvider(chainId: number): BaseProvider } } @@ -129,10 +129,12 @@ type WalletProviderProps = { showAdvancedAccounts?: boolean showTestNets?: boolean showFinoa?: boolean + alchemyKey?: string + infuraKey?: string } let cachedEvmConnectors: EvmConnectorMeta[] | undefined = undefined -const cachedProviders: Record = {} +const cachedProviders = new Map() export function WalletProvider({ children, @@ -148,12 +150,15 @@ export function WalletProvider({ showAdvancedAccounts, showTestNets, showFinoa, + alchemyKey, + infuraKey, }: WalletProviderProps) { if (!evmChainsProp[1]?.urls[0]) throw new Error('Mainnet should be defined in EVM Chains') const cent = useCentrifuge() const consts = useCentrifugeConsts() const centEvmChainId = useCentEvmChainId() + console.log('🚀 ~ centEvmChainId:', centEvmChainId) const evmChains = React.useMemo(() => { const centUrl = new URL(cent.parachainUrl) @@ -240,11 +245,25 @@ export function WalletProvider({ const [proxies] = useCentrifugeQuery(['allProxies'], (cent) => cent.proxies.getAllProxies()) - function getProvider(chainId: number) { - return ( - cachedProviders[chainId] || - (cachedProviders[chainId] = new JsonRpcProvider((evmChains as any)[chainId].urls[0], chainId)) - ) + function getProvider(networkish: Networkish) { + let network = networkish + if (networkish === 2090) { + network = 'https://fullnode.demo.k-f.dev/' + } + if (networkish === 84532) { + network = 'https://sepolia.base.org' + } + const cachedProvider = cachedProviders.get(network) + if (cachedProvider) { + return cachedProvider + } else { + const provider = getDefaultProvider(network, { + alchemy: alchemyKey, + infura: infuraKey, + }) + cachedProviders.set(network, provider) + return provider + } } function setFilteredAccounts(accounts: SubstrateAccount[]) { diff --git a/centrifuge-react/src/components/WalletProvider/evm/chains.ts b/centrifuge-react/src/components/WalletProvider/evm/chains.ts index 27807e43ea..ea11f502a9 100644 --- a/centrifuge-react/src/components/WalletProvider/evm/chains.ts +++ b/centrifuge-react/src/components/WalletProvider/evm/chains.ts @@ -47,11 +47,6 @@ const chainExtendedInfo = { nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }, blockExplorerUrl: 'https://etherscan.io/', }, - 5: { - name: 'Ethereum Görli', - nativeCurrency: { name: 'Görli Ether', symbol: 'görETH', decimals: 18 }, - blockExplorerUrl: 'https://goerli.etherscan.io/', - }, } export function getChainInfo(chains: EvmChains, chainId: number): ExtendedChainInformation { From d9f728a5c9f1a4936834669bb25a7a882906d5d4 Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 19 Aug 2024 19:15:05 -0400 Subject: [PATCH 02/26] Remove references to goerli --- centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx index 5d92ce4e79..7e0357dd9c 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx @@ -17,7 +17,6 @@ import { import * as React from 'react' import { useNavigate } from 'react-router-dom' import { useTheme } from 'styled-components' -import { ethConfig } from '../../config' import { formatBalance } from '../../utils/formatting' import { useAddress } from '../../utils/useAddress' import { useActiveDomains } from '../../utils/useLiquidityPools' @@ -51,7 +50,7 @@ export function InvestRedeem({ poolId, trancheId, ...rest }: InvestRedeemProps) const domainsWithAtLeastOneLP = domains && domains.filter((domain) => Object.values(domain.liquidityPools[trancheId] ?? {}).some((p) => !!p)) - const networks: Network[] = poolId.startsWith('0x') ? [ethConfig.network === 'goerli' ? 5 : 1] : ['centrifuge'] + const networks: Network[] = poolId.startsWith('0x') ? [1] : ['centrifuge'] if (domainsWithAtLeastOneLP) { networks.push(...domainsWithAtLeastOneLP.map((d) => d.chainId)) } From af8ff3c2286b55f25af7c23f50d8e6ac13b875a4 Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 20 Aug 2024 14:49:01 -0400 Subject: [PATCH 03/26] Clean up --- centrifuge-app/src/utils/useLiquidityPools.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/centrifuge-app/src/utils/useLiquidityPools.ts b/centrifuge-app/src/utils/useLiquidityPools.ts index 58508fce01..f167ac4da3 100644 --- a/centrifuge-app/src/utils/useLiquidityPools.ts +++ b/centrifuge-app/src/utils/useLiquidityPools.ts @@ -27,8 +27,7 @@ export function useActiveDomains(poolId: string, suspense?: boolean) { const results = await Promise.allSettled( routers! // remove all goerli networks since providers don't support goerli anymore - .filter((r) => r.chainId !== 5) - .filter((r) => r.chainId !== 84531) + .filter((r) => r.chainId !== 5 && r.chainId !== 84531) .map((r) => { async function getManager() { const rpcProvider = getProvider(r.chainId) From 891e249851176dfdece179d6a1ef24d848301510 Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 20 Aug 2024 15:51:17 -0400 Subject: [PATCH 04/26] Use JsonRpcProvider as fallback if defaultprovider doesn't support network --- centrifuge-app/src/config.ts | 2 +- .../src/utils/tinlake/useTinlakeBalances.ts | 4 +-- centrifuge-app/src/utils/useCFGTokenPrice.ts | 13 ++++---- .../WalletProvider/WalletProvider.tsx | 30 ++++++++++--------- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/centrifuge-app/src/config.ts b/centrifuge-app/src/config.ts index 575dd3fdb9..68f71a6b25 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -156,7 +156,7 @@ export const evmChains: EvmChains = { decimals: 18, }, blockExplorerUrl: 'https://etherscan.io/', - urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], + urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], // the urls[] is used just for external connectors iconUrl: ethereumLogo, isTestnet: false, }, diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts index 835587bcb9..c8eacf5249 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts @@ -8,7 +8,7 @@ import { } from '@centrifuge/centrifuge-js' import { useWallet } from '@centrifuge/centrifuge-react' import { BigNumber } from '@ethersproject/bignumber' -import { JsonRpcProvider } from '@ethersproject/providers' +import { BaseProvider } from '@ethersproject/providers' import { useQuery } from 'react-query' import { ethConfig } from '../../config' import { currencies } from './currencies' @@ -31,7 +31,7 @@ export function useTinlakeBalances(address?: string) { const WCFG_ADDRESS = '0xc221b7e65ffc80de234bbb6667abdd46593d34f0' -async function getBalances(pools: TinlakePool[], address: string, provider: JsonRpcProvider) { +async function getBalances(pools: TinlakePool[], address: string, provider: BaseProvider) { const calls: EvmMulticallCall[] = [] const toTokenBalance = (val: BigNumber) => new TokenBalance(val.toString(), 18) const toCurrencyBalance = (val: BigNumber) => new CurrencyBalance(val.toString(), 18) diff --git a/centrifuge-app/src/utils/useCFGTokenPrice.ts b/centrifuge-app/src/utils/useCFGTokenPrice.ts index d06f4176ef..a8aa4a1f19 100644 --- a/centrifuge-app/src/utils/useCFGTokenPrice.ts +++ b/centrifuge-app/src/utils/useCFGTokenPrice.ts @@ -1,12 +1,13 @@ -import { ethers } from 'ethers' +import { useWallet } from '@centrifuge/centrifuge-react' +import { Contract } from '@ethersproject/contracts' +import { BaseProvider } from '@ethersproject/providers' import { useQuery } from 'react-query' import { Dec } from './Decimal' -async function getWCFGPrice() { +async function getWCFGPrice(provider: BaseProvider) { const usdcWcfgPool = '0x7270233cCAE676e776a659AFfc35219e6FCfbB10' const uniswapPoolAbi = ['function observe(uint32[] secondsAgos) external view returns (int56[], uint160[])'] - const provider2 = new ethers.providers.InfuraProvider() - const poolContract = new ethers.Contract(usdcWcfgPool, uniswapPoolAbi, provider2) + const poolContract = new Contract(usdcWcfgPool, uniswapPoolAbi, provider) const observations = (await poolContract.observe([0, 1]))[0] const first = Dec(observations[0].toString()) const second = Dec(observations[1].toString()) @@ -15,7 +16,9 @@ async function getWCFGPrice() { } export const useCFGTokenPrice = () => { - const { data: CFGPrice } = useQuery('wCFGPrice', () => getWCFGPrice()) + const { getProvider } = useWallet().evm + const provider = getProvider(1) + const { data: CFGPrice } = useQuery('wCFGPrice', () => getWCFGPrice(provider)) return CFGPrice } diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index 8423189fbb..5513280b45 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -1,5 +1,5 @@ import { addressToHex, ComputedMultisig, evmToSubstrateAddress, Multisig } from '@centrifuge/centrifuge-js' -import { BaseProvider, getDefaultProvider, Networkish } from '@ethersproject/providers' +import { BaseProvider, getDefaultProvider, JsonRpcProvider, Networkish } from '@ethersproject/providers' import { isWeb3Injected } from '@polkadot/extension-dapp' import { getWallets } from '@subwallet/wallet-connect/dotsama/wallets' import { Wallet } from '@subwallet/wallet-connect/types' @@ -158,7 +158,6 @@ export function WalletProvider({ const cent = useCentrifuge() const consts = useCentrifugeConsts() const centEvmChainId = useCentEvmChainId() - console.log('🚀 ~ centEvmChainId:', centEvmChainId) const evmChains = React.useMemo(() => { const centUrl = new URL(cent.parachainUrl) @@ -247,22 +246,25 @@ export function WalletProvider({ function getProvider(networkish: Networkish) { let network = networkish - if (networkish === 2090) { - network = 'https://fullnode.demo.k-f.dev/' - } - if (networkish === 84532) { - network = 'https://sepolia.base.org' - } const cachedProvider = cachedProviders.get(network) if (cachedProvider) { return cachedProvider } else { - const provider = getDefaultProvider(network, { - alchemy: alchemyKey, - infura: infuraKey, - }) - cachedProviders.set(network, provider) - return provider + try { + const provider = getDefaultProvider(network, { + alchemy: alchemyKey, + infura: infuraKey, + }) + cachedProviders.set(network, provider) + return provider + } catch (error) { + if (typeof network === 'number') { + const provider = new JsonRpcProvider((evmChains as any)[network].urls[0], network) + cachedProviders.set(network, provider) + return provider + } + throw error + } } } From eab77863cc889f224444438d963fdbe227658286 Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 20 Aug 2024 15:51:26 -0400 Subject: [PATCH 05/26] Fix console warnings --- centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index 76a15d9ad5..cb2420a879 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -151,7 +151,12 @@ const AvailableNetworks = ({ poolId }: { poolId: string }) => { Centrifuge {pool.tranches.length > 1 ? ( pool.tranches.map((tranche) => ( - + View {tranche.currency.name.split(' ').at(-1)} @@ -184,6 +189,7 @@ const AvailableNetworks = ({ poolId }: { poolId: string }) => { const chain = (evmChains as any)[domain.chainId] return ( Date: Tue, 20 Aug 2024 15:51:36 -0400 Subject: [PATCH 06/26] Fix start script in main package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3195e5b19..3abeb9aff3 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "format:run": "cd $INIT_CWD && prettier --write \"./**/*.{ts,tsx}\"", "format:check": "cd $INIT_CWD && prettier --check \"./**/*.{ts,tsx}\"", "onboarding-api": "yarn workspace @centrifuge/onboarding-api start:functions", - "pinning-api": "yarn workspace @centrifuge/pinning-api start:functions", + "pinning-api": "yarn workspace pinning-api start:functions", "centrifuge-app": "yarn workspace @centrifuge/centrifuge-app start", "faucet-api": "yarn workspace @centrifuge/faucet-api start", "start": "concurrently --kill-others-on-fail \"yarn onboarding-api\" \"yarn pinning-api\" \"yarn centrifuge-app\" -p name -n \"onboarding-api,pinning-api,centrifuge-app\"", From 6b9dc810f4e2c9914eacf4028733a95936acf7f3 Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 20 Aug 2024 15:56:58 -0400 Subject: [PATCH 07/26] Clean up --- centrifuge-app/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centrifuge-app/src/config.ts b/centrifuge-app/src/config.ts index 68f71a6b25..575dd3fdb9 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -156,7 +156,7 @@ export const evmChains: EvmChains = { decimals: 18, }, blockExplorerUrl: 'https://etherscan.io/', - urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], // the urls[] is used just for external connectors + urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], iconUrl: ethereumLogo, isTestnet: false, }, From dd9ae1fa6c2ae8655b0382a9b5b407670b381aad Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 26 Aug 2024 19:57:17 -0400 Subject: [PATCH 08/26] Upgrade ethersjs --- centrifuge-app/package.json | 3 - .../DebugFlags/components/ConvertAddress.tsx | 2 +- .../InvestRedeemLiquidityPoolsProvider.tsx | 4 +- .../src/components/OnboardingAuthProvider.tsx | 9 +- .../Portfolio/TransferTokensDrawer.tsx | 2 +- .../IssuerPool/Access/AssetOriginators.tsx | 2 +- .../IssuerPool/Investors/InvestorStatus.tsx | 2 +- .../pages/Onboarding/queries/useSignRemark.ts | 2 +- centrifuge-app/src/utils/address.ts | 2 +- .../src/utils/tinlake/useEvmTransaction.ts | 2 +- .../src/utils/tinlake/useTinlakeBalances.ts | 9 +- .../utils/tinlake/useTinlakeInvestments.ts | 5 +- .../src/utils/tinlake/useTinlakePools.ts | 15 +- .../src/utils/tinlake/useTinlakePortfolio.ts | 3 +- .../utils/tinlake/useTinlakeTransaction.ts | 2 +- centrifuge-app/src/utils/useCFGTokenPrice.ts | 5 +- centrifuge-app/src/utils/usePermissions.tsx | 2 +- centrifuge-app/src/utils/validation/index.ts | 2 +- centrifuge-js/package.json | 5 - centrifuge-js/src/Centrifuge.ts | 2 +- centrifuge-js/src/CentrifugeBase.ts | 2 +- centrifuge-js/src/modules/liquidityPools.ts | 66 +-- .../liquidityPools/abi/Gateway.abi.json | 10 +- .../abi/InvestmentManager.abi.json | 10 +- centrifuge-js/src/modules/pools.ts | 4 +- centrifuge-js/src/modules/tinlake.ts | 70 +++- centrifuge-js/src/types/index.ts | 5 +- centrifuge-js/src/utils/evmMulticall.ts | 10 +- centrifuge-react/package.json | 4 - .../CentrifugeProvider/CentrifugeProvider.tsx | 2 +- .../src/components/WalletMenu/WalletMenu.tsx | 2 +- .../WalletProvider/WalletProvider.tsx | 6 +- .../components/WalletProvider/evm/utils.ts | 13 +- fabric/src/components/TextInput/index.tsx | 2 +- fabric/tsconfig.json | 23 +- onboarding-api/package.json | 4 - onboarding-api/src/middleware/verifyAuth.ts | 2 +- onboarding-api/src/utils/networks/evm.ts | 13 +- onboarding-api/src/utils/networks/tinlake.ts | 19 +- onboarding-api/tsconfig.json | 8 +- package.json | 1 + tsconfig.base.json | 9 +- yarn.lock | 387 ++---------------- 43 files changed, 236 insertions(+), 516 deletions(-) diff --git a/centrifuge-app/package.json b/centrifuge-app/package.json index e20cbc141b..85925dfbce 100644 --- a/centrifuge-app/package.json +++ b/centrifuge-app/package.json @@ -29,9 +29,6 @@ "@centrifuge/centrifuge-js": "workspace:*", "@centrifuge/centrifuge-react": "workspace:*", "@centrifuge/fabric": "workspace:*", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/contracts": "^5.6.0", - "@ethersproject/providers": "^5.6.0", "@makerdao/multicall": "^0.12.0", "@polkadot/react-identicon": "~3.1.4", "@styled-system/css": "^5.1.5", diff --git a/centrifuge-app/src/components/DebugFlags/components/ConvertAddress.tsx b/centrifuge-app/src/components/DebugFlags/components/ConvertAddress.tsx index 82b19ea66a..2f06c4615c 100644 --- a/centrifuge-app/src/components/DebugFlags/components/ConvertAddress.tsx +++ b/centrifuge-app/src/components/DebugFlags/components/ConvertAddress.tsx @@ -7,8 +7,8 @@ import { useWallet, } from '@centrifuge/centrifuge-react' import { Dialog, Grid, Select, Stack, Text, TextInput } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress as isSubstrateAddress } from '@polkadot/util-crypto' +import { isAddress as isEvmAddress } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { firstValueFrom } from 'rxjs' diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx index 2b066ce04b..5585bcf956 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx @@ -7,8 +7,8 @@ import { useEvmProvider, useWallet, } from '@centrifuge/centrifuge-react' -import { TransactionRequest } from '@ethersproject/providers' import BN from 'bn.js' +import { TransactionRequest } from 'ethers' import * as React from 'react' import { Dec } from '../../utils/Decimal' import { useEvmTransaction } from '../../utils/tinlake/useEvmTransaction' @@ -48,6 +48,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children const tranche = pool.tranches.find((t) => t.id === trancheId) const { data: metadata, isLoading: isMetadataLoading } = usePoolMetadata(pool) const trancheMeta = metadata?.tranches?.[trancheId] + const chainId = provider?.network.chainId || 1 if (!tranche) throw new Error(`Token not found. Pool id: ${poolId}, token id: ${trancheId}`) @@ -254,6 +255,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children lpInvest?.lpAddress, lpInvest?.currency.address, amount.toString(), + chainId, ]), approveTrancheToken: () => {}, cancelInvest: doAction('cancelInvest', () => [lpInvest?.lpAddress]), diff --git a/centrifuge-app/src/components/OnboardingAuthProvider.tsx b/centrifuge-app/src/components/OnboardingAuthProvider.tsx index 00fb589f2e..4c15f1bb01 100644 --- a/centrifuge-app/src/components/OnboardingAuthProvider.tsx +++ b/centrifuge-app/src/components/OnboardingAuthProvider.tsx @@ -1,9 +1,8 @@ import Centrifuge from '@centrifuge/centrifuge-js' import { useCentrifuge, useCentrifugeUtils, useEvmProvider, useWallet } from '@centrifuge/centrifuge-react' -import { BigNumber } from '@ethersproject/bignumber' import { Signer } from '@polkadot/types/types' import { encodeAddress } from '@polkadot/util-crypto' -import { ethers, utils } from 'ethers' +import { ethers, hashMessage } from 'ethers' import * as React from 'react' import { useMutation, useQuery } from 'react-query' @@ -240,7 +239,7 @@ Issued At: ${new Date().toISOString()}` let body if (signedMessage === '0x') { - const messageHash = utils.hashMessage(message) + const messageHash = hashMessage(message) const isValid = await isValidSignature(signer, address, messageHash, evmChainId || 1) @@ -308,9 +307,9 @@ const isValidSignature = async (provider: any, safeAddress: string, messageHash: throw new Error('Unable to fetch SafeMessage') } - const threshold = BigNumber.from(await safeContract.getThreshold()).toNumber() + const threshold = BigInt(await safeContract.getThreshold()) - if (!threshold || threshold > safeMessage.confirmations.length) { + if (!threshold || threshold > BigInt(safeMessage.confirmations.length)) { throw new Error('Threshold has not been met') } diff --git a/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx b/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx index b07a2155d2..032b65d797 100644 --- a/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx +++ b/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx @@ -20,9 +20,9 @@ import { TabsItem, Text, } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress as isSubstrateAddress } from '@polkadot/util-crypto' import Decimal from 'decimal.js-light' +import { isAddress as isEvmAddress } from 'ethers' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import React, { useMemo } from 'react' import { useQuery } from 'react-query' diff --git a/centrifuge-app/src/pages/IssuerPool/Access/AssetOriginators.tsx b/centrifuge-app/src/pages/IssuerPool/Access/AssetOriginators.tsx index 6e6a77a9cd..6c61ee51fc 100644 --- a/centrifuge-app/src/pages/IssuerPool/Access/AssetOriginators.tsx +++ b/centrifuge-app/src/pages/IssuerPool/Access/AssetOriginators.tsx @@ -18,9 +18,9 @@ import { useGetNetworkName, } from '@centrifuge/centrifuge-react' import { Button, IconMinusCircle, InputErrorMessage, SelectInner, Stack, Text, TextInput } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress as isSubstrateAddress, sortAddresses } from '@polkadot/util-crypto' import { BN } from 'bn.js' +import { isAddress as isEvmAddress } from 'ethers' import { ErrorMessage, Field, diff --git a/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx b/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx index 721a6700ae..7d442f2b38 100644 --- a/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx +++ b/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx @@ -21,8 +21,8 @@ import { Text, TextWithPlaceholder, } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress } from '@polkadot/util-crypto' +import { isAddress as isEvmAddress } from 'ethers' import React from 'react' import { useParams } from 'react-router' import { DataTable } from '../../../components/DataTable' diff --git a/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts b/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts index 3848352845..6eec6e9b03 100644 --- a/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts +++ b/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts @@ -8,7 +8,7 @@ import { useWallet, } from '@centrifuge/centrifuge-react' import { useNativeBalance } from '@centrifuge/centrifuge-react/dist/components/WalletProvider/evm/utils' -import { Contract } from '@ethersproject/contracts' +import { Contract } from 'ethers' import React, { useEffect } from 'react' import { UseMutateFunction } from 'react-query' import { lastValueFrom } from 'rxjs' diff --git a/centrifuge-app/src/utils/address.ts b/centrifuge-app/src/utils/address.ts index 54a9e9371a..66c00cf3a0 100644 --- a/centrifuge-app/src/utils/address.ts +++ b/centrifuge-app/src/utils/address.ts @@ -1,5 +1,5 @@ -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress } from '@polkadot/util-crypto' +import { isAddress as isEvmAddress } from 'ethers' export function isSubstrateAddress(address: string) { return isAddress(address) && !isEvmAddress(address) diff --git a/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts b/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts index a6f1ecf6c6..9857947811 100644 --- a/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts +++ b/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts @@ -7,7 +7,7 @@ import { useTransactions, useWallet, } from '@centrifuge/centrifuge-react' -import { TransactionRequest, TransactionResponse } from '@ethersproject/providers' +import { TransactionRequest, TransactionResponse } from 'ethers' import * as React from 'react' import { Observable, lastValueFrom, tap } from 'rxjs' diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts index c8eacf5249..8a33ddc2ed 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts @@ -7,8 +7,7 @@ import { TokenBalance, } from '@centrifuge/centrifuge-js' import { useWallet } from '@centrifuge/centrifuge-react' -import { BigNumber } from '@ethersproject/bignumber' -import { BaseProvider } from '@ethersproject/providers' +import { Provider } from 'ethers' import { useQuery } from 'react-query' import { ethConfig } from '../../config' import { currencies } from './currencies' @@ -31,10 +30,10 @@ export function useTinlakeBalances(address?: string) { const WCFG_ADDRESS = '0xc221b7e65ffc80de234bbb6667abdd46593d34f0' -async function getBalances(pools: TinlakePool[], address: string, provider: BaseProvider) { +async function getBalances(pools: TinlakePool[], address: string, provider: Provider) { const calls: EvmMulticallCall[] = [] - const toTokenBalance = (val: BigNumber) => new TokenBalance(val.toString(), 18) - const toCurrencyBalance = (val: BigNumber) => new CurrencyBalance(val.toString(), 18) + const toTokenBalance = (val: BigInt) => new TokenBalance(val.toString(), 18) + const toCurrencyBalance = (val: BigInt) => new CurrencyBalance(val.toString(), 18) const seenCurrencies = new Set() diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts b/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts index 664db8b130..fc22ee9a94 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts @@ -1,5 +1,4 @@ import { CurrencyBalance } from '@centrifuge/centrifuge-js' -import { BigNumber } from '@ethersproject/bignumber' import Decimal from 'decimal.js-light' import { useQuery } from 'react-query' import { useAddress } from '../useAddress' @@ -17,8 +16,8 @@ export function useTinlakeInvestments(poolId: string, address?: string) { } async function getInvestment(pool: TinlakePool, address: string) { - const toNumber = (val: BigNumber) => val.toNumber() - const toDec18 = (val: BigNumber) => new CurrencyBalance(val.toString(), 18).toDecimal() + const toNumber = (val: BigInt) => Number(val) + const toDec18 = (val: BigInt) => new CurrencyBalance(val.toString(), 18).toDecimal() const calls: Call[] = [ { target: pool.addresses.JUNIOR_TRANCHE, diff --git a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts index 13071a2059..b51c03800c 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts @@ -9,7 +9,6 @@ import { TokenBalance, } from '@centrifuge/centrifuge-js' import { useCentrifuge } from '@centrifuge/centrifuge-react' -import { BigNumber } from '@ethersproject/bignumber' import BN from 'bn.js' import * as React from 'react' import { useQuery } from 'react-query' @@ -346,12 +345,12 @@ export async function getWriteOffPercentages(pool: TinlakePool, loans: any[]) { } async function getPools(pools: IpfsPools): Promise<{ pools: TinlakePool[] }> { - const toDateString = (val: BigNumber) => new Date(val.toNumber() * 1000).toISOString() - const toNumber = (val: BigNumber) => val.toNumber() - const toCurrencyBalance = (val: BigNumber) => new CurrencyBalance(val.toString(), 18) - const toTokenBalance = (val: BigNumber) => new TokenBalance(val.toString(), 18) - const toRate = (val: BigNumber) => new Rate(val.toString()) - const toPrice = (val: BigNumber) => new Rate(val.toString()) + const toDateString = (val: BigInt) => new Date(Number(val) * 1000).toISOString() + const toNumber = (val: BigInt) => Number(val) + const toCurrencyBalance = (val: BigInt) => new CurrencyBalance(val.toString(), 18) + const toTokenBalance = (val: BigInt) => new TokenBalance(val.toString(), 18) + const toRate = (val: BigInt) => new Rate(val.toString()) + const toPrice = (val: BigInt) => new Rate(val.toString()) const calls: Call[] = [] pools.active.forEach((pool) => { @@ -828,6 +827,6 @@ interface State { submissionPeriod: boolean } -function toBN(val: BigNumber) { +function toBN(val: BigInt) { return new BN(val.toString()) } diff --git a/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts b/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts index f12f5561bf..c03b86ab5c 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts @@ -1,5 +1,4 @@ import { CurrencyBalance } from '@centrifuge/centrifuge-js' -import { BigNumber } from '@ethersproject/bignumber' import BN from 'bn.js' import { useQuery } from 'react-query' import { useAddress } from '../useAddress' @@ -24,7 +23,7 @@ export enum TinlakeTranche { } async function getTinlakePortfolio(ipfsPools: IpfsPools, address: string) { - const toBN = (val: BigNumber) => new CurrencyBalance(val.toString(), 18) + const toBN = (val: BigInt) => new CurrencyBalance(val.toString(), 18) const calls: Call[] = ipfsPools.active.flatMap((pool) => [ { diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeTransaction.ts b/centrifuge-app/src/utils/tinlake/useTinlakeTransaction.ts index 42098fb2b3..ad2455828d 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeTransaction.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeTransaction.ts @@ -1,5 +1,5 @@ import Centrifuge, { TinlakeContractAddresses, TinlakeContractVersions } from '@centrifuge/centrifuge-js' -import { TransactionRequest, TransactionResponse } from '@ethersproject/providers' +import { TransactionRequest, TransactionResponse } from 'ethers' import { Observable } from 'rxjs' import { usePool } from '../usePools' import { useEvmTransaction } from './useEvmTransaction' diff --git a/centrifuge-app/src/utils/useCFGTokenPrice.ts b/centrifuge-app/src/utils/useCFGTokenPrice.ts index a8aa4a1f19..27f34eb6c5 100644 --- a/centrifuge-app/src/utils/useCFGTokenPrice.ts +++ b/centrifuge-app/src/utils/useCFGTokenPrice.ts @@ -1,10 +1,9 @@ import { useWallet } from '@centrifuge/centrifuge-react' -import { Contract } from '@ethersproject/contracts' -import { BaseProvider } from '@ethersproject/providers' +import { Contract, Provider } from 'ethers' import { useQuery } from 'react-query' import { Dec } from './Decimal' -async function getWCFGPrice(provider: BaseProvider) { +async function getWCFGPrice(provider: Provider) { const usdcWcfgPool = '0x7270233cCAE676e776a659AFfc35219e6FCfbB10' const uniswapPoolAbi = ['function observe(uint32[] secondsAgos) external view returns (int56[], uint160[])'] const poolContract = new Contract(usdcWcfgPool, uniswapPoolAbi, provider) diff --git a/centrifuge-app/src/utils/usePermissions.tsx b/centrifuge-app/src/utils/usePermissions.tsx index 0a227e3eb5..c44ee12284 100644 --- a/centrifuge-app/src/utils/usePermissions.tsx +++ b/centrifuge-app/src/utils/usePermissions.tsx @@ -14,8 +14,8 @@ import { useWallet, } from '@centrifuge/centrifuge-react' import { Select } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { ApiRx } from '@polkadot/api' +import { isAddress as isEvmAddress } from 'ethers' import * as React from 'react' import { combineLatest, combineLatestWith, filter, map, repeatWhen, switchMap, take } from 'rxjs' import { diffPermissions } from '../pages/IssuerPool/Configuration/Admins' diff --git a/centrifuge-app/src/utils/validation/index.ts b/centrifuge-app/src/utils/validation/index.ts index d26641a0e6..c7143a2c0f 100644 --- a/centrifuge-app/src/utils/validation/index.ts +++ b/centrifuge-app/src/utils/validation/index.ts @@ -1,7 +1,7 @@ import { ExternalPricingInfo } from '@centrifuge/centrifuge-js' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress as isSubstrateAddress } from '@polkadot/util-crypto' import Decimal from 'decimal.js-light' +import { isAddress as isEvmAddress } from 'ethers' import { Dec } from '../Decimal' import { daysBetween } from '../date' import { formatPercentage } from '../formatting' diff --git a/centrifuge-js/package.json b/centrifuge-js/package.json index b824f6e0d5..5cdd78bad5 100644 --- a/centrifuge-js/package.json +++ b/centrifuge-js/package.json @@ -28,11 +28,6 @@ "lint": "eslint src/**/*.ts" }, "dependencies": { - "@ethersproject/abi": "^5.6.0", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/contracts": "^5.6.0", - "@ethersproject/providers": "^5.6.0", "@polkadot/api": "~12.1.1", "@polkadot/keyring": "^11.1.3", "@polkadot/types": "~12.1.1", diff --git a/centrifuge-js/src/Centrifuge.ts b/centrifuge-js/src/Centrifuge.ts index b0e4b8bb8f..92f774b2fa 100644 --- a/centrifuge-js/src/Centrifuge.ts +++ b/centrifuge-js/src/Centrifuge.ts @@ -1,6 +1,6 @@ -import type { JsonRpcSigner } from '@ethersproject/providers' import { AddressOrPair } from '@polkadot/api/types' import { Signer } from '@polkadot/types/types' +import type { JsonRpcSigner } from 'ethers' import { CentrifugeBase, UserProvidedConfig } from './CentrifugeBase' import { getAuthModule } from './modules/auth' import { getLiquidityPoolsModule } from './modules/liquidityPools' diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index a22ebd7350..af551d2375 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -1,10 +1,10 @@ -import type { JsonRpcSigner, TransactionRequest } from '@ethersproject/providers' import { ApiRx } from '@polkadot/api' import { AddressOrPair, SubmittableExtrinsic } from '@polkadot/api/types' import { SignedBlock } from '@polkadot/types/interfaces' import { DefinitionRpc, DefinitionsCall, ISubmittableResult, Signer } from '@polkadot/types/types' import { hexToBn } from '@polkadot/util' import { sortAddresses } from '@polkadot/util-crypto' +import type { JsonRpcSigner, TransactionRequest } from 'ethers' import 'isomorphic-fetch' import { Observable, diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index 9dc84f7e82..ea0f03906e 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,8 +1,6 @@ -import { BigNumber } from '@ethersproject/bignumber' -import { Contract, ContractInterface } from '@ethersproject/contracts' -import type { BaseProvider, TransactionRequest, TransactionResponse } from '@ethersproject/providers' import BN from 'bn.js' import { signERC2612Permit } from 'eth-permit' +import { Contract, Interface, Provider, TransactionRequest, TransactionResponse } from 'ethers' import set from 'lodash/set' import { combineLatestWith, firstValueFrom, from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' @@ -16,7 +14,7 @@ const PERMIT_TYPEHASH = '0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c6 const NULL_ADDRESS = '0x0000000000000000000000000000000000000000' type EvmQueryOptions = { - rpcProvider?: BaseProvider + rpcProvider?: Provider } export type Permit = { @@ -25,8 +23,8 @@ export type Permit = { s: string v: number } -const toCurrencyBalance = (decimals: number) => (val: BigNumber) => new CurrencyBalance(val.toString(), decimals) -const toTokenBalance = (decimals: number) => (val: BigNumber) => new TokenBalance(val.toString(), decimals) +const toCurrencyBalance = (decimals: number) => (val: BigInt) => new CurrencyBalance(val.toString(), decimals) +const toTokenBalance = (decimals: number) => (val: BigInt) => new TokenBalance(val.toString(), decimals) type LPConfig = { centrifugeRouter: string @@ -52,7 +50,7 @@ const config: Record = { } export function getLiquidityPoolsModule(inst: Centrifuge) { - function contract(contractAddress: string, abi: ContractInterface, options?: EvmQueryOptions) { + function contract(contractAddress: string, abi: Interface, options?: EvmQueryOptions) { const provider = inst.config.evmSigner ?? options?.rpcProvider if (!provider) throw new Error('Needs provider') return new Contract(contractAddress, abi, provider) @@ -124,7 +122,10 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { ) { const [poolManager, poolId, trancheId] = args return pending( - contract(poolManager, ABI.PoolManager).deployTranche(poolId, trancheId, { ...options, gasLimit: 5000000 }) + contract(poolManager, new Interface(ABI.PoolManager)).deployTranche(poolId, trancheId, { + ...options, + gasLimit: 5000000, + }) ) } @@ -134,7 +135,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { ) { const [poolManager, poolId, trancheId, currencyAddress] = args return pending( - contract(poolManager, ABI.PoolManager).deployVault(poolId, trancheId, currencyAddress, { + contract(poolManager, new Interface(ABI.PoolManager)).deployVault(poolId, trancheId, currencyAddress, { ...options, gasLimit: 5000000, }) @@ -146,15 +147,14 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { options: TransactionRequest = {} ) { const [address, currencyAddress, amount] = args - return pending(contract(currencyAddress, ABI.Currency).approve(address, amount, options)) + return pending(contract(currencyAddress, new Interface(ABI.Currency)).approve(address, amount, options)) } - async function signPermit(args: [spender: string, currencyAddress: string, amount: BN]) { - const [spender, currencyAddress, amount] = args + async function signPermit(args: [spender: string, currencyAddress: string, amount: BN, chainId: number]) { + const [spender, currencyAddress, amount, chainId] = args if (!inst.config.evmSigner) throw new Error('EVM signer not set') let domainOrCurrency: any = currencyAddress - const chainId = await inst.config.evmSigner.getChainId() if (currencyAddress.toLowerCase() === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') { // USDC has custom version domainOrCurrency = { name: 'USD Coin', version: '2', chainId, verifyingContract: currencyAddress } @@ -177,7 +177,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const [lpAddress, order] = args const user = inst.getSignerAddress('evm') return pending( - contract(lpAddress, ABI.LiquidityPool).requestDeposit(order.toString(), user, user, { + contract(lpAddress, new Interface(ABI.LiquidityPool)).requestDeposit(order.toString(), user, user, { ...options, gasLimit: 300000, }) @@ -188,7 +188,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const [lpAddress, order] = args const user = inst.getSignerAddress('evm') return pending( - contract(lpAddress, ABI.LiquidityPool).requestRedeem(order.toString(), user, user, { + contract(lpAddress, new Interface(ABI.LiquidityPool)).requestRedeem(order.toString(), user, user, { ...options, gasLimit: 300000, }) @@ -213,32 +213,36 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { function cancelRedeemOrder(args: [lpAddress: string], options: TransactionRequest = {}) { const [lpAddress] = args const user = inst.getSignerAddress('evm') - return pending(contract(lpAddress, ABI.LiquidityPool).cancelRedeemRequest(0, user, options)) + return pending(contract(lpAddress, new Interface(ABI.LiquidityPool)).cancelRedeemRequest(0, user, options)) } function cancelInvestOrder(args: [lpAddress: string], options: TransactionRequest = {}) { const [lpAddress] = args const user = inst.getSignerAddress('evm') - return pending(contract(lpAddress, ABI.LiquidityPool).cancelDepositRequest(0, user, options)) + return pending(contract(lpAddress, new Interface(ABI.LiquidityPool)).cancelDepositRequest(0, user, options)) } function claimCancelDeposit(args: [lpAddress: string], options: TransactionRequest = {}) { const [lpAddress] = args const user = inst.getSignerAddress('evm') - return pending(contract(lpAddress, ABI.LiquidityPool).claimCancelDepositRequest(0, user, user, options)) + return pending( + contract(lpAddress, new Interface(ABI.LiquidityPool)).claimCancelDepositRequest(0, user, user, options) + ) } function claimCancelRedeem(args: [lpAddress: string], options: TransactionRequest = {}) { const [lpAddress] = args const user = inst.getSignerAddress('evm') - return pending(contract(lpAddress, ABI.LiquidityPool).claimCancelRedeemRequest(0, user, user, options)) + return pending( + contract(lpAddress, new Interface(ABI.LiquidityPool)).claimCancelRedeemRequest(0, user, user, options) + ) } function mint(args: [lpAddress: string, mint: BN, receiver?: string], options: TransactionRequest = {}) { const [lpAddress, mint, receiver] = args const user = inst.getSignerAddress('evm') return pending( - contract(lpAddress, ABI.LiquidityPool).mint(mint.toString(), receiver ?? user, { + contract(lpAddress, new Interface(ABI.LiquidityPool)).mint(mint.toString(), receiver ?? user, { ...options, gasLimit: 200000, }) @@ -249,7 +253,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const [lpAddress, withdraw, receiver] = args const user = inst.getSignerAddress('evm') return pending( - contract(lpAddress, ABI.LiquidityPool).withdraw(withdraw.toString(), receiver ?? user, user, { + contract(lpAddress, new Interface(ABI.LiquidityPool)).withdraw(withdraw.toString(), receiver ?? user, user, { ...options, gasLimit: 200000, }) @@ -284,15 +288,15 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { async function getManagerFromRouter(args: [router: string], options?: EvmQueryOptions) { const [router] = args - const gatewayAddress = await contract(router, ABI.Router, options).gateway() - const managerAddress = await contract(gatewayAddress, ABI.Gateway, options).investmentManager() + const gatewayAddress = await contract(router, new Interface(ABI.Router), options).gateway() + const managerAddress = await contract(gatewayAddress, new Interface(ABI.Gateway), options).investmentManager() return managerAddress as string } async function getRecentLPEvents(args: [lpAddress: string, user: string], options?: EvmQueryOptions) { const [lpAddress, user] = args const blockNumber = await getProvider(options)!.getBlockNumber() - const cont = contract(lpAddress, ABI.LiquidityPool, options) + const cont = contract(lpAddress, new Interface(ABI.LiquidityPool), options) const depositFilter = cont.filters.DepositRequest(user) const redeemFilter = cont.filters.RedeemRequest(user) const cancelDepositFilter = cont.filters.CancelDepositRequest(user) @@ -324,7 +328,11 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const currencies = await firstValueFrom(getDomainCurrencies([chainId])) - const poolManager = (await contract(investmentManager, ABI.InvestmentManager, options).poolManager()) as string + const poolManager = (await contract( + investmentManager, + new Interface(ABI.InvestmentManager), + options + ).poolManager()) as string const poolData = await multicall<{ isActive: boolean @@ -373,7 +381,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { ...(currencies.flatMap((currency) => ({ target: poolManager, call: ['function assetToId(address) view returns (uint128)', currency.address], - returns: [[`currencyNeedsAdding[${currency.address}]`, (id: BigNumber) => id.isZero()]], + returns: [[`currencyNeedsAdding[${currency.address}]`, (id: BigInt) => id === BigInt(0)]], })) as Call[]), ], { @@ -421,7 +429,11 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const currencies = await firstValueFrom(getDomainCurrencies([chainId])) - const poolManager: string = await contract(managerAddress, ABI.InvestmentManager, options).poolManager() + const poolManager: string = await contract( + managerAddress, + new Interface(ABI.InvestmentManager), + options + ).poolManager() if (!currencies?.length) return [] diff --git a/centrifuge-js/src/modules/liquidityPools/abi/Gateway.abi.json b/centrifuge-js/src/modules/liquidityPools/abi/Gateway.abi.json index 4dac24fd35..78046d1c21 100644 --- a/centrifuge-js/src/modules/liquidityPools/abi/Gateway.abi.json +++ b/centrifuge-js/src/modules/liquidityPools/abi/Gateway.abi.json @@ -1 +1,9 @@ -["function investmentManager() view returns (address)"] +[ + { + "inputs": [], + "name": "investmentManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/centrifuge-js/src/modules/liquidityPools/abi/InvestmentManager.abi.json b/centrifuge-js/src/modules/liquidityPools/abi/InvestmentManager.abi.json index 06adf46e1a..fdaac84254 100644 --- a/centrifuge-js/src/modules/liquidityPools/abi/InvestmentManager.abi.json +++ b/centrifuge-js/src/modules/liquidityPools/abi/InvestmentManager.abi.json @@ -1 +1,9 @@ -["function poolManager() view returns (address)"] +[ + { + "inputs": [], + "name": "poolManager", + "outputs": [{ "internalType": "contract IPoolManager", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts index d1752dcdb5..c7f1be3628 100644 --- a/centrifuge-js/src/modules/pools.ts +++ b/centrifuge-js/src/modules/pools.ts @@ -1,4 +1,3 @@ -import { isAddress as isEvmAddress } from '@ethersproject/address' import { ApiRx } from '@polkadot/api' import { SubmittableExtrinsic } from '@polkadot/api/types' import { StorageKey, u32 } from '@polkadot/types' @@ -7,6 +6,7 @@ import { ISubmittableResult } from '@polkadot/types/types' import { blake2AsHex } from '@polkadot/util-crypto/blake2' import BN from 'bn.js' import Decimal from 'decimal.js-light' +import { isAddress as isEvmAddress } from 'ethers' import { EMPTY, Observable, combineLatest, expand, firstValueFrom, forkJoin, from, of, startWith } from 'rxjs' import { combineLatestWith, filter, map, repeatWhen, switchMap, take, takeLast } from 'rxjs/operators' import { SolverResult, calculateOptimalSolution } from '..' @@ -3679,6 +3679,8 @@ export function getPoolsModule(inst: Centrifuge) { switchMap(({ api, pool: rawPool }) => { const pool = rawPool.toHuman() as PoolDetailsData const trancheIds = pool.tranches.ids + console.log('🚀 ~ trancheIds:', trancheIds) + console.log('🚀 ~ poolId:', poolId) return combineLatest([ api.queryMulti( trancheIds.flatMap((trancheId) => [ diff --git a/centrifuge-js/src/modules/tinlake.ts b/centrifuge-js/src/modules/tinlake.ts index bd919f1a97..deb2d88b96 100644 --- a/centrifuge-js/src/modules/tinlake.ts +++ b/centrifuge-js/src/modules/tinlake.ts @@ -1,11 +1,10 @@ -import { Contract } from '@ethersproject/contracts' -import { TransactionRequest, TransactionResponse } from '@ethersproject/providers' import BN from 'bn.js' +import { Contract, TransactionRequest, TransactionResponse } from 'ethers' import { from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' import { TransactionOptions } from '../types' import { CurrencyBalance } from '../utils/BN' -import { calculateOptimalSolution, Orders, State } from '../utils/solver/tinlakeSolver' +import { Orders, State, calculateOptimalSolution } from '../utils/solver/tinlakeSolver' import { abis } from './tinlake/abi' const contracts: Record = {} @@ -94,6 +93,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( + // @ts-ignore contract(contractAddresses, contractVersions, 'TINLAKE_CURRENCY').approve( contractAddresses[tranche === 'junior' ? 'JUNIOR_TRANCHE' : 'SENIOR_TRANCHE'], maxUint256, @@ -110,6 +110,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( + // @ts-ignore contract(contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_TOKEN' : 'SENIOR_TOKEN').approve( contractAddresses[tranche === 'junior' ? 'JUNIOR_TRANCHE' : 'SENIOR_TRANCHE'], maxUint256, @@ -126,10 +127,12 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche, order] = args return pending( + // @ts-ignore contract( contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR' + // @ts-ignore ).supplyOrder(order.toString(), options) ) } @@ -142,10 +145,12 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche, order] = args return pending( + // @ts-ignore contract( contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR' + // @ts-ignore ).redeemOrder(order.toString(), options) ) } @@ -158,6 +163,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( + // @ts-ignore contract(contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR')[ 'disburse()' ](options) @@ -181,25 +187,37 @@ export function getTinlakeModule(inst: Centrifuge) { const reserve = toBN( await (beforeClosing ? isMakerIntegrated - ? contract(contractAddresses, contractVersions, 'ASSESSOR').totalBalance() - : contract(contractAddresses, contractVersions, 'RESERVE').totalBalance() - : coordinator.epochReserve()) + ? // @ts-ignore + contract(contractAddresses, contractVersions, 'ASSESSOR').totalBalance() + : // @ts-ignore + contract(contractAddresses, contractVersions, 'RESERVE').totalBalance() + : // @ts-ignore + coordinator.epochReserve()) ) const netAssetValue = toBN( await (beforeClosing ? contractVersions?.FEED === 2 - ? feed.latestNAV() - : feed.approximatedNAV() - : coordinator.epochNAV()) + ? // @ts-ignore + feed.latestNAV() + : // @ts-ignore + feed.approximatedNAV() + : // @ts-ignore + coordinator.epochNAV()) ) const seniorAsset = beforeClosing ? isMakerIntegrated - ? toBN(await assessor.seniorDebt()).add(toBN(await assessor.seniorBalance())) - : toBN(await assessor.seniorDebt_()).add(toBN(await assessor.seniorBalance_())) - : toBN(await coordinator.epochSeniorAsset()) - + ? // @ts-ignore + toBN(await assessor.seniorDebt()).add(toBN(await assessor.seniorBalance())) + : // @ts-ignore + toBN(await assessor.seniorDebt_()).add(toBN(await assessor.seniorBalance_())) + : // @ts-ignore + toBN(await coordinator.epochSeniorAsset()) + + // @ts-ignore const minDropRatio = toBN(await assessor.minSeniorRatio()) + // @ts-ignore const maxDropRatio = toBN(await assessor.maxSeniorRatio()) + // @ts-ignore const maxReserve = toBN(await assessor.maxReserve()) return { reserve, netAssetValue, seniorAsset, minDropRatio, maxDropRatio, maxReserve } @@ -220,27 +238,36 @@ export function getTinlakeModule(inst: Centrifuge) { const assessor = contract(contractAddresses, contractVersions, 'ASSESSOR') const feed = contract(contractAddresses, contractVersions, 'FEED') + // @ts-ignore const epochNAV = toBN(await feed.currentNAV()) + // @ts-ignore const epochReserve = toBN(await contract(contractAddresses, contractVersions, 'RESERVE').totalBalance()) const epochSeniorTokenPrice = toBN( + // @ts-ignore await assessor['calcSeniorTokenPrice(uint256,uint256)'](epochNAV.toString(), epochReserve.toString()) ) const epochJuniorTokenPrice = toBN( + // @ts-ignore await assessor['calcJuniorTokenPrice(uint256,uint256)'](epochNAV.toString(), epochReserve.toString()) ) return { + // @ts-ignore dropInvest: toBN(await seniorTranche.totalSupply()), + // @ts-ignore dropRedeem: toBN(await seniorTranche.totalRedeem()) .mul(epochSeniorTokenPrice) .div(e27), + // @ts-ignore tinInvest: toBN(await juniorTranche.totalSupply()), + // @ts-ignore tinRedeem: toBN(await juniorTranche.totalRedeem()) .mul(epochJuniorTokenPrice) .div(e27), } } const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + // @ts-ignore const orderState = await coordinator.order() return { @@ -258,10 +285,16 @@ export function getTinlakeModule(inst: Centrifuge) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') return { + // @ts-ignore dropInvest: toBN(await coordinator.weightSeniorSupply()), + // @ts-ignore dropRedeem: toBN(await coordinator.weightSeniorRedeem()), + // @ts-ignore tinInvest: toBN(await coordinator.weightJuniorSupply()), + // @ts-ignore tinRedeem: toBN(await coordinator.weightJuniorRedeem()), + // @ts-ignore + seniorAsset: toBN(await coordinator.weightSeniorAsset()), } } @@ -272,6 +305,7 @@ export function getTinlakeModule(inst: Centrifuge) { options: TransactionRequest = {} ) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + // @ts-ignore return pending(coordinator.closeEpoch({ ...options, gasLimit: 5000000 })) } @@ -283,6 +317,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const submissionTx = (async () => { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + // @ts-ignore if ((await coordinator.submissionPeriod()) !== true) throw new Error('Not in submission period') const state = await getEpochState(contractAddresses, contractVersions, []) const orders = await getOrders(contractAddresses, contractVersions, []) @@ -292,6 +327,7 @@ export function getTinlakeModule(inst: Centrifuge) { throw new Error('Failed to find a solution') } + // @ts-ignore return coordinator.submitSolution( solution.dropRedeem.toString(), solution.tinRedeem.toString(), @@ -332,6 +368,7 @@ export function getTinlakeModule(inst: Centrifuge) { throw new Error('Current epoch is still in the challenge period') } + // @ts-ignore return coordinator.executeEpoch({ ...options, gasLimit: 2000000 }) })() return pending(tx) @@ -349,7 +386,7 @@ export function getTinlakeModule(inst: Centrifuge) { contractVersions: TinlakeContractVersions | undefined ) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') - + // @ts-ignore const minChallengePeriodEnd = toBN(await coordinator.minChallengePeriodEnd()).toNumber() const latestBlockTimestamp = await getLatestBlockTimestamp() if (minChallengePeriodEnd !== 0) { @@ -357,12 +394,15 @@ export function getTinlakeModule(inst: Centrifuge) { return 'in-challenge-period' } + // @ts-ignore const submissionPeriod = await coordinator.submissionPeriod() if (submissionPeriod === true) { return 'in-submission-period' } + // @ts-ignore const lastEpochClosed = toBN(await coordinator.lastEpochClosed()).toNumber() + // @ts-ignore const minimumEpochTime = toBN(await coordinator.minimumEpochTime()).toNumber() if (submissionPeriod === false) { if (lastEpochClosed + minimumEpochTime < latestBlockTimestamp) return 'can-be-closed' @@ -385,6 +425,7 @@ export function getTinlakeModule(inst: Centrifuge) { const [address] = args const coordinator = contract(contractAddresses, contractVersions, 'CLAIM_CFG') + // @ts-ignore const tx = coordinator.accounts(address, options) return pending(tx) } @@ -398,6 +439,7 @@ export function getTinlakeModule(inst: Centrifuge) { const [centAddress] = args const coordinator = contract(contractAddresses, contractVersions, 'CLAIM_CFG') + // @ts-ignore const tx = coordinator.update(centAddress, options) return pending(tx) } diff --git a/centrifuge-js/src/types/index.ts b/centrifuge-js/src/types/index.ts index 4315ad45f0..f339dc753c 100644 --- a/centrifuge-js/src/types/index.ts +++ b/centrifuge-js/src/types/index.ts @@ -1,11 +1,8 @@ -import { - TransactionReceipt as EvmTransactionReceipt, - TransactionResponse as EvmTransactionResponse, -} from '@ethersproject/providers' import { AddressOrPair } from '@polkadot/api/types' import { ISubmittableResult } from '@polkadot/types/types' import { HexString } from '@polkadot/util/types' import BN from 'bn.js' +import { TransactionReceipt as EvmTransactionReceipt, TransactionResponse as EvmTransactionResponse } from 'ethers' import { Config } from '../CentrifugeBase' type EvmTransactionResult = { diff --git a/centrifuge-js/src/utils/evmMulticall.ts b/centrifuge-js/src/utils/evmMulticall.ts index 96129f7320..00025e8be1 100644 --- a/centrifuge-js/src/utils/evmMulticall.ts +++ b/centrifuge-js/src/utils/evmMulticall.ts @@ -1,6 +1,4 @@ -import { Interface } from '@ethersproject/abi' -import { Contract } from '@ethersproject/contracts' -import { BaseProvider } from '@ethersproject/providers' +import { Contract, Interface, Provider } from 'ethers' import set from 'lodash/set' const MULTICALL_ABI = [ @@ -25,7 +23,7 @@ const MULTICALL_ABI = [ const MULTICALL_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11' type AggregateOptions = { - rpcProvider: BaseProvider + rpcProvider: Provider allowFailure?: boolean } @@ -41,7 +39,7 @@ export type Call = { } const identity = (v: any) => v -const multicallContracts = new WeakMap() +const multicallContracts = new WeakMap() export async function multicall>(calls: Call[], options: AggregateOptions) { let contract = multicallContracts.get(options.rpcProvider) @@ -60,7 +58,7 @@ export async function multicall>(calls: Call[], options: callData: interfaces[i][0].encodeFunctionData(interfaces[i][1], c.call.slice(1)), })) - const results = await contract.callStatic.aggregate3(encoded) + const results = await contract.aggregate3.staticCall(encoded) const transformed: Record = {} calls.forEach((c, i) => { diff --git a/centrifuge-react/package.json b/centrifuge-react/package.json index 8e8a01ec4e..98e96d0430 100644 --- a/centrifuge-react/package.json +++ b/centrifuge-react/package.json @@ -46,10 +46,6 @@ }, "dependencies": { "@coinbase/wallet-sdk": "^3.6.3", - "@ethersproject/address": "^5.6.0", - "@ethersproject/bignumber": "^5.6.0", - "@ethersproject/networks": "^5.6.0", - "@ethersproject/providers": "^5.6.0", "@finoa/finoa-connect-sdk": "^1.0.1", "@polkadot/extension-dapp": "~0.45.5", "@polkadot/react-identicon": "~3.1.4", diff --git a/centrifuge-react/src/components/CentrifugeProvider/CentrifugeProvider.tsx b/centrifuge-react/src/components/CentrifugeProvider/CentrifugeProvider.tsx index ea94c699ab..c1a5cb4248 100644 --- a/centrifuge-react/src/components/CentrifugeProvider/CentrifugeProvider.tsx +++ b/centrifuge-react/src/components/CentrifugeProvider/CentrifugeProvider.tsx @@ -1,9 +1,9 @@ import Centrifuge, { Account, CurrencyBalance } from '@centrifuge/centrifuge-js' import type { UserProvidedConfig } from '@centrifuge/centrifuge-js/dist/CentrifugeBase' -import { getAddress, isAddress as isEvmAddress } from '@ethersproject/address' import { ApiRx } from '@polkadot/api' import { encodeAddress } from '@polkadot/util-crypto' import { BN } from 'bn.js' +import { getAddress, isAddress as isEvmAddress } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' diff --git a/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx b/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx index 27782a56df..2d74cbe373 100644 --- a/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx +++ b/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx @@ -15,7 +15,7 @@ import { Text, WalletButton, } from '@centrifuge/fabric' -import { getAddress } from '@ethersproject/address' +import { getAddress } from 'ethers' import * as React from 'react' import { Link } from 'react-router-dom' import styled from 'styled-components' diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index 5513280b45..b4faafc734 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -1,10 +1,10 @@ import { addressToHex, ComputedMultisig, evmToSubstrateAddress, Multisig } from '@centrifuge/centrifuge-js' -import { BaseProvider, getDefaultProvider, JsonRpcProvider, Networkish } from '@ethersproject/providers' import { isWeb3Injected } from '@polkadot/extension-dapp' import { getWallets } from '@subwallet/wallet-connect/dotsama/wallets' import { Wallet } from '@subwallet/wallet-connect/types' import { Web3ReactState } from '@web3-react/types' import { WalletConnect as WalletConnectV2 } from '@web3-react/walletconnect-v2' +import { getDefaultProvider, JsonRpcProvider, Networkish, Provider } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { firstValueFrom, map, switchMap } from 'rxjs' @@ -63,7 +63,7 @@ export type WalletContextType = { selectedWallet: EvmConnectorMeta | null isSmartContractWallet: boolean selectedAddress: string | null - getProvider(chainId: number): BaseProvider + getProvider(chainId: number): Provider } } @@ -134,7 +134,7 @@ type WalletProviderProps = { } let cachedEvmConnectors: EvmConnectorMeta[] | undefined = undefined -const cachedProviders = new Map() +const cachedProviders = new Map() export function WalletProvider({ children, diff --git a/centrifuge-react/src/components/WalletProvider/evm/utils.ts b/centrifuge-react/src/components/WalletProvider/evm/utils.ts index 4d1ae68b16..7b969c0c45 100644 --- a/centrifuge-react/src/components/WalletProvider/evm/utils.ts +++ b/centrifuge-react/src/components/WalletProvider/evm/utils.ts @@ -1,14 +1,13 @@ import { CurrencyBalance } from '@centrifuge/centrifuge-js' -import type { Networkish } from '@ethersproject/networks' -import type { BaseProvider, Web3Provider } from '@ethersproject/providers' import { CoinbaseWallet } from '@web3-react/coinbase-wallet' import { EIP1193 } from '@web3-react/eip1193' import { EMPTY, Empty } from '@web3-react/empty' import { GnosisSafe } from '@web3-react/gnosis-safe' import { MetaMask } from '@web3-react/metamask' import { createWeb3ReactStoreAndActions } from '@web3-react/store' -import { Actions, Provider, Web3ReactState, Web3ReactStore } from '@web3-react/types' +import { Actions, Provider as Web3ReactProvider, Web3ReactState, Web3ReactStore } from '@web3-react/types' import { WalletConnect as WalletConnectV2 } from '@web3-react/walletconnect-v2' +import type { Networkish } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { useWallet } from '../WalletProvider' @@ -37,7 +36,7 @@ export function useConnectorState(connector?: Connector | null) { return state } -const providerKeys = new WeakMap() +const providerKeys = new WeakMap() function getProviderKey(connector: Connector) { let providerKey if (connector.provider) { @@ -50,7 +49,7 @@ function getProviderKey(connector: Connector) { return providerKey } -export function useProviderForConnector( +export function useProviderForConnector( connector?: Connector | null, network?: Networkish ) { @@ -61,8 +60,8 @@ export function useProviderForConnector( const { data: provider } = useQuery( ['evmProvider', getProviderKey(conn), typeof network === 'object' ? network.chainId : network], async () => { - const { Web3Provider } = await import('@ethersproject/providers') - const provider = new Web3Provider(conn.provider!, network) + const { BrowserProvider } = await import('ethers') + const provider = new BrowserProvider(conn.provider!, network) return provider }, { enabled: !!conn.provider && isActive, staleTime: Infinity } diff --git a/fabric/src/components/TextInput/index.tsx b/fabric/src/components/TextInput/index.tsx index 1bc5397d48..7272919809 100644 --- a/fabric/src/components/TextInput/index.tsx +++ b/fabric/src/components/TextInput/index.tsx @@ -1,5 +1,5 @@ -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress as isSubstrateAddress } from '@polkadot/util-crypto' +import { isAddress as isEvmAddress } from 'ethers' import * as React from 'react' import styled, { keyframes } from 'styled-components' import { Flex, IconCentrifuge, IconEthereum, IconLoader, IconSearch } from '../..' diff --git a/fabric/tsconfig.json b/fabric/tsconfig.json index a1ba2a2a8c..eb0fbe0ddc 100644 --- a/fabric/tsconfig.json +++ b/fabric/tsconfig.json @@ -2,8 +2,14 @@ "compilerOptions": { "outDir": "dist", "module": "esnext", - "target": "es6", - "lib": ["es6", "dom", "es2016", "es2017", "ES2021.String"], + "target": "esnext", + "lib": [ + "es6", + "dom", + "es2016", + "es2017", + "ES2021.String" + ], "jsx": "react", "declaration": true, "moduleResolution": "node", @@ -17,6 +23,13 @@ "allowSyntheticDefaultImports": true, "skipLibCheck": true // an error happens in @types/download }, - "include": ["src", "./**/*.d.ts"], - "exclude": ["node_modules", "lib", "dist"] -} + "include": [ + "src", + "./**/*.d.ts" + ], + "exclude": [ + "node_modules", + "lib", + "dist" + ] +} \ No newline at end of file diff --git a/onboarding-api/package.json b/onboarding-api/package.json index deec5239c5..27b93bf033 100644 --- a/onboarding-api/package.json +++ b/onboarding-api/package.json @@ -16,10 +16,6 @@ }, "dependencies": { "@centrifuge/centrifuge-js": "workspace:centrifuge-js", - "@ethersproject/address": "^5.7.0", - "@ethersproject/contracts": "^5.7.0", - "@ethersproject/providers": "^5.7.2", - "@ethersproject/wallet": "^5.7.0", "@google-cloud/firestore": "^6.8.0", "@google-cloud/functions-framework": "^3.1.3", "@google-cloud/storage": "^6.9.1", diff --git a/onboarding-api/src/middleware/verifyAuth.ts b/onboarding-api/src/middleware/verifyAuth.ts index b7bbf78922..c19fc52c2f 100644 --- a/onboarding-api/src/middleware/verifyAuth.ts +++ b/onboarding-api/src/middleware/verifyAuth.ts @@ -1,4 +1,4 @@ -import { isAddress } from '@ethersproject/address' +import { isAddress } from 'ethers' import { NextFunction, Request, Response } from 'express' import * as jwt from 'jsonwebtoken' import { getValidSubstrateAddress } from '../utils/networks/centrifuge' diff --git a/onboarding-api/src/utils/networks/evm.ts b/onboarding-api/src/utils/networks/evm.ts index 02dc376266..01beecc69a 100644 --- a/onboarding-api/src/utils/networks/evm.ts +++ b/onboarding-api/src/utils/networks/evm.ts @@ -1,7 +1,4 @@ -import { isAddress } from '@ethersproject/address' -import { Contract } from '@ethersproject/contracts' -import { InfuraProvider, JsonRpcProvider, Provider } from '@ethersproject/providers' -import { BigNumber, ethers } from 'ethers' +import { Contract, InfuraProvider, JsonRpcProvider, Provider, ethers, isAddress } from 'ethers' import { Request, Response } from 'express' import fetch from 'node-fetch' import { SiweMessage } from 'siwe' @@ -41,7 +38,7 @@ export const validateEvmRemark = async ( Number(transactionInfo.blockNumber) ) - const [sender, actualRemark] = filteredEvents.flatMap((ev) => ev.args?.map((arg) => arg.toString())) + const [sender, actualRemark] = filteredEvents.flatMap((ev) => ev.topics?.map((arg) => arg.toString())) if (actualRemark !== expectedRemark || sender !== wallet.address) { throw new HttpError(400, 'Invalid remark') } @@ -102,9 +99,9 @@ export const verifySafeWallet = async (req: Request, res: Response) => { throw new HttpError(400, 'Unable to fetch SafeMessage') } - const threshold = BigNumber.from(await safeContract.getThreshold()).toNumber() + const threshold = BigInt(await safeContract.getThreshold()) - if (!threshold || threshold > safeMessage.confirmations.length) { + if (!threshold || threshold > BigInt(safeMessage.confirmations.length)) { throw new HttpError(400, 'Threshold has not been met') } @@ -134,5 +131,5 @@ const fetchSafeMessage = async (safeMessageHash: string, chainId: number) => { headers: { 'Content-Type': 'application/json' }, }) - return response.json() + return response.json() as Promise<{ confirmations: any[]; preparedSignature: string }> } diff --git a/onboarding-api/src/utils/networks/tinlake.ts b/onboarding-api/src/utils/networks/tinlake.ts index 954fcf91a6..be9d66eb13 100644 --- a/onboarding-api/src/utils/networks/tinlake.ts +++ b/onboarding-api/src/utils/networks/tinlake.ts @@ -1,6 +1,4 @@ -import { Contract } from '@ethersproject/contracts' -import { InfuraProvider } from '@ethersproject/providers' -import { Wallet } from '@ethersproject/wallet' +import { Contract, InfuraProvider, Wallet } from 'ethers' import { Request } from 'express' import { lastValueFrom } from 'rxjs' import { HttpError, reportHttpError } from '../httpError' @@ -196,16 +194,11 @@ export const addTinlakeInvestorToMemberList = async (wallet: Request['wallet'], : pool.addresses.JUNIOR_MEMBERLIST const OneHundredYearsFromNow = Math.floor(Date.now() / 1000 + 100 * 365 * 24 * 60 * 60) - const tx = await memberAdminContract.functions.updateMember( - memberlistAddress, - wallet.address, - OneHundredYearsFromNow, - { - gasLimit: 1000000, - // TODO: find a better number, this is causing errors on goerli - // maxPriorityFeePerGas: 4000000000, // 4 gwei - } - ) + const tx = await memberAdminContract.updateMember(memberlistAddress, wallet.address, OneHundredYearsFromNow, { + gasLimit: 1000000, + // TODO: find a better number, this is causing errors on goerli + // maxPriorityFeePerGas: 4000000000, // 4 gwei + }) const finalizedTx = await tx.wait() console.log(`tx finalized: ${finalizedTx.transactionHash}, nonce=${tx.nonce}`) return { txHash: finalizedTx.transactionHash } diff --git a/onboarding-api/tsconfig.json b/onboarding-api/tsconfig.json index b33eec1daa..85e8b74b9d 100644 --- a/onboarding-api/tsconfig.json +++ b/onboarding-api/tsconfig.json @@ -1,8 +1,10 @@ { "compilerOptions": { - "lib": ["ES2021"], + "lib": [ + "ES2021" + ], "module": "commonjs", - "target": "ES2021", + "target": "esnext", "noImplicitReturns": true, "noUnusedLocals": true, "outDir": "lib", @@ -17,4 +19,4 @@ "include": [ "src" ] -} +} \ No newline at end of file diff --git a/package.json b/package.json index 3abeb9aff3..b24b41f85a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@sendgrid/mail": "^7.7.0", "bn.js": "^5.2.1", "dotenv": "16.0.3", + "ethers": "^6.13.2", "rxjs": "^7.8.0" }, "scripts": { diff --git a/tsconfig.base.json b/tsconfig.base.json index 845b7c2114..5e1f6f57f3 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,19 +1,18 @@ { "compilerOptions": { /* Basic Options */ - "target": "es5", + "target": "esnext", "module": "commonjs", - "lib": ["ESNext"], - + "lib": [ + "ESNext" + ], /* Strict Type-Checking Options */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - /* Module Resolution Options */ "moduleResolution": "node", "esModuleInterop": true, - /* Advanced Options */ "forceConsistentCasingInFileNames": true, "skipLibCheck": true diff --git a/yarn.lock b/yarn.lock index fd10b730ab..3171e8003a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1735,9 +1735,6 @@ __metadata: "@centrifuge/centrifuge-js": "workspace:*" "@centrifuge/centrifuge-react": "workspace:*" "@centrifuge/fabric": "workspace:*" - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/contracts": ^5.6.0 - "@ethersproject/providers": ^5.6.0 "@makerdao/multicall": ^0.12.0 "@polkadot/react-identicon": ~3.1.4 "@styled-system/css": ^5.1.5 @@ -1788,11 +1785,6 @@ __metadata: version: 0.0.0-use.local resolution: "@centrifuge/centrifuge-js@workspace:centrifuge-js" dependencies: - "@ethersproject/abi": ^5.6.0 - "@ethersproject/address": ^5.6.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/contracts": ^5.6.0 - "@ethersproject/providers": ^5.6.0 "@polkadot/api": ~12.1.1 "@polkadot/keyring": ^11.1.3 "@polkadot/types": ~12.1.1 @@ -1824,10 +1816,6 @@ __metadata: "@centrifuge/centrifuge-js": "workspace:*" "@centrifuge/fabric": "workspace:*" "@coinbase/wallet-sdk": ^3.6.3 - "@ethersproject/address": ^5.6.0 - "@ethersproject/bignumber": ^5.6.0 - "@ethersproject/networks": ^5.6.0 - "@ethersproject/providers": ^5.6.0 "@finoa/finoa-connect-sdk": ^1.0.1 "@mdx-js/preact": ^2.1.1 "@mdx-js/react": ^1.6.22 @@ -1927,10 +1915,6 @@ __metadata: resolution: "@centrifuge/onboarding-api@workspace:onboarding-api" dependencies: "@centrifuge/centrifuge-js": "workspace:centrifuge-js" - "@ethersproject/address": ^5.7.0 - "@ethersproject/contracts": ^5.7.0 - "@ethersproject/providers": ^5.7.2 - "@ethersproject/wallet": ^5.7.0 "@google-cloud/firestore": ^6.8.0 "@google-cloud/functions-framework": ^3.1.3 "@google-cloud/storage": ^6.9.1 @@ -2797,52 +2781,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:^5.6.0, @ethersproject/abi@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abi@npm:5.7.0" - dependencies: - "@ethersproject/address": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - checksum: bc6962bb6cb854e4d2a4d65b2c49c716477675b131b1363312234bdbb7e19badb7d9ce66f4ca2a70ae2ea84f7123dbc4e300a1bfe5d58864a7eafabc1466627e - languageName: node - linkType: hard - -"@ethersproject/abstract-provider@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abstract-provider@npm:5.7.0" - dependencies: - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/networks": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/web": ^5.7.0 - checksum: 74cf4696245cf03bb7cc5b6cbf7b4b89dd9a79a1c4688126d214153a938126d4972d42c93182198653ce1de35f2a2cad68be40337d4774b3698a39b28f0228a8 - languageName: node - linkType: hard - -"@ethersproject/abstract-signer@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abstract-signer@npm:5.7.0" - dependencies: - "@ethersproject/abstract-provider": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - checksum: a823dac9cfb761e009851050ebebd5b229d1b1cc4a75b125c2da130ff37e8218208f7f9d1386f77407705b889b23d4a230ad67185f8872f083143e0073cbfbe3 - languageName: node - linkType: hard - -"@ethersproject/address@npm:^5, @ethersproject/address@npm:^5.6.0, @ethersproject/address@npm:^5.7.0": +"@ethersproject/address@npm:^5": version: 5.7.0 resolution: "@ethersproject/address@npm:5.7.0" dependencies: @@ -2855,26 +2794,7 @@ __metadata: languageName: node linkType: hard -"@ethersproject/base64@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/base64@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - checksum: 7dd5d734d623582f08f665434f53685041a3d3b334a0e96c0c8afa8bbcaab934d50e5b6b980e826a8fde8d353e0b18f11e61faf17468177274b8e7c69cd9742b - languageName: node - linkType: hard - -"@ethersproject/basex@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/basex@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - checksum: 326087b7e1f3787b5fe6cd1cf2b4b5abfafbc355a45e88e22e5e9d6c845b613ffc5301d629b28d5c4d5e2bfe9ec424e6782c804956dff79be05f0098cb5817de - languageName: node - linkType: hard - -"@ethersproject/bignumber@npm:^5.6.0, @ethersproject/bignumber@npm:^5.7.0": +"@ethersproject/bignumber@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/bignumber@npm:5.7.0" dependencies: @@ -2894,91 +2814,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/constants@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/constants@npm:5.7.0" - dependencies: - "@ethersproject/bignumber": ^5.7.0 - checksum: 6d4b1355747cce837b3e76ec3bde70e4732736f23b04f196f706ebfa5d4d9c2be50904a390d4d40ce77803b98d03d16a9b6898418e04ba63491933ce08c4ba8a - languageName: node - linkType: hard - -"@ethersproject/contracts@npm:^5.6.0, @ethersproject/contracts@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/contracts@npm:5.7.0" - dependencies: - "@ethersproject/abi": ^5.7.0 - "@ethersproject/abstract-provider": ^5.7.0 - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - checksum: 6ccf1121cba01b31e02f8c507cb971ab6bfed85706484a9ec09878ef1594a62215f43c4fdef8f4a4875b99c4a800bc95e3be69b1803f8ce479e07634b5a740c0 - languageName: node - linkType: hard - -"@ethersproject/hash@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/hash@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/base64": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - checksum: 6e9fa8d14eb08171cd32f17f98cc108ec2aeca74a427655f0d689c550fee0b22a83b3b400fad7fb3f41cf14d4111f87f170aa7905bcbcd1173a55f21b06262ef - languageName: node - linkType: hard - -"@ethersproject/hdnode@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/hdnode@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/basex": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/pbkdf2": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/sha2": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/wordlists": ^5.7.0 - checksum: bfe5ca2d89a42de73655f853170ef4766b933c5f481cddad709b3aca18823275b096e572f92d1602a052f80b426edde44ad6b9d028799775a7dad4a5bbed2133 - languageName: node - linkType: hard - -"@ethersproject/json-wallets@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/json-wallets@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hdnode": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/pbkdf2": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/random": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - checksum: f583458d22db62efaaf94d38dd243482776a45bf90f9f3882fbad5aa0b8fd288b41eb7c1ff8ec0b99c9b751088e43d6173530db64dd33c59f9d8daa8d7ad5aa2 - languageName: node - linkType: hard - "@ethersproject/keccak256@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/keccak256@npm:5.7.0" @@ -2996,72 +2831,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/networks@npm:^5.6.0, @ethersproject/networks@npm:^5.7.0": - version: 5.7.1 - resolution: "@ethersproject/networks@npm:5.7.1" - dependencies: - "@ethersproject/logger": ^5.7.0 - checksum: 0339f312304c17d9a0adce550edb825d4d2c8c9468c1634c44172c67a9ed256f594da62c4cda5c3837a0f28b7fabc03aca9b492f68ff1fdad337ee861b27bd5d - languageName: node - linkType: hard - -"@ethersproject/pbkdf2@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/pbkdf2@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/sha2": ^5.7.0 - checksum: b895adb9e35a8a127e794f7aadc31a2424ef355a70e51cde10d457e3e888bb8102373199a540cf61f2d6b9a32e47358f9c65b47d559f42bf8e596b5fd67901e9 - languageName: node - linkType: hard - -"@ethersproject/properties@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/properties@npm:5.7.0" - dependencies: - "@ethersproject/logger": ^5.7.0 - checksum: 6ab0ccf0c3aadc9221e0cdc5306ce6cd0df7f89f77d77bccdd1277182c9ead0202cd7521329ba3acde130820bf8af299e17cf567d0d497c736ee918207bbf59f - languageName: node - linkType: hard - -"@ethersproject/providers@npm:^5.6.0, @ethersproject/providers@npm:^5.7.2": - version: 5.7.2 - resolution: "@ethersproject/providers@npm:5.7.2" - dependencies: - "@ethersproject/abstract-provider": ^5.7.0 - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/base64": ^5.7.0 - "@ethersproject/basex": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/networks": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/random": ^5.7.0 - "@ethersproject/rlp": ^5.7.0 - "@ethersproject/sha2": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/web": ^5.7.0 - bech32: 1.1.4 - ws: 7.4.6 - checksum: 1754c731a5ca6782ae9677f4a9cd8b6246c4ef21a966c9a01b133750f3c578431ec43ec254e699969c4a0f87e84463ded50f96b415600aabd37d2056aee58c19 - languageName: node - linkType: hard - -"@ethersproject/random@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/random@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - checksum: 017829c91cff6c76470852855108115b0b52c611b6be817ed1948d56ba42d6677803ec2012aa5ae298a7660024156a64c11fcf544e235e239ab3f89f0fff7345 - languageName: node - linkType: hard - "@ethersproject/rlp@npm:^5.7.0": version: 5.7.0 resolution: "@ethersproject/rlp@npm:5.7.0" @@ -3072,108 +2841,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/sha2@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/sha2@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - hash.js: 1.1.7 - checksum: 09321057c022effbff4cc2d9b9558228690b5dd916329d75c4b1ffe32ba3d24b480a367a7cc92d0f0c0b1c896814d03351ae4630e2f1f7160be2bcfbde435dbc - languageName: node - linkType: hard - -"@ethersproject/signing-key@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/signing-key@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - bn.js: ^5.2.1 - elliptic: 6.5.4 - hash.js: 1.1.7 - checksum: 8f8de09b0aac709683bbb49339bc0a4cd2f95598f3546436c65d6f3c3a847ffa98e06d35e9ed2b17d8030bd2f02db9b7bd2e11c5cf8a71aad4537487ab4cf03a - languageName: node - linkType: hard - -"@ethersproject/strings@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/strings@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - checksum: 5ff78693ae3fdf3cf23e1f6dc047a61e44c8197d2408c42719fef8cb7b7b3613a4eec88ac0ed1f9f5558c74fe0de7ae3195a29ca91a239c74b9f444d8e8b50df - languageName: node - linkType: hard - -"@ethersproject/transactions@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/transactions@npm:5.7.0" - dependencies: - "@ethersproject/address": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/constants": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/rlp": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - checksum: a31b71996d2b283f68486241bff0d3ea3f1ba0e8f1322a8fffc239ccc4f4a7eb2ea9994b8fd2f093283fd75f87bae68171e01b6265261f821369aca319884a79 - languageName: node - linkType: hard - -"@ethersproject/wallet@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/wallet@npm:5.7.0" - dependencies: - "@ethersproject/abstract-provider": ^5.7.0 - "@ethersproject/abstract-signer": ^5.7.0 - "@ethersproject/address": ^5.7.0 - "@ethersproject/bignumber": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/hdnode": ^5.7.0 - "@ethersproject/json-wallets": ^5.7.0 - "@ethersproject/keccak256": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/random": ^5.7.0 - "@ethersproject/signing-key": ^5.7.0 - "@ethersproject/transactions": ^5.7.0 - "@ethersproject/wordlists": ^5.7.0 - checksum: a4009bf7331eddab38e3015b5e9101ef92de7f705b00a6196b997db0e5635b6d83561674d46c90c6f77b87c0500fe4a6b0183ba13749efc22db59c99deb82fbd - languageName: node - linkType: hard - -"@ethersproject/web@npm:^5.7.0": - version: 5.7.1 - resolution: "@ethersproject/web@npm:5.7.1" - dependencies: - "@ethersproject/base64": ^5.7.0 - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - checksum: 7028c47103f82fd2e2c197ce0eecfacaa9180ffeec7de7845b1f4f9b19d84081b7a48227aaddde05a4aaa526af574a9a0ce01cc0fc75e3e371f84b38b5b16b2b - languageName: node - linkType: hard - -"@ethersproject/wordlists@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/wordlists@npm:5.7.0" - dependencies: - "@ethersproject/bytes": ^5.7.0 - "@ethersproject/hash": ^5.7.0 - "@ethersproject/logger": ^5.7.0 - "@ethersproject/properties": ^5.7.0 - "@ethersproject/strings": ^5.7.0 - checksum: 30eb6eb0731f9ef5faa44bf9c0c6e950bcaaef61e4d2d9ce0ae6d341f4e2d6d1f4ab4f8880bfce03b7aac4b862fb740e1421170cfbf8e2aafc359277d49e6e97 - languageName: node - linkType: hard - "@fal-works/esbuild-plugin-global-externals@npm:^2.1.2": version: 2.1.2 resolution: "@fal-works/esbuild-plugin-global-externals@npm:2.1.2" @@ -12076,13 +11743,6 @@ __metadata: languageName: node linkType: hard -"bech32@npm:1.1.4": - version: 1.1.4 - resolution: "bech32@npm:1.1.4" - checksum: 0e98db619191548390d6f09ff68b0253ba7ae6a55db93dfdbb070ba234c1fd3308c0606fbcc95fad50437227b10011e2698b89f0181f6e7f845c499bd14d0f4b - languageName: node - linkType: hard - "better-opn@npm:^3.0.2": version: 3.0.2 resolution: "better-opn@npm:3.0.2" @@ -16507,6 +16167,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.13.2": + version: 6.13.2 + resolution: "ethers@npm:6.13.2" + dependencies: + "@adraffy/ens-normalize": 1.10.1 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 + "@types/node": 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.17.1 + checksum: 981860c736c7ae121774ad38ea07e3611ce524a77d2fcb77db499b65afe0cbe8f344cd5204d94b68b316349ff770fd2a7d9c8b2039da41c072f98d9864099925 + languageName: node + linkType: hard + "ethers@npm:^6.7.1": version: 6.11.1 resolution: "ethers@npm:6.11.1" @@ -18243,7 +17918,7 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": +"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": version: 1.1.7 resolution: "hash.js@npm:1.1.7" dependencies: @@ -25007,6 +24682,7 @@ __metadata: dotenv: 16.0.3 esbuild: ^0.16.17 esbuild-node-externals: ^1.6.0 + ethers: ^6.13.2 husky: ^6.0.0 prettier: ^2.4.1 prettier-plugin-organize-imports: 3.2.4 @@ -25146,13 +24822,6 @@ __metadata: languageName: node linkType: hard -"scrypt-js@npm:3.0.1": - version: 3.0.1 - resolution: "scrypt-js@npm:3.0.1" - checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 - languageName: node - linkType: hard - "seek-bzip@npm:^1.0.5": version: 1.0.6 resolution: "seek-bzip@npm:1.0.6" @@ -28519,24 +28188,24 @@ __metadata: languageName: node linkType: hard -"ws@npm:7.4.6": - version: 7.4.6 - resolution: "ws@npm:7.4.6" +"ws@npm:8.13.0": + version: 8.13.0 + resolution: "ws@npm:8.13.0" peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: ">=5.0.2" peerDependenciesMeta: bufferutil: optional: true utf-8-validate: optional: true - checksum: 3a990b32ed08c72070d5e8913e14dfcd831919205be52a3ff0b4cdd998c8d554f167c9df3841605cde8b11d607768cacab3e823c58c96a5c08c987e093eb767a + checksum: 53e991bbf928faf5dc6efac9b8eb9ab6497c69feeb94f963d648b7a3530a720b19ec2e0ec037344257e05a4f35bd9ad04d9de6f289615ffb133282031b18c61c languageName: node linkType: hard -"ws@npm:8.13.0": - version: 8.13.0 - resolution: "ws@npm:8.13.0" +"ws@npm:8.17.1": + version: 8.17.1 + resolution: "ws@npm:8.17.1" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -28545,7 +28214,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 53e991bbf928faf5dc6efac9b8eb9ab6497c69feeb94f963d648b7a3530a720b19ec2e0ec037344257e05a4f35bd9ad04d9de6f289615ffb133282031b18c61c + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf languageName: node linkType: hard From ae845111e595d2286060567c60cf04789cf335ed Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 27 Aug 2024 11:18:15 -0400 Subject: [PATCH 09/26] Do manual health check on rpcs instead of relying on getDefaultBrowser for more reliable rpc connections --- centrifuge-app/.env-config/.env.altair | 1 + centrifuge-app/.env-config/.env.catalyst | 3 +- centrifuge-app/.env-config/.env.demo | 1 + centrifuge-app/.env-config/.env.development | 1 + centrifuge-app/.env-config/.env.example | 1 + centrifuge-app/.env-config/.env.ff-prod | 3 +- centrifuge-app/.env-config/.env.production | 3 +- centrifuge-app/declarations.d.ts | 1 + .../InvestRedeemLiquidityPoolsProvider.tsx | 5 ++- .../components/PoolOverview/KeyMetrics.tsx | 2 +- centrifuge-app/src/components/Root.tsx | 2 - centrifuge-app/src/config.ts | 12 ++++-- .../src/utils/tinlake/useEvmTransaction.ts | 2 +- centrifuge-js/src/modules/liquidityPools.ts | 4 +- .../WalletProvider/WalletProvider.tsx | 40 ++++++++----------- .../components/WalletProvider/evm/utils.ts | 6 +-- 16 files changed, 46 insertions(+), 41 deletions(-) diff --git a/centrifuge-app/.env-config/.env.altair b/centrifuge-app/.env-config/.env.altair index 884e2b033a..d63326a6ef 100644 --- a/centrifuge-app/.env-config/.env.altair +++ b/centrifuge-app/.env-config/.env.altair @@ -20,3 +20,4 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 diff --git a/centrifuge-app/.env-config/.env.catalyst b/centrifuge-app/.env-config/.env.catalyst index 8e98e86a2e..3803d0cca8 100644 --- a/centrifuge-app/.env-config/.env.catalyst +++ b/centrifuge-app/.env-config/.env.catalyst @@ -19,4 +19,5 @@ REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=4bo2vNkwZtr2PuqppWwqya6dPC8MzxqZ4kgnAoTZyK REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn -REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc \ No newline at end of file +REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.demo b/centrifuge-app/.env-config/.env.demo index 887b028ef7..84202b0e55 100644 --- a/centrifuge-app/.env-config/.env.demo +++ b/centrifuge-app/.env-config/.env.demo @@ -20,3 +20,4 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 diff --git a/centrifuge-app/.env-config/.env.development b/centrifuge-app/.env-config/.env.development index 887b028ef7..84202b0e55 100644 --- a/centrifuge-app/.env-config/.env.development +++ b/centrifuge-app/.env-config/.env.development @@ -20,3 +20,4 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 diff --git a/centrifuge-app/.env-config/.env.example b/centrifuge-app/.env-config/.env.example index d7cac13f79..6afb90e0e6 100644 --- a/centrifuge-app/.env-config/.env.example +++ b/centrifuge-app/.env-config/.env.example @@ -20,3 +20,4 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc +REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 diff --git a/centrifuge-app/.env-config/.env.ff-prod b/centrifuge-app/.env-config/.env.ff-prod index dd1ee7b41e..73617dfb5b 100644 --- a/centrifuge-app/.env-config/.env.ff-prod +++ b/centrifuge-app/.env-config/.env.ff-prod @@ -19,4 +19,5 @@ REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kALJqPUHFzDR2VkoQYWefPQyzjGzKznNny2smXGQpS REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=4dpEcgqJRyJK3J8Es6v8ZfVntV7c64Ysgcjd4hYwyGoFPWbg -REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 \ No newline at end of file +REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 +REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.production b/centrifuge-app/.env-config/.env.production index 87db551428..02fb25f56c 100644 --- a/centrifuge-app/.env-config/.env.production +++ b/centrifuge-app/.env-config/.env.production @@ -19,4 +19,5 @@ REACT_APP_MEMBERLIST_ADMIN_PURE_PROXY=kALJqPUHFzDR2VkoQYWefPQyzjGzKznNny2smXGQpS REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=4dpEcgqJRyJK3J8Es6v8ZfVntV7c64Ysgcjd4hYwyGoFPWbg -REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 \ No newline at end of file +REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 +REACT_APP_ONFINALITY_KEY=84bb59f4-05cc-440b-8fd4-7917623a90c6 \ No newline at end of file diff --git a/centrifuge-app/declarations.d.ts b/centrifuge-app/declarations.d.ts index be67d42803..77543f37c3 100644 --- a/centrifuge-app/declarations.d.ts +++ b/centrifuge-app/declarations.d.ts @@ -17,4 +17,5 @@ interface ImportMetaEnv { REACT_APP_ALCHEMY_KEY: string REACT_APP_WALLETCONNECT_ID: string REACT_APP_PRIME_IPFS_HASH: string + REACT_APP_ONFINALITY_KEY: string } diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx index 5585bcf956..17ae872ad1 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx @@ -48,7 +48,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children const tranche = pool.tranches.find((t) => t.id === trancheId) const { data: metadata, isLoading: isMetadataLoading } = usePoolMetadata(pool) const trancheMeta = metadata?.tranches?.[trancheId] - const chainId = provider?.network.chainId || 1 + const chainId = Number(provider?._network.chainId) || 1 if (!tranche) throw new Error(`Token not found. Pool id: ${poolId}, token id: ${trancheId}`) @@ -228,12 +228,13 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children // If the last tx was an approve, we may not have refetched the allowance yet, // so assume the allowance is enough to do a normal invest else if (lpInvest.lpCurrencyAllowance.lt(assets) && supportsPermits && pendingAction !== 'approvePoolCurrency') { - const signer = provider!.getSigner() + const signer = await provider!.getSigner() const connectedCent = cent.connectEvm(evmAddress!, signer) const permit = await connectedCent.liquidityPools.signPermit([ lpInvest.lpAddress, lpInvest.currency.address, assets, + chainId, ]) console.log('permit', permit) // investWithPermit.execute([lpInvest.lpAddress, assets, permit]) diff --git a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index cb2420a879..3838a9c27f 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -184,7 +184,7 @@ const AvailableNetworks = ({ poolId }: { poolId: string }) => { )} {activeDomains.data - ?.filter((domain) => domain.isActive) + ?.filter((domain) => domain.isActive && domain.chainId !== 5) .map((domain) => { const chain = (evmChains as any)[domain.chainId] return ( diff --git a/centrifuge-app/src/components/Root.tsx b/centrifuge-app/src/components/Root.tsx index e5183d9c22..3d1798c806 100644 --- a/centrifuge-app/src/components/Root.tsx +++ b/centrifuge-app/src/components/Root.tsx @@ -85,8 +85,6 @@ export function Root() { showAdvancedAccounts={debugState.showAdvancedAccounts} showTestNets={debugState.showTestNets} showFinoa={debugState.showFinoa} - alchemyKey={import.meta.env.REACT_APP_ALCHEMY_KEY} - infuraKey={import.meta.env.REACT_APP_INFURA_KEY} > diff --git a/centrifuge-app/src/config.ts b/centrifuge-app/src/config.ts index 575dd3fdb9..5caf01fb74 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -123,7 +123,7 @@ const CENTRIFUGE: EnvironmentConfig = { const ethNetwork = import.meta.env.REACT_APP_TINLAKE_NETWORK || 'mainnet' const alchemyKey = import.meta.env.REACT_APP_ALCHEMY_KEY - +const onfinalityKey = import.meta.env.REACT_APP_ONFINALITY_KEY export const ethConfig = { rpcUrl: `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, chainId: 1, @@ -156,7 +156,10 @@ export const evmChains: EvmChains = { decimals: 18, }, blockExplorerUrl: 'https://etherscan.io/', - urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], + urls: [ + `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, + `https://eth.api.onfinality.io/rpc?apikey=${onfinalityKey}`, + ], iconUrl: ethereumLogo, isTestnet: false, }, @@ -164,7 +167,10 @@ export const evmChains: EvmChains = { name: 'Ethereum Sepolia', nativeCurrency: { name: 'Sepolia Ether', symbol: 'sepETH', decimals: 18 }, blockExplorerUrl: 'https://sepolia.etherscan.io/', - urls: [`https://eth-sepolia.g.alchemy.com/v2/${alchemyKey}`], + urls: [ + `https://eth-sepolia.g.alchemy.com/v2/${alchemyKey}`, + `https://eth-sepolia.api.onfinality.io/rpc?apikey=${onfinalityKey}`, + ], iconUrl: sepoliaLogo, isTestnet: true, }, diff --git a/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts b/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts index 9857947811..8b8b45655b 100644 --- a/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts +++ b/centrifuge-app/src/utils/tinlake/useEvmTransaction.ts @@ -29,7 +29,7 @@ export function useEvmTransaction>( async function doTransaction(id: string, args: T, txOptions?: TransactionRequest) { try { - const signer = provider!.getSigner() + const signer = await provider!.getSigner() const connectedCent = centrifuge.connectEvm(selectedAddress!, signer) const transaction = transactionCallback(connectedCent) updateTransaction(id, { status: 'unconfirmed' }) diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index ea0f03906e..ff96db20b5 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -483,7 +483,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const currencyData = await multicall<{ currencies: { currencySupportsPermit?: boolean }[] trancheTokenSymbol: string - trancheTokenDecimals: number + trancheTokenDecimals: BigInt }>( [ ...Object.values(currenciesByLpAddress).flatMap( @@ -521,7 +521,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { managerAddress, trancheTokenAddress: shareData.share, trancheTokenSymbol: currencyData.trancheTokenSymbol, - trancheTokenDecimals: currencyData.trancheTokenDecimals, + trancheTokenDecimals: Number(currencyData.trancheTokenDecimals), currencySupportsPermit: currencyData.currencies?.[i]?.currencySupportsPermit, })) return result diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index b4faafc734..93b07b9b4f 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -4,7 +4,7 @@ import { getWallets } from '@subwallet/wallet-connect/dotsama/wallets' import { Wallet } from '@subwallet/wallet-connect/types' import { Web3ReactState } from '@web3-react/types' import { WalletConnect as WalletConnectV2 } from '@web3-react/walletconnect-v2' -import { getDefaultProvider, JsonRpcProvider, Networkish, Provider } from 'ethers' +import { JsonRpcProvider, Provider } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { firstValueFrom, map, switchMap } from 'rxjs' @@ -129,12 +129,10 @@ type WalletProviderProps = { showAdvancedAccounts?: boolean showTestNets?: boolean showFinoa?: boolean - alchemyKey?: string - infuraKey?: string } let cachedEvmConnectors: EvmConnectorMeta[] | undefined = undefined -const cachedProviders = new Map() +const cachedProviders = new Map() export function WalletProvider({ children, @@ -150,8 +148,6 @@ export function WalletProvider({ showAdvancedAccounts, showTestNets, showFinoa, - alchemyKey, - infuraKey, }: WalletProviderProps) { if (!evmChainsProp[1]?.urls[0]) throw new Error('Mainnet should be defined in EVM Chains') @@ -244,28 +240,26 @@ export function WalletProvider({ const [proxies] = useCentrifugeQuery(['allProxies'], (cent) => cent.proxies.getAllProxies()) - function getProvider(networkish: Networkish) { - let network = networkish - const cachedProvider = cachedProviders.get(network) - if (cachedProvider) { - return cachedProvider - } else { + async function findHealthyProvider(chainId: number, urls: string[]): Promise { + for (const url of urls) { try { - const provider = getDefaultProvider(network, { - alchemy: alchemyKey, - infura: infuraKey, - }) - cachedProviders.set(network, provider) + const provider = new JsonRpcProvider(url, chainId) + await provider.getBlockNumber() + cachedProviders.set(chainId, provider) return provider } catch (error) { - if (typeof network === 'number') { - const provider = new JsonRpcProvider((evmChains as any)[network].urls[0], network) - cachedProviders.set(network, provider) - return provider - } - throw error + console.error(`Provider health check failed for ${url}:`, error) } } + throw new Error(`No healthy provider found for chain ${chainId}`) + } + + function getProvider(chainId: number): JsonRpcProvider { + const urls = (evmChains as any)[chainId].urls + if (!cachedProviders.has(chainId)) { + findHealthyProvider(chainId, urls).catch(console.error) + } + return cachedProviders.get(chainId) || new JsonRpcProvider(urls[0], chainId) } function setFilteredAccounts(accounts: SubstrateAccount[]) { diff --git a/centrifuge-react/src/components/WalletProvider/evm/utils.ts b/centrifuge-react/src/components/WalletProvider/evm/utils.ts index 7b969c0c45..4ac5f87802 100644 --- a/centrifuge-react/src/components/WalletProvider/evm/utils.ts +++ b/centrifuge-react/src/components/WalletProvider/evm/utils.ts @@ -8,6 +8,7 @@ import { createWeb3ReactStoreAndActions } from '@web3-react/store' import { Actions, Provider as Web3ReactProvider, Web3ReactState, Web3ReactStore } from '@web3-react/types' import { WalletConnect as WalletConnectV2 } from '@web3-react/walletconnect-v2' import type { Networkish } from 'ethers' +import { BrowserProvider } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { useWallet } from '../WalletProvider' @@ -49,10 +50,7 @@ function getProviderKey(connector: Connector) { return providerKey } -export function useProviderForConnector( - connector?: Connector | null, - network?: Networkish -) { +export function useProviderForConnector(connector?: Connector | null, network?: Networkish) { const conn = connector ?? emptyConnector const state = useConnectorState(conn) const isActive = computeIsActive(state) From a214de953be8aed0763660fcd8281952c8dbad65 Mon Sep 17 00:00:00 2001 From: sophian Date: Tue, 27 Aug 2024 11:28:08 -0400 Subject: [PATCH 10/26] Fix ts error --- .../src/pages/Onboarding/queries/useSignRemark.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts b/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts index 6eec6e9b03..0cff17925a 100644 --- a/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts +++ b/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts @@ -149,11 +149,13 @@ export const useSignRemark = ( try { const [message] = args const remarkerContract = new Contract(ethConfig.remarkerAddress, RemarkerAbi) - if (!evmProvider?.getSigner()) { + const signer = await evmProvider?.getSigner() + if (!signer) { throw new Error('Signer may not be set') } - const connectedContract = remarkerContract.connect(evmProvider?.getSigner()) - const result = await connectedContract.functions.remarkWithEvent(message) + const connectedContract = remarkerContract.connect(signer) as Contract + + const result = await connectedContract.remarkWithEvent(message) updateTransaction(txId, () => ({ status: 'pending', hash: result.hash, From 091a710ed098db87331302109119fec6eda16fb9 Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 28 Aug 2024 10:16:11 -0400 Subject: [PATCH 11/26] Fix more type errros from upgrade --- centrifuge-app/src/components/LiquidityEpochSection.tsx | 5 +++-- centrifuge-js/src/utils/evmMulticall.ts | 6 +++++- centrifuge-react/src/hooks/useCentrifugeTransaction.ts | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/centrifuge-app/src/components/LiquidityEpochSection.tsx b/centrifuge-app/src/components/LiquidityEpochSection.tsx index 29f8b03744..120238cf1b 100644 --- a/centrifuge-app/src/components/LiquidityEpochSection.tsx +++ b/centrifuge-app/src/components/LiquidityEpochSection.tsx @@ -8,6 +8,7 @@ import { useWallet, } from '@centrifuge/centrifuge-react' import { Button, IconInfo, Shelf, Stack, Text } from '@centrifuge/fabric' +import { Contract } from 'ethers' import * as React from 'react' import { switchMap } from 'rxjs' import { Dec } from '../utils/Decimal' @@ -337,9 +338,9 @@ function TinlakeEpochStatus({ pool }: { pool: TinlakePool }) { (cent) => cent.tinlake.closeEpoch, { onSuccess: async () => { - const signer = provider!.getSigner() + const signer = await provider!.getSigner() const connectedCent = cent.connectEvm(selectedAddress!, signer) - const coordinator = connectedCent.tinlake.contract(pool.addresses, undefined, 'COORDINATOR') + const coordinator = connectedCent.tinlake.contract(pool.addresses, undefined, 'COORDINATOR') as Contract if ((await coordinator.submissionPeriod()) === true) { // didn't execute right away, run solver solveEpochTx([]) diff --git a/centrifuge-js/src/utils/evmMulticall.ts b/centrifuge-js/src/utils/evmMulticall.ts index 00025e8be1..d4595d2abc 100644 --- a/centrifuge-js/src/utils/evmMulticall.ts +++ b/centrifuge-js/src/utils/evmMulticall.ts @@ -50,7 +50,11 @@ export async function multicall>(calls: Call[], options: const interfaces = calls.map((c) => { const int = new Interface([c.call[0] as string]) - return [int, int.fragments[0].name] as const + const functionFragment = int.getFunction(c.call[0] as string) + if (!functionFragment) { + throw new Error(`Function ${c.call[0]} not found in interface`) + } + return [int, functionFragment.name] as const }) const encoded = calls.map((c, i) => ({ target: c.target, diff --git a/centrifuge-react/src/hooks/useCentrifugeTransaction.ts b/centrifuge-react/src/hooks/useCentrifugeTransaction.ts index 60b319507e..52630385a4 100644 --- a/centrifuge-react/src/hooks/useCentrifugeTransaction.ts +++ b/centrifuge-react/src/hooks/useCentrifugeTransaction.ts @@ -53,7 +53,8 @@ export function useCentrifugeTransaction>( try { let connectedCent if (isEvmOnSubstrate) { - connectedCent = cent.connectEvm(evm.selectedAddress!, provider!.getSigner(), substrate.evmChainId!) + const signer = await provider!.getSigner() + connectedCent = cent.connectEvm(evm.selectedAddress!, signer, substrate.evmChainId!) } else { connectedCent = cent.connect(account.signingAccount?.address, account.signingAccount?.signer as any) } From a7ef87a09b43a29b8e1a72a6ff7e7d821f313406 Mon Sep 17 00:00:00 2001 From: sophian Date: Thu, 29 Aug 2024 13:16:36 -0400 Subject: [PATCH 12/26] Add connection checks to centrifuge base before connecting to parachain --- centrifuge-js/src/CentrifugeBase.ts | 138 +++++++++++++++--- .../WalletProvider/WalletProvider.tsx | 2 +- 2 files changed, 118 insertions(+), 22 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index af551d2375..88c1bfd787 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -7,6 +7,7 @@ import { sortAddresses } from '@polkadot/util-crypto' import type { JsonRpcSigner, TransactionRequest } from 'ethers' import 'isomorphic-fetch' import { + BehaviorSubject, Observable, Subject, bufferCount, @@ -19,6 +20,7 @@ import { map, mergeWith, of, + race, share, startWith, switchMap, @@ -26,6 +28,7 @@ import { takeWhile, tap, throwError, + timer, } from 'rxjs' import { fromFetch } from 'rxjs/fetch' import { TransactionErrorResult, TransactionOptions, TransactionResult } from './types' @@ -298,16 +301,89 @@ const blockEvents: Record> = {} export class CentrifugeBase { config: Config - parachainUrl: string relayChainUrl: string subqueryUrl: string + rpcEndpoints: string[] + private parachainUrlCache: BehaviorSubject // cache the healthy parachain url + private healthCheckInProgress: Promise | null = null // prevent concurrent health checks constructor(config: UserProvidedConfig = {}) { this.config = { ...defaultConfig, ...config } - this.parachainUrl = this.config.network === 'centrifuge' ? this.config.centrifugeWsUrl : this.config.altairWsUrl this.relayChainUrl = this.config.network === 'centrifuge' ? this.config.polkadotWsUrl : this.config.kusamaWsUrl this.subqueryUrl = this.config.network === 'centrifuge' ? this.config.centrifugeSubqueryUrl : this.config.altairSubqueryUrl + this.rpcEndpoints = this.config.centrifugeWsUrl.split(',').map((url) => url.trim()) + this.parachainUrlCache = new BehaviorSubject(null) + this.initParachainUrl() + } + + private initParachainUrl() { + if (!this.healthCheckInProgress) { + this.healthCheckInProgress = this.findHealthyWs().then((url) => { + this.parachainUrlCache.next(url) + this.healthCheckInProgress = null + return url + }) + } + return this.healthCheckInProgress + } + + private findHealthyWs(): Promise { + return firstValueFrom( + from(this.rpcEndpoints).pipe( + switchMap((url) => this.checkWsHealth(url)), + map((url) => { + if (url) { + console.log(`Connection to ${url} established`) + return url + } + throw new Error('No healthy parachain URL found') + }), + catchError((error) => { + console.error('Error establishing connection to parachain URL:', error) + return of(null) + }) + ) + ) + } + + private checkWsHealth(url: string, timeoutMs: number = 5000): Observable { + return race( + new Observable((observer) => { + const ws = new WebSocket(url) + ws.onopen = () => { + ws.close() + observer.next(url) + observer.complete() + } + ws.onerror = () => { + ws.close() + observer.next(null) + observer.complete() + } + return () => ws.close() + }), + timer(timeoutMs).pipe(map(() => null)) + ).pipe( + tap((result) => { + if (result === null) { + console.log(`Connection to ${url} failed or timed out`) + } + }) + ) + } + + private async getCachedParachainUrl(): Promise { + const cachedUrl = this.parachainUrlCache.getValue() + if (cachedUrl) { + return cachedUrl + } + await this.findHealthyWs() + const parachainUrl = this.parachainUrlCache.getValue() + if (!parachainUrl) { + throw new Error('No healthy parachain URL available') + } + return parachainUrl } async getChainId() { @@ -459,7 +535,13 @@ export class CentrifugeBase { }), tap((result) => { options?.onStatusChange?.(result) - if (result.status === 'InBlock') this.getTxCompletedEvents().next(result.events) + if (result.status === 'InBlock') { + from(this.getTxCompletedEvents()) + .pipe(take(1)) + .subscribe((subject) => { + subject.next(result.events) + }) + } }), takeWhile((result) => { return result.status !== 'InBlock' && !result.error @@ -593,39 +675,53 @@ export class CentrifugeBase { } getBlockEvents() { - if (blockEvents[this.parachainUrl]) return blockEvents[this.parachainUrl] - const $api = this.getApi() - - return (blockEvents[this.parachainUrl] = $api.pipe( - switchMap((api) => - api.queryMulti([api.query.system.events, api.query.system.number]).pipe( - bufferCount(2, 1), // Delay the events by one block, to make sure storage has been updated - filter(([[events]]) => !!(events as any)?.length), - map(([[events]]) => events as any) - ) - ), - share() - )) + return from(this.getCachedParachainUrl()).pipe( + switchMap((url) => { + if (blockEvents[url]) return blockEvents[url] + const $api = this.getApi() + + return (blockEvents[url] = $api.pipe( + switchMap((api) => + api.queryMulti([api.query.system.events, api.query.system.number]).pipe( + bufferCount(2, 1), + filter(([[events]]) => !!(events as any)?.length), + map(([[events]]) => events as any) + ) + ), + share() + )) + }) + ) } - getTxCompletedEvents() { - return txCompletedEvents[this.parachainUrl] || (txCompletedEvents[this.parachainUrl] = new Subject()) + async getTxCompletedEvents() { + const parachainUrl = await this.getCachedParachainUrl() + if (!txCompletedEvents[parachainUrl]) { + txCompletedEvents[parachainUrl] = new Subject() + } + return txCompletedEvents[parachainUrl] } getEvents() { return this.getBlockEvents().pipe( - mergeWith(this.getTxCompletedEvents()), + mergeWith(from(this.getTxCompletedEvents())), combineLatestWith(this.getApi()), map(([events, api]) => ({ events, api })) ) } getApi() { - return getPolkadotApi(this.parachainUrl, parachainTypes, parachainRpcMethods, parachainRuntimeApi) + return from(this.getCachedParachainUrl()).pipe( + switchMap((parachainUrl) => + getPolkadotApi(parachainUrl, parachainTypes, parachainRpcMethods, parachainRuntimeApi) + ) + ) } getApiPromise() { - return firstValueFrom(getPolkadotApi(this.parachainUrl, parachainTypes, parachainRpcMethods, parachainRuntimeApi)) + return this.getCachedParachainUrl().then((parachainUrl) => + firstValueFrom(getPolkadotApi(parachainUrl, parachainTypes, parachainRpcMethods, parachainRuntimeApi)) + ) } getRelayChainApi() { diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index 93b07b9b4f..4d3b893bc8 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -156,7 +156,7 @@ export function WalletProvider({ const centEvmChainId = useCentEvmChainId() const evmChains = React.useMemo(() => { - const centUrl = new URL(cent.parachainUrl) + const centUrl = new URL(cent.config.centrifugeWsUrl.split(',')[0]) centUrl.protocol = 'https:' const chains = { ...evmChainsProp, From f973f503d5518d26b2a394152250450dd4f81992 Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 4 Sep 2024 19:01:10 -0400 Subject: [PATCH 13/26] Clean up substrate network detection --- centrifuge-js/src/CentrifugeBase.ts | 96 +++++++++++------------------ 1 file changed, 35 insertions(+), 61 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index 603746ee4f..b7e8e03cc9 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -7,7 +7,6 @@ import { sortAddresses } from '@polkadot/util-crypto' import type { JsonRpcSigner, TransactionRequest } from 'ethers' import 'isomorphic-fetch' import { - BehaviorSubject, Observable, Subject, bufferCount, @@ -20,7 +19,6 @@ import { map, mergeWith, of, - race, share, startWith, switchMap, @@ -28,7 +26,6 @@ import { takeWhile, tap, throwError, - timer, } from 'rxjs' import { fromFetch } from 'rxjs/fetch' import { TransactionErrorResult, TransactionOptions, TransactionResult } from './types' @@ -298,14 +295,13 @@ type Events = ISubmittableResult['events'] const txCompletedEvents: Record> = {} const blockEvents: Record> = {} +let parachainUrlCache: string | null = null export class CentrifugeBase { config: Config relayChainUrl: string subqueryUrl: string rpcEndpoints: string[] - private parachainUrlCache: BehaviorSubject // cache the healthy parachain url - private healthCheckInProgress: Promise | null = null // prevent concurrent health checks constructor(config: UserProvidedConfig = {}) { this.config = { ...defaultConfig, ...config } @@ -313,77 +309,55 @@ export class CentrifugeBase { this.subqueryUrl = this.config.network === 'centrifuge' ? this.config.centrifugeSubqueryUrl : this.config.altairSubqueryUrl this.rpcEndpoints = this.config.centrifugeWsUrl.split(',').map((url) => url.trim()) - this.parachainUrlCache = new BehaviorSubject(null) - this.initParachainUrl() } - private initParachainUrl() { - if (!this.healthCheckInProgress) { - this.healthCheckInProgress = this.findHealthyWs().then((url) => { - this.parachainUrlCache.next(url) - this.healthCheckInProgress = null + private async findHealthyWs(): Promise { + for (const url of this.rpcEndpoints) { + const isHealthy = await this.checkWsHealth(url) + if (isHealthy) { + console.log(`Connection to ${url} established`) return url - }) + } } - return this.healthCheckInProgress - } - private findHealthyWs(): Promise { - return firstValueFrom( - from(this.rpcEndpoints).pipe( - switchMap((url) => this.checkWsHealth(url)), - map((url) => { - if (url) { - console.log(`Connection to ${url} established`) - return url - } - throw new Error('No healthy parachain URL found') - }), - catchError((error) => { - console.error('Error establishing connection to parachain URL:', error) - return of(null) - }) - ) - ) + console.error('Error: No healthy parachain URL found') + return null } - private checkWsHealth(url: string, timeoutMs: number = 5000): Observable { - return race( - new Observable((observer) => { - const ws = new WebSocket(url) - ws.onopen = () => { - ws.close() - observer.next(url) - observer.complete() - } - ws.onerror = () => { - ws.close() - observer.next(null) - observer.complete() - } - return () => ws.close() - }), - timer(timeoutMs).pipe(map(() => null)) - ).pipe( - tap((result) => { - if (result === null) { - console.log(`Connection to ${url} failed or timed out`) - } - }) - ) + private checkWsHealth(url: string, timeoutMs: number = 5000): Promise { + return new Promise((resolve) => { + const ws = new WebSocket(url) + const timer = setTimeout(() => { + ws.close() + console.log(`Connection to ${url} timed out`) + resolve(false) + }, timeoutMs) + + ws.onopen = () => { + clearTimeout(timer) + ws.close() + resolve(true) + } + + ws.onerror = () => { + clearTimeout(timer) + ws.close() + console.log(`Connection to ${url} failed`) + resolve(false) + } + }) } private async getCachedParachainUrl(): Promise { - const cachedUrl = this.parachainUrlCache.getValue() + const cachedUrl = parachainUrlCache if (cachedUrl) { return cachedUrl } - await this.findHealthyWs() - const parachainUrl = this.parachainUrlCache.getValue() - if (!parachainUrl) { + parachainUrlCache = await this.findHealthyWs() + if (!parachainUrlCache) { throw new Error('No healthy parachain URL available') } - return parachainUrl + return parachainUrlCache } async getChainId() { From 470a40921504a29d8265c9c9af6c8adb8af04147 Mon Sep 17 00:00:00 2001 From: sophian Date: Thu, 5 Sep 2024 18:15:02 -0400 Subject: [PATCH 14/26] Fix event parsing --- centrifuge-js/src/CentrifugeBase.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index b7e8e03cc9..bf893165a7 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -1,6 +1,6 @@ import { ApiRx } from '@polkadot/api' import { AddressOrPair, SubmittableExtrinsic } from '@polkadot/api/types' -import { SignedBlock } from '@polkadot/types/interfaces' +import { EventRecord, SignedBlock } from '@polkadot/types/interfaces' import { DefinitionRpc, DefinitionsCall, ISubmittableResult, Signer } from '@polkadot/types/types' import { hexToBn } from '@polkadot/util' import { sortAddresses } from '@polkadot/util-crypto' @@ -17,6 +17,7 @@ import { firstValueFrom, from, map, + mergeAll, mergeWith, of, share, @@ -673,15 +674,12 @@ export class CentrifugeBase { async getTxCompletedEvents() { const parachainUrl = await this.getCachedParachainUrl() - if (!txCompletedEvents[parachainUrl]) { - txCompletedEvents[parachainUrl] = new Subject() - } - return txCompletedEvents[parachainUrl] + return txCompletedEvents[parachainUrl] || (txCompletedEvents[parachainUrl] = new Subject()) } getEvents() { return this.getBlockEvents().pipe( - mergeWith(from(this.getTxCompletedEvents())), + mergeWith(from(this.getTxCompletedEvents()).pipe(mergeAll())), combineLatestWith(this.getApi()), map(([events, api]) => ({ events, api })) ) From 6ff7e7c5b530ccbea94c7967c4dd1f8f935b8963 Mon Sep 17 00:00:00 2001 From: sophian Date: Thu, 5 Sep 2024 18:15:21 -0400 Subject: [PATCH 15/26] Add tenderly node rpc key --- centrifuge-app/.env-config/.env.altair | 1 + centrifuge-app/.env-config/.env.catalyst | 3 ++- centrifuge-app/.env-config/.env.demo | 3 ++- centrifuge-app/.env-config/.env.development | 1 + centrifuge-app/.env-config/.env.example | 1 + centrifuge-app/.env-config/.env.ff-prod | 5 +++-- centrifuge-app/.env-config/.env.production | 5 +++-- centrifuge-app/src/config.ts | 3 +++ 8 files changed, 16 insertions(+), 6 deletions(-) diff --git a/centrifuge-app/.env-config/.env.altair b/centrifuge-app/.env-config/.env.altair index d63326a6ef..6ec9cad940 100644 --- a/centrifuge-app/.env-config/.env.altair +++ b/centrifuge-app/.env-config/.env.altair @@ -21,3 +21,4 @@ REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43 REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.catalyst b/centrifuge-app/.env-config/.env.catalyst index 3803d0cca8..ebd76eb3d0 100644 --- a/centrifuge-app/.env-config/.env.catalyst +++ b/centrifuge-app/.env-config/.env.catalyst @@ -20,4 +20,5 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc -REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 \ No newline at end of file +REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.demo b/centrifuge-app/.env-config/.env.demo index 84202b0e55..69a1a033c2 100644 --- a/centrifuge-app/.env-config/.env.demo +++ b/centrifuge-app/.env-config/.env.demo @@ -1,4 +1,4 @@ -REACT_APP_COLLATOR_WSS_URL=wss://fullnode-apps.demo.k-f.dev +REACT_APP_COLLATOR_WSS_URL=wss://fullnode.demo.k-f.dev,wss://fullnodey-apps.demo.k-f.dev REACT_APP_DEFAULT_UNLIST_POOLS=true REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-demo REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ @@ -21,3 +21,4 @@ REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43 REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.development b/centrifuge-app/.env-config/.env.development index 84202b0e55..01b83d2086 100644 --- a/centrifuge-app/.env-config/.env.development +++ b/centrifuge-app/.env-config/.env.development @@ -21,3 +21,4 @@ REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43 REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.example b/centrifuge-app/.env-config/.env.example index 6afb90e0e6..1b02c6a9f8 100644 --- a/centrifuge-app/.env-config/.env.example +++ b/centrifuge-app/.env-config/.env.example @@ -21,3 +21,4 @@ REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43 REACT_APP_TREASURY=kAJkmGxAd6iqX9JjWTdhXgCf2PL1TAphTRYrmEqzBrYhwbXAn REACT_APP_PRIME_IPFS_HASH=QmQfcuHM3EGrtpjhitDwJsgie5THLPtRNzvk7N3uymgHGc REACT_APP_ONFINALITY_KEY=0e1c049f-d876-4e77-a45f-b5afdf5739b2 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.ff-prod b/centrifuge-app/.env-config/.env.ff-prod index 73617dfb5b..e8374b2240 100644 --- a/centrifuge-app/.env-config/.env.ff-prod +++ b/centrifuge-app/.env-config/.env.ff-prod @@ -1,4 +1,4 @@ -REACT_APP_COLLATOR_WSS_URL=wss://fullnode.parachain.centrifuge.io +REACT_APP_COLLATOR_WSS_URL=wss://fullnode.parachain.centrifuge.io,wss://centrifuge-parachain.api.onfinality.io/public-ws REACT_APP_DEFAULT_UNLIST_POOLS=false REACT_APP_FAUCET_URL= REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ @@ -20,4 +20,5 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=4dpEcgqJRyJK3J8Es6v8ZfVntV7c64Ysgcjd4hYwyGoFPWbg REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 -REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 \ No newline at end of file +REACT_APP_ONFINALITY_KEY=18704429-288d-4f55-bda8-8b60f4c53b96 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/.env-config/.env.production b/centrifuge-app/.env-config/.env.production index 02fb25f56c..8917d00354 100644 --- a/centrifuge-app/.env-config/.env.production +++ b/centrifuge-app/.env-config/.env.production @@ -1,4 +1,4 @@ -REACT_APP_COLLATOR_WSS_URL=wss://apps.fullnode.centrifuge.io +REACT_APP_COLLATOR_WSS_URL=wss://apps.fullnode.centrifuge.io,wss://centrifuge-parachain.api.onfinality.io/public-ws REACT_APP_DEFAULT_UNLIST_POOLS=false REACT_APP_FAUCET_URL= REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ @@ -20,4 +20,5 @@ REACT_APP_WALLETCONNECT_ID=c32fa79350803519804a67fcab0b742a REACT_APP_TINLAKE_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_clhi43ef5g4rw49zwftsvd2ks/subgraphs/main/prod/gn REACT_APP_TREASURY=4dpEcgqJRyJK3J8Es6v8ZfVntV7c64Ysgcjd4hYwyGoFPWbg REACT_APP_PRIME_IPFS_HASH=QmS5gX2sk1ZCEyWnMjjmQyYkLTz27VVNGzVtCKWneABbj5 -REACT_APP_ONFINALITY_KEY=84bb59f4-05cc-440b-8fd4-7917623a90c6 \ No newline at end of file +REACT_APP_ONFINALITY_KEY=84bb59f4-05cc-440b-8fd4-7917623a90c6 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ No newline at end of file diff --git a/centrifuge-app/src/config.ts b/centrifuge-app/src/config.ts index 5caf01fb74..6615d37017 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -124,6 +124,8 @@ const ethNetwork = import.meta.env.REACT_APP_TINLAKE_NETWORK || 'mainnet' const alchemyKey = import.meta.env.REACT_APP_ALCHEMY_KEY const onfinalityKey = import.meta.env.REACT_APP_ONFINALITY_KEY +const tenderlyKey = import.meta.env.REACT_APP_TENDERLY_KEY + export const ethConfig = { rpcUrl: `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, chainId: 1, @@ -157,6 +159,7 @@ export const evmChains: EvmChains = { }, blockExplorerUrl: 'https://etherscan.io/', urls: [ + `https://mainnet.gateway.tenderly.co/${tenderlyKey}`, `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, `https://eth.api.onfinality.io/rpc?apikey=${onfinalityKey}`, ], From bb8c0cf6013001bf1305f2ab87a3efb977477baf Mon Sep 17 00:00:00 2001 From: sophian Date: Thu, 5 Sep 2024 19:53:36 -0400 Subject: [PATCH 16/26] Enable getDefaultProvider for evm instead of manual implementation --- centrifuge-app/src/config.ts | 7 +++ .../WalletProvider/WalletProvider.tsx | 52 +++++++++++-------- .../components/WalletProvider/evm/chains.ts | 1 + 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/centrifuge-app/src/config.ts b/centrifuge-app/src/config.ts index 6615d37017..f673c4a055 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -163,6 +163,7 @@ export const evmChains: EvmChains = { `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, `https://eth.api.onfinality.io/rpc?apikey=${onfinalityKey}`, ], + network: 'mainnet', iconUrl: ethereumLogo, isTestnet: false, }, @@ -174,6 +175,7 @@ export const evmChains: EvmChains = { `https://eth-sepolia.g.alchemy.com/v2/${alchemyKey}`, `https://eth-sepolia.api.onfinality.io/rpc?apikey=${onfinalityKey}`, ], + network: 'sepolia', iconUrl: sepoliaLogo, isTestnet: true, }, @@ -183,6 +185,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://basescan.org/', urls: ['https://mainnet.base.org'], iconUrl: baseLogo, + network: 'base-mainnet', isTestnet: false, }, 84532: { @@ -191,6 +194,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://sepolia.basescan.org/', urls: [`https://sepolia.base.org`], iconUrl: baseLogo, + network: 'base-sepolia', isTestnet: true, }, 42161: { @@ -203,6 +207,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://arbiscan.io/', urls: ['https://arb1.arbitrum.io/rpc'], iconUrl: arbitrumLogo, + network: 'arbitrum-mainnet', isTestnet: false, }, 42220: { @@ -216,6 +221,7 @@ export const evmChains: EvmChains = { urls: ['https://forno.celo.org'], iconUrl: celoLogo, isTestnet: false, + network: 'celo-mainnet', }, 44787: { name: 'Celo Alfajores', @@ -228,6 +234,7 @@ export const evmChains: EvmChains = { urls: ['https://alfajores-forno.celo-testnet.org'], iconUrl: celoLogo, isTestnet: true, + network: 'celo-alfajores', }, } diff --git a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx index 4d3b893bc8..cb2c099dc3 100644 --- a/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx +++ b/centrifuge-react/src/components/WalletProvider/WalletProvider.tsx @@ -4,7 +4,7 @@ import { getWallets } from '@subwallet/wallet-connect/dotsama/wallets' import { Wallet } from '@subwallet/wallet-connect/types' import { Web3ReactState } from '@web3-react/types' import { WalletConnect as WalletConnectV2 } from '@web3-react/walletconnect-v2' -import { JsonRpcProvider, Provider } from 'ethers' +import { AbstractProvider, getDefaultProvider, JsonRpcProvider } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { firstValueFrom, map, switchMap } from 'rxjs' @@ -63,10 +63,19 @@ export type WalletContextType = { selectedWallet: EvmConnectorMeta | null isSmartContractWallet: boolean selectedAddress: string | null - getProvider(chainId: number): Provider + getProvider(chainId: number): JsonRpcProvider | AbstractProvider } } +const unsupportedNetworksByDefaultProvider = [ + 'base-sepolia', + 'base-mainnet', + 'celo-alfajores', + 'celo-mainnet', + 'arbitrum-sepolia', + 'arbitrum-mainnet', +] + const WalletContext = React.createContext(null as any) export const wallets = getWallets() @@ -129,10 +138,13 @@ type WalletProviderProps = { showAdvancedAccounts?: boolean showTestNets?: boolean showFinoa?: boolean + infuraApiKey?: string + alchemyApiKey?: string + tenderlyApiKey?: string } let cachedEvmConnectors: EvmConnectorMeta[] | undefined = undefined -const cachedProviders = new Map() +const cachedProviders = new Map() export function WalletProvider({ children, @@ -148,6 +160,9 @@ export function WalletProvider({ showAdvancedAccounts, showTestNets, showFinoa, + infuraApiKey, + alchemyApiKey, + tenderlyApiKey, }: WalletProviderProps) { if (!evmChainsProp[1]?.urls[0]) throw new Error('Mainnet should be defined in EVM Chains') @@ -240,26 +255,21 @@ export function WalletProvider({ const [proxies] = useCentrifugeQuery(['allProxies'], (cent) => cent.proxies.getAllProxies()) - async function findHealthyProvider(chainId: number, urls: string[]): Promise { - for (const url of urls) { - try { - const provider = new JsonRpcProvider(url, chainId) - await provider.getBlockNumber() - cachedProviders.set(chainId, provider) - return provider - } catch (error) { - console.error(`Provider health check failed for ${url}:`, error) - } - } - throw new Error(`No healthy provider found for chain ${chainId}`) - } - - function getProvider(chainId: number): JsonRpcProvider { - const urls = (evmChains as any)[chainId].urls + function getProvider(chainId: number) { + const defaultUrl = (evmChains as any)[chainId].urls[0] + const network = (evmChains as any)[chainId].network if (!cachedProviders.has(chainId)) { - findHealthyProvider(chainId, urls).catch(console.error) + let networkish = unsupportedNetworksByDefaultProvider.includes(network) ? defaultUrl : network + const provider = getDefaultProvider(networkish, { + infura: infuraApiKey, + alchemy: alchemyApiKey, + tenderly: tenderlyApiKey, + exclusive: ['infura', 'alchemy', 'tenderly'], + }) + cachedProviders.set(chainId, provider) + return provider } - return cachedProviders.get(chainId) || new JsonRpcProvider(urls[0], chainId) + return cachedProviders.get(chainId) as JsonRpcProvider | AbstractProvider } function setFilteredAccounts(accounts: SubstrateAccount[]) { diff --git a/centrifuge-react/src/components/WalletProvider/evm/chains.ts b/centrifuge-react/src/components/WalletProvider/evm/chains.ts index ea11f502a9..db0a2106f8 100644 --- a/centrifuge-react/src/components/WalletProvider/evm/chains.ts +++ b/centrifuge-react/src/components/WalletProvider/evm/chains.ts @@ -7,6 +7,7 @@ type BasicChainInformation = { } type ExtendedChainInformation = BasicChainInformation & { + network: string name: string nativeCurrency: AddEthereumChainParameter['nativeCurrency'] blockExplorerUrl: string From c3cf7c83404b9a2bef176da260a2de78912ed608 Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 11 Sep 2024 10:20:39 -0400 Subject: [PATCH 17/26] Replace BigInt with bigint --- .../src/utils/tinlake/useTinlakeBalances.ts | 4 ++-- .../src/utils/tinlake/useTinlakeInvestments.ts | 4 ++-- .../src/utils/tinlake/useTinlakePools.ts | 14 +++++++------- .../src/utils/tinlake/useTinlakePortfolio.ts | 2 +- centrifuge-js/tsconfig.json | 13 ++++++++++--- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts index 8a33ddc2ed..811ffe445d 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts @@ -32,8 +32,8 @@ const WCFG_ADDRESS = '0xc221b7e65ffc80de234bbb6667abdd46593d34f0' async function getBalances(pools: TinlakePool[], address: string, provider: Provider) { const calls: EvmMulticallCall[] = [] - const toTokenBalance = (val: BigInt) => new TokenBalance(val.toString(), 18) - const toCurrencyBalance = (val: BigInt) => new CurrencyBalance(val.toString(), 18) + const toTokenBalance = (val: bigint) => new TokenBalance(val.toString(), 18) + const toCurrencyBalance = (val: bigint) => new CurrencyBalance(val.toString(), 18) const seenCurrencies = new Set() diff --git a/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts b/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts index fc22ee9a94..c8b1f22280 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakeInvestments.ts @@ -16,8 +16,8 @@ export function useTinlakeInvestments(poolId: string, address?: string) { } async function getInvestment(pool: TinlakePool, address: string) { - const toNumber = (val: BigInt) => Number(val) - const toDec18 = (val: BigInt) => new CurrencyBalance(val.toString(), 18).toDecimal() + const toNumber = (val: bigint) => Number(val) + const toDec18 = (val: bigint) => new CurrencyBalance(val.toString(), 18).toDecimal() const calls: Call[] = [ { target: pool.addresses.JUNIOR_TRANCHE, diff --git a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts index b51c03800c..4c53ff39e7 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakePools.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakePools.ts @@ -345,12 +345,12 @@ export async function getWriteOffPercentages(pool: TinlakePool, loans: any[]) { } async function getPools(pools: IpfsPools): Promise<{ pools: TinlakePool[] }> { - const toDateString = (val: BigInt) => new Date(Number(val) * 1000).toISOString() - const toNumber = (val: BigInt) => Number(val) - const toCurrencyBalance = (val: BigInt) => new CurrencyBalance(val.toString(), 18) - const toTokenBalance = (val: BigInt) => new TokenBalance(val.toString(), 18) - const toRate = (val: BigInt) => new Rate(val.toString()) - const toPrice = (val: BigInt) => new Rate(val.toString()) + const toDateString = (val: bigint) => new Date(Number(val) * 1000).toISOString() + const toNumber = (val: bigint) => Number(val) + const toCurrencyBalance = (val: bigint) => new CurrencyBalance(val.toString(), 18) + const toTokenBalance = (val: bigint) => new TokenBalance(val.toString(), 18) + const toRate = (val: bigint) => new Rate(val.toString()) + const toPrice = (val: bigint) => new Rate(val.toString()) const calls: Call[] = [] pools.active.forEach((pool) => { @@ -827,6 +827,6 @@ interface State { submissionPeriod: boolean } -function toBN(val: BigInt) { +function toBN(val: bigint) { return new BN(val.toString()) } diff --git a/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts b/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts index c03b86ab5c..c37bf78ad6 100644 --- a/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts +++ b/centrifuge-app/src/utils/tinlake/useTinlakePortfolio.ts @@ -23,7 +23,7 @@ export enum TinlakeTranche { } async function getTinlakePortfolio(ipfsPools: IpfsPools, address: string) { - const toBN = (val: BigInt) => new CurrencyBalance(val.toString(), 18) + const toBN = (val: bigint) => new CurrencyBalance(val.toString(), 18) const calls: Call[] = ipfsPools.active.flatMap((pool) => [ { diff --git a/centrifuge-js/tsconfig.json b/centrifuge-js/tsconfig.json index 92e42cb922..27fc9743e4 100644 --- a/centrifuge-js/tsconfig.json +++ b/centrifuge-js/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "module": "esnext", - "lib": ["dom", "esnext"], + "lib": [ + "dom", + "esnext" + ], + "target": "ES2020", "importHelpers": true, "declaration": true, "sourceMap": true, @@ -19,5 +23,8 @@ "noUnusedLocals": true, "noUnusedParameters": true }, - "include": ["src", "types"] -} + "include": [ + "src", + "types" + ] +} \ No newline at end of file From a5a0c5619082d2c0e566d46d14e3f4b152118217 Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 11 Sep 2024 10:20:59 -0400 Subject: [PATCH 18/26] Update imports --- centrifuge-js/src/modules/liquidityPools.ts | 69 +++++++++++++-------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index 28a56d269e..47df1062db 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,9 +1,7 @@ -import { Interface } from '@ethersproject/abi' -import { Contract } from '@ethersproject/contracts' -import type { TransactionRequest, TransactionResponse } from '@ethersproject/providers' import BN from 'bn.js' import { signERC2612Permit } from 'eth-permit' -import { Provider } from 'ethers' +import type { TransactionRequest, TransactionResponse } from 'ethers' +import { Contract, Interface, Provider } from 'ethers' import set from 'lodash/set' import { combineLatestWith, firstValueFrom, from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' @@ -72,7 +70,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { function centrifugeRouter(chainId: number) { const centrifugeRouter = getCentrifugeRouterAddress(chainId) - const getEstimate = from(contract(centrifugeRouter, ABI.CentrifugeRouter).estimate([0])) + const getEstimate = from(contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).estimate([0])) return getEstimate.pipe( map((estimate) => { return { estimate, centrifugeRouter } @@ -175,11 +173,13 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const [currencyAddress, amount, chainId] = args const centrifugeRouterAddress = getCentrifugeRouterAddress(chainId) - return pending(contract(currencyAddress, ABI.Currency).approve(centrifugeRouterAddress, amount, options)) + return pending( + contract(currencyAddress, new Interface(ABI.Currency)).approve(centrifugeRouterAddress, amount, options) + ) } async function signPermit(args: [currencyAddress: string, amount: BN, chainId: number]) { - const [currencyAddress, amount] = args + const [currencyAddress, amount, chainId] = args if (!inst.config.evmSigner) throw new Error('EVM signer not set') let domainOrCurrency: any = currencyAddress @@ -226,7 +226,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const enable = iface.encodeFunctionData('enableLockDepositRequest', [lpAddress, order.toString()]) const requestDeposit = iface.encodeFunctionData('executeLockedDepositRequest', [lpAddress, user, estimate]) return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).multicall([enable, requestDeposit], { + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).multicall([enable, requestDeposit], { ...options, gasLimit: 500000, value: estimate, @@ -245,7 +245,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).requestRedeem( + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).requestRedeem( lpAddress, order.toString(), user, @@ -293,7 +293,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { ]) return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).multicall([permit, enable, requestDeposit], { + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).multicall([permit, enable, requestDeposit], { ...options, gasLimit: 500000, value: estimate, @@ -308,7 +308,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).cancelRedeemRequest(lpAddress, estimate, { + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).cancelRedeemRequest(lpAddress, estimate, { ...options, value: estimate, }) @@ -323,7 +323,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).cancelDepositRequest(lpAddress, estimate, { + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).cancelDepositRequest(lpAddress, estimate, { ...options, value: estimate, }) @@ -338,10 +338,15 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).claimCancelDepositRequest(lpAddress, user, user, { - ...options, - value: estimate, - }) + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).claimCancelDepositRequest( + lpAddress, + user, + user, + { + ...options, + value: estimate, + } + ) ) }) ) @@ -353,10 +358,15 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).claimCancelRedeemRequest(lpAddress, user, user, { - ...options, - value: estimate, - }) + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).claimCancelRedeemRequest( + lpAddress, + user, + user, + { + ...options, + value: estimate, + } + ) ) }) ) @@ -368,11 +378,16 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).claimDeposit(lpAddress, receiver ?? user, user, { - ...options, - value: estimate, - gasLimit: 200000, - }) + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).claimDeposit( + lpAddress, + receiver ?? user, + user, + { + ...options, + value: estimate, + gasLimit: 200000, + } + ) ) }) ) @@ -387,7 +402,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { return centrifugeRouter(chainId).pipe( switchMap(({ estimate, centrifugeRouter }) => { return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).claimRedeem( + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).claimRedeem( lpAddress, withdraw.toString(), receiver ?? user, @@ -523,7 +538,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { ...(currencies.flatMap((currency) => ({ target: poolManager, call: ['function assetToId(address) view returns (uint128)', currency.address], - returns: [[`currencyNeedsAdding[${currency.address}]`, (id: BigInt) => id === BigInt(0)]], + returns: [[`currencyNeedsAdding[${currency.address}]`, (id: bigint) => id === 0n]], })) as Call[]), ], { From b050d4f06069f8431ff72c0aacf06cc7665bc80d Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 11 Sep 2024 10:21:16 -0400 Subject: [PATCH 19/26] Clean up for centrifuge base --- centrifuge-js/src/CentrifugeBase.ts | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index bf893165a7..f4cf9ca714 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -313,38 +313,35 @@ export class CentrifugeBase { } private async findHealthyWs(): Promise { - for (const url of this.rpcEndpoints) { - const isHealthy = await this.checkWsHealth(url) - if (isHealthy) { - console.log(`Connection to ${url} established`) - return url - } + const url = await Promise.any(this.rpcEndpoints.map((url) => this.checkWsHealth(url))) + if (url) { + console.log(`Connection to ${url} established`) + return url } - console.error('Error: No healthy parachain URL found') return null } - private checkWsHealth(url: string, timeoutMs: number = 5000): Promise { - return new Promise((resolve) => { + private checkWsHealth(url: string, timeoutMs: number = 5000): Promise { + return new Promise((resolve, reject) => { const ws = new WebSocket(url) const timer = setTimeout(() => { ws.close() console.log(`Connection to ${url} timed out`) - resolve(false) + reject() }, timeoutMs) ws.onopen = () => { clearTimeout(timer) ws.close() - resolve(true) + resolve(url) } ws.onerror = () => { clearTimeout(timer) ws.close() console.log(`Connection to ${url} failed`) - resolve(false) + reject() } }) } @@ -508,14 +505,10 @@ export class CentrifugeBase { blockNumber: (result as any).blockNumber ? Number((result as any).blockNumber?.toString()) : undefined, } }), - tap((result) => { + tap(async (result) => { options?.onStatusChange?.(result) if (result.status === 'InBlock') { - from(this.getTxCompletedEvents()) - .pipe(take(1)) - .subscribe((subject) => { - subject.next(result.events) - }) + ;(await this.getTxCompletedEvents()).next(result.events) } }), takeWhile((result) => { From e8a6074bae25c39bea1197a65fe23a02791632a8 Mon Sep 17 00:00:00 2001 From: sophian Date: Thu, 12 Sep 2024 13:03:43 -0400 Subject: [PATCH 20/26] Clean up --- .../InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx | 2 +- centrifuge-app/src/components/Root.tsx | 3 +++ centrifuge-js/esbuild.js | 2 +- centrifuge-js/src/modules/liquidityPools.ts | 5 +++-- centrifuge-react/src/components/Provider/Provider.tsx | 9 +++++++++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx index 07b3e3093a..411c5c070d 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx @@ -45,7 +45,7 @@ export function InvestRedeemLiquidityPoolsProvider({ poolId, trancheId, children const tranche = pool.tranches.find((t) => t.id === trancheId) const { data: metadata, isLoading: isMetadataLoading } = usePoolMetadata(pool) const trancheMeta = metadata?.tranches?.[trancheId] - const chainId = provider?.network.chainId || 1 + const chainId = Number(provider?._network.chainId) if (!tranche) throw new Error(`Token not found. Pool id: ${poolId}, token id: ${trancheId}`) diff --git a/centrifuge-app/src/components/Root.tsx b/centrifuge-app/src/components/Root.tsx index 5cae7b5760..2ba8c053c1 100644 --- a/centrifuge-app/src/components/Root.tsx +++ b/centrifuge-app/src/components/Root.tsx @@ -189,6 +189,9 @@ export function Root() { showAdvancedAccounts={debugState.showAdvancedAccounts} showTestNets={debugState.showTestNets} showFinoa={debugState.showFinoa} + infuraApiKey={import.meta.env.REACT_APP_INFURA_KEY} + alchemyApiKey={import.meta.env.REACT_APP_ALCHEMY_KEY} + tenderlyApiKey={import.meta.env.REACT_APP_TENDERLY_KEY} > diff --git a/centrifuge-js/esbuild.js b/centrifuge-js/esbuild.js index 57ac0d4081..bf620dd23d 100644 --- a/centrifuge-js/esbuild.js +++ b/centrifuge-js/esbuild.js @@ -19,7 +19,7 @@ Promise.all([ : undefined, external: Object.keys(pkg.dependencies), format: 'esm', - target: ['es6'], + target: ['es2020'], }), esbuild.build({ entryPoints: ['src/index.ts'], diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index 47df1062db..2732a11901 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,7 +1,7 @@ import BN from 'bn.js' import { signERC2612Permit } from 'eth-permit' import type { TransactionRequest, TransactionResponse } from 'ethers' -import { Contract, Interface, Provider } from 'ethers' +import { Contract, Interface, Provider, ethers } from 'ethers' import set from 'lodash/set' import { combineLatestWith, firstValueFrom, from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' @@ -70,7 +70,8 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { function centrifugeRouter(chainId: number) { const centrifugeRouter = getCentrifugeRouterAddress(chainId) - const getEstimate = from(contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).estimate([0])) + const bytes = ethers.hexlify(new Uint8Array([0x12])) + const getEstimate = from(contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).estimate(bytes)) return getEstimate.pipe( map((estimate) => { return { estimate, centrifugeRouter } diff --git a/centrifuge-react/src/components/Provider/Provider.tsx b/centrifuge-react/src/components/Provider/Provider.tsx index 3b837af31a..c5e9cd6967 100644 --- a/centrifuge-react/src/components/Provider/Provider.tsx +++ b/centrifuge-react/src/components/Provider/Provider.tsx @@ -20,6 +20,9 @@ export type ProviderProps = { walletConnectId?: string subscanUrl?: string transactionToastPositionProps?: TransactionToastsProps['positionProps'] + infuraApiKey?: string + alchemyApiKey?: string + tenderlyApiKey?: string } export function Provider({ @@ -30,6 +33,9 @@ export function Provider({ walletConnectId, subscanUrl, transactionToastPositionProps, + infuraApiKey, + alchemyApiKey, + tenderlyApiKey, }: ProviderProps) { return ( @@ -39,6 +45,9 @@ export function Provider({ evmAdditionalConnectors={evmAdditionalConnectors} walletConnectId={walletConnectId} subscanUrl={subscanUrl} + infuraApiKey={infuraApiKey} + alchemyApiKey={alchemyApiKey} + tenderlyApiKey={tenderlyApiKey} > From 42ebed47bb0c5b331f30d38281135f0159c238c1 Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 16 Sep 2024 17:38:45 -0400 Subject: [PATCH 21/26] Remove outdated eth-permit in favor of custom code --- centrifuge-js/package.json | 1 - centrifuge-js/src/modules/liquidityPools.ts | 2 +- centrifuge-js/src/modules/pools.ts | 2 - centrifuge-js/src/utils/signERC2612Permit.ts | 67 ++++++++++++++++++++ yarn.lock | 12 +--- 5 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 centrifuge-js/src/utils/signERC2612Permit.ts diff --git a/centrifuge-js/package.json b/centrifuge-js/package.json index 5cdd78bad5..fc25bd3acd 100644 --- a/centrifuge-js/package.json +++ b/centrifuge-js/package.json @@ -34,7 +34,6 @@ "@stablelib/blake2b": "^1.0.1", "clp-wasm": "^0.0.15", "decimal.js-light": "^2.5.1", - "eth-permit": "^0.2.3", "isomorphic-fetch": "^3.0.0", "jw3t": "^1.0.8", "lodash": "^4.17.21" diff --git a/centrifuge-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index 2732a11901..b7dfc50058 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,5 +1,4 @@ import BN from 'bn.js' -import { signERC2612Permit } from 'eth-permit' import type { TransactionRequest, TransactionResponse } from 'ethers' import { Contract, Interface, Provider, ethers } from 'ethers' import set from 'lodash/set' @@ -8,6 +7,7 @@ import { Centrifuge } from '../Centrifuge' import { TransactionOptions } from '../types' import { CurrencyBalance, TokenBalance } from '../utils/BN' import { Call, multicall } from '../utils/evmMulticall' +import { signERC2612Permit } from '../utils/signERC2612Permit' import * as ABI from './liquidityPools/abi' import { CurrencyKey, CurrencyMetadata, getCurrencyEvmAddress, getCurrencyLocation } from './pools' diff --git a/centrifuge-js/src/modules/pools.ts b/centrifuge-js/src/modules/pools.ts index 677be2bc8c..d23f6f131b 100644 --- a/centrifuge-js/src/modules/pools.ts +++ b/centrifuge-js/src/modules/pools.ts @@ -3801,8 +3801,6 @@ export function getPoolsModule(inst: Centrifuge) { switchMap(({ api, pool: rawPool }) => { const pool = rawPool.toHuman() as PoolDetailsData const trancheIds = pool.tranches.ids - console.log('🚀 ~ trancheIds:', trancheIds) - console.log('🚀 ~ poolId:', poolId) return combineLatest([ api.queryMulti( trancheIds.flatMap((trancheId) => [ diff --git a/centrifuge-js/src/utils/signERC2612Permit.ts b/centrifuge-js/src/utils/signERC2612Permit.ts new file mode 100644 index 0000000000..0a3d70badf --- /dev/null +++ b/centrifuge-js/src/utils/signERC2612Permit.ts @@ -0,0 +1,67 @@ +import { ethers } from 'ethers' + +export async function signERC2612Permit( + provider: any, + token: string | { name: string; version: string; chainId: number; verifyingContract: string }, + owner: string, + spender: string, + value: string, + deadline: number +) { + const tokenAddress = typeof token === 'string' ? token : token.verifyingContract + const tokenContract = new ethers.Contract( + tokenAddress, + ['function name() view returns (string)', 'function nonces(address) view returns (uint256)'], + provider + ) + + let name: string, version: string, chainId: number + if (typeof token === 'string') { + name = await tokenContract.name() + version = '1' + chainId = Number((await provider.getNetwork()).chainId) + } else { + ;({ name, version, chainId } = token) + } + + const domain = { + name, + version, + chainId, + verifyingContract: tokenAddress, + } + + const types = { + Permit: [ + { name: 'owner', type: 'address' }, + { name: 'spender', type: 'address' }, + { name: 'value', type: 'uint256' }, + { name: 'nonce', type: 'uint256' }, + { name: 'deadline', type: 'uint256' }, + ], + } + + const nonce = await tokenContract.nonces(owner) + + const values = { + owner, + spender, + value, + nonce, + deadline, + } + + const signer = await provider.getSigner(owner) + const signature = await signer.signTypedData(domain, types, values) + const { v, r, s } = ethers.Signature.from(signature) + + return { + owner, + spender, + value, + deadline, + v, + r, + s, + } +} diff --git a/yarn.lock b/yarn.lock index 3171e8003a..ccd31ddb8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1798,7 +1798,6 @@ __metadata: clp-wasm: ^0.0.15 decimal.js-light: ^2.5.1 eslint: ^7.32.0 - eth-permit: ^0.2.3 isomorphic-fetch: ^3.0.0 jest: ^27.4.3 jw3t: ^1.0.8 @@ -16092,15 +16091,6 @@ __metadata: languageName: node linkType: hard -"eth-permit@npm:^0.2.3": - version: 0.2.3 - resolution: "eth-permit@npm:0.2.3" - dependencies: - utf8: ^3.0.0 - checksum: 9bf3eed8ecb8c914aadfff97d6c3d19fc432928c72fbe205075153e84289ea95f3a101f77e2dae78ad629e09682700241f207b5436b575ca7d4fbae68eacd3f6 - languageName: node - linkType: hard - "eth-query@npm:^2.1.2": version: 2.1.2 resolution: "eth-query@npm:2.1.2" @@ -27340,7 +27330,7 @@ __metadata: languageName: node linkType: hard -"utf8@npm:3.0.0, utf8@npm:^3.0.0": +"utf8@npm:3.0.0": version: 3.0.0 resolution: "utf8@npm:3.0.0" checksum: cb89a69ad9ab393e3eae9b25305b3ff08bebca9adc839191a34f90777eb2942f86a96369d2839925fea58f8f722f7e27031d697f10f5f39690f8c5047303e62d From 3126dc522698c32f630faac7bf52772b448ebf4e Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 16 Sep 2024 17:52:26 -0400 Subject: [PATCH 22/26] Fix typescript errors in tinlake --- centrifuge-js/src/modules/tinlake.ts | 84 ++++++++++------------------ 1 file changed, 28 insertions(+), 56 deletions(-) diff --git a/centrifuge-js/src/modules/tinlake.ts b/centrifuge-js/src/modules/tinlake.ts index deb2d88b96..1a87488050 100644 --- a/centrifuge-js/src/modules/tinlake.ts +++ b/centrifuge-js/src/modules/tinlake.ts @@ -1,5 +1,5 @@ import BN from 'bn.js' -import { Contract, TransactionRequest, TransactionResponse } from 'ethers' +import { Contract, Interface, TransactionRequest, TransactionResponse } from 'ethers' import { from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' import { TransactionOptions } from '../types' @@ -68,10 +68,10 @@ export function getTinlakeModule(inst: Centrifuge) { if (!inst.config.evmSigner) throw new Error('Needs signer') if (!abi) throw new Error('ABI not found') if (!contracts[contractAddress]) { - contracts[contractAddress] = new Contract(contractAddress, abi) + contracts[contractAddress] = new Contract(contractAddress, new Interface(abi)) } - return contracts[contractAddress].connect(inst.config.evmSigner) + return contracts[contractAddress].connect(inst.config.evmSigner) as Contract } function pending(txPromise: Promise) { @@ -93,7 +93,6 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( - // @ts-ignore contract(contractAddresses, contractVersions, 'TINLAKE_CURRENCY').approve( contractAddresses[tranche === 'junior' ? 'JUNIOR_TRANCHE' : 'SENIOR_TRANCHE'], maxUint256, @@ -110,7 +109,6 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( - // @ts-ignore contract(contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_TOKEN' : 'SENIOR_TOKEN').approve( contractAddresses[tranche === 'junior' ? 'JUNIOR_TRANCHE' : 'SENIOR_TRANCHE'], maxUint256, @@ -127,12 +125,10 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche, order] = args return pending( - // @ts-ignore contract( contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR' - // @ts-ignore ).supplyOrder(order.toString(), options) ) } @@ -145,12 +141,10 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche, order] = args return pending( - // @ts-ignore contract( contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR' - // @ts-ignore ).redeemOrder(order.toString(), options) ) } @@ -163,7 +157,6 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const [tranche] = args return pending( - // @ts-ignore contract(contractAddresses, contractVersions, tranche === 'junior' ? 'JUNIOR_OPERATOR' : 'SENIOR_OPERATOR')[ 'disburse()' ](options) @@ -187,37 +180,27 @@ export function getTinlakeModule(inst: Centrifuge) { const reserve = toBN( await (beforeClosing ? isMakerIntegrated - ? // @ts-ignore - contract(contractAddresses, contractVersions, 'ASSESSOR').totalBalance() - : // @ts-ignore - contract(contractAddresses, contractVersions, 'RESERVE').totalBalance() - : // @ts-ignore - coordinator.epochReserve()) + ? contract(contractAddresses, contractVersions, 'ASSESSOR').totalBalance() + : contract(contractAddresses, contractVersions, 'RESERVE').totalBalance() + : coordinator.epochReserve()) ) const netAssetValue = toBN( await (beforeClosing ? contractVersions?.FEED === 2 - ? // @ts-ignore - feed.latestNAV() - : // @ts-ignore - feed.approximatedNAV() - : // @ts-ignore - coordinator.epochNAV()) + ? feed.latestNAV() + : feed.approximatedNAV() + : coordinator.epochNAV()) ) const seniorAsset = beforeClosing ? isMakerIntegrated - ? // @ts-ignore - toBN(await assessor.seniorDebt()).add(toBN(await assessor.seniorBalance())) - : // @ts-ignore - toBN(await assessor.seniorDebt_()).add(toBN(await assessor.seniorBalance_())) - : // @ts-ignore - toBN(await coordinator.epochSeniorAsset()) - - // @ts-ignore + ? toBN(await assessor.seniorDebt()).add(toBN(await assessor.seniorBalance())) + : toBN(await assessor.seniorDebt_()).add(toBN(await assessor.seniorBalance_())) + : toBN(await coordinator.epochSeniorAsset()) + const minDropRatio = toBN(await assessor.minSeniorRatio()) - // @ts-ignore + const maxDropRatio = toBN(await assessor.maxSeniorRatio()) - // @ts-ignore + const maxReserve = toBN(await assessor.maxReserve()) return { reserve, netAssetValue, seniorAsset, minDropRatio, maxDropRatio, maxReserve } @@ -238,36 +221,32 @@ export function getTinlakeModule(inst: Centrifuge) { const assessor = contract(contractAddresses, contractVersions, 'ASSESSOR') const feed = contract(contractAddresses, contractVersions, 'FEED') - // @ts-ignore const epochNAV = toBN(await feed.currentNAV()) - // @ts-ignore + const epochReserve = toBN(await contract(contractAddresses, contractVersions, 'RESERVE').totalBalance()) const epochSeniorTokenPrice = toBN( - // @ts-ignore await assessor['calcSeniorTokenPrice(uint256,uint256)'](epochNAV.toString(), epochReserve.toString()) ) const epochJuniorTokenPrice = toBN( - // @ts-ignore await assessor['calcJuniorTokenPrice(uint256,uint256)'](epochNAV.toString(), epochReserve.toString()) ) return { - // @ts-ignore dropInvest: toBN(await seniorTranche.totalSupply()), - // @ts-ignore + dropRedeem: toBN(await seniorTranche.totalRedeem()) .mul(epochSeniorTokenPrice) .div(e27), - // @ts-ignore + tinInvest: toBN(await juniorTranche.totalSupply()), - // @ts-ignore + tinRedeem: toBN(await juniorTranche.totalRedeem()) .mul(epochJuniorTokenPrice) .div(e27), } } const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') - // @ts-ignore + const orderState = await coordinator.order() return { @@ -285,15 +264,14 @@ export function getTinlakeModule(inst: Centrifuge) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') return { - // @ts-ignore dropInvest: toBN(await coordinator.weightSeniorSupply()), - // @ts-ignore + dropRedeem: toBN(await coordinator.weightSeniorRedeem()), - // @ts-ignore + tinInvest: toBN(await coordinator.weightJuniorSupply()), - // @ts-ignore + tinRedeem: toBN(await coordinator.weightJuniorRedeem()), - // @ts-ignore + seniorAsset: toBN(await coordinator.weightSeniorAsset()), } } @@ -305,7 +283,7 @@ export function getTinlakeModule(inst: Centrifuge) { options: TransactionRequest = {} ) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') - // @ts-ignore + return pending(coordinator.closeEpoch({ ...options, gasLimit: 5000000 })) } @@ -317,7 +295,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const submissionTx = (async () => { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') - // @ts-ignore + if ((await coordinator.submissionPeriod()) !== true) throw new Error('Not in submission period') const state = await getEpochState(contractAddresses, contractVersions, []) const orders = await getOrders(contractAddresses, contractVersions, []) @@ -327,7 +305,6 @@ export function getTinlakeModule(inst: Centrifuge) { throw new Error('Failed to find a solution') } - // @ts-ignore return coordinator.submitSolution( solution.dropRedeem.toString(), solution.tinRedeem.toString(), @@ -368,7 +345,6 @@ export function getTinlakeModule(inst: Centrifuge) { throw new Error('Current epoch is still in the challenge period') } - // @ts-ignore return coordinator.executeEpoch({ ...options, gasLimit: 2000000 }) })() return pending(tx) @@ -386,7 +362,7 @@ export function getTinlakeModule(inst: Centrifuge) { contractVersions: TinlakeContractVersions | undefined ) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') - // @ts-ignore + const minChallengePeriodEnd = toBN(await coordinator.minChallengePeriodEnd()).toNumber() const latestBlockTimestamp = await getLatestBlockTimestamp() if (minChallengePeriodEnd !== 0) { @@ -394,15 +370,13 @@ export function getTinlakeModule(inst: Centrifuge) { return 'in-challenge-period' } - // @ts-ignore const submissionPeriod = await coordinator.submissionPeriod() if (submissionPeriod === true) { return 'in-submission-period' } - // @ts-ignore const lastEpochClosed = toBN(await coordinator.lastEpochClosed()).toNumber() - // @ts-ignore + const minimumEpochTime = toBN(await coordinator.minimumEpochTime()).toNumber() if (submissionPeriod === false) { if (lastEpochClosed + minimumEpochTime < latestBlockTimestamp) return 'can-be-closed' @@ -425,7 +399,6 @@ export function getTinlakeModule(inst: Centrifuge) { const [address] = args const coordinator = contract(contractAddresses, contractVersions, 'CLAIM_CFG') - // @ts-ignore const tx = coordinator.accounts(address, options) return pending(tx) } @@ -439,7 +412,6 @@ export function getTinlakeModule(inst: Centrifuge) { const [centAddress] = args const coordinator = contract(contractAddresses, contractVersions, 'CLAIM_CFG') - // @ts-ignore const tx = coordinator.update(centAddress, options) return pending(tx) } From 5ca0a25ac6f34b6070046996b6283d9563312574 Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 16 Sep 2024 18:11:48 -0400 Subject: [PATCH 23/26] Use set for parachain url cache --- centrifuge-js/src/CentrifugeBase.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index f4cf9ca714..c6f82088cd 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -296,7 +296,7 @@ type Events = ISubmittableResult['events'] const txCompletedEvents: Record> = {} const blockEvents: Record> = {} -let parachainUrlCache: string | null = null +const parachainUrlCache = new Set() export class CentrifugeBase { config: Config @@ -347,15 +347,15 @@ export class CentrifugeBase { } private async getCachedParachainUrl(): Promise { - const cachedUrl = parachainUrlCache - if (cachedUrl) { - return cachedUrl + if (parachainUrlCache.values().next().value) { + return parachainUrlCache.values().next().value } - parachainUrlCache = await this.findHealthyWs() - if (!parachainUrlCache) { + const healthyUrl = await this.findHealthyWs() + if (!healthyUrl) { throw new Error('No healthy parachain URL available') } - return parachainUrlCache + parachainUrlCache.add(healthyUrl) + return healthyUrl } async getChainId() { From 713e77c3b161a521a9f10d299ff1ef226c806d5c Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 7 Oct 2024 15:29:18 -0400 Subject: [PATCH 24/26] Match with rpc endpoints --- centrifuge-js/src/CentrifugeBase.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/centrifuge-js/src/CentrifugeBase.ts b/centrifuge-js/src/CentrifugeBase.ts index c6f82088cd..5314d2b02b 100644 --- a/centrifuge-js/src/CentrifugeBase.ts +++ b/centrifuge-js/src/CentrifugeBase.ts @@ -347,8 +347,9 @@ export class CentrifugeBase { } private async getCachedParachainUrl(): Promise { - if (parachainUrlCache.values().next().value) { - return parachainUrlCache.values().next().value + const match = this.rpcEndpoints.find((url) => parachainUrlCache.has(url)) + if (match) { + return match } const healthyUrl = await this.findHealthyWs() if (!healthyUrl) { From 85efdea69047c47141ee16e65043692898753ea3 Mon Sep 17 00:00:00 2001 From: sophian Date: Mon, 7 Oct 2024 15:40:25 -0400 Subject: [PATCH 25/26] Fix typo --- centrifuge-app/.env-config/.env.demo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centrifuge-app/.env-config/.env.demo b/centrifuge-app/.env-config/.env.demo index 69a1a033c2..b8a57d14e6 100644 --- a/centrifuge-app/.env-config/.env.demo +++ b/centrifuge-app/.env-config/.env.demo @@ -1,4 +1,4 @@ -REACT_APP_COLLATOR_WSS_URL=wss://fullnode.demo.k-f.dev,wss://fullnodey-apps.demo.k-f.dev +REACT_APP_COLLATOR_WSS_URL=wss://fullnode.demo.k-f.dev,wss://fullnode-apps.demo.k-f.dev REACT_APP_DEFAULT_UNLIST_POOLS=true REACT_APP_FAUCET_URL=https://europe-central2-peak-vista-185616.cloudfunctions.net/faucet-api-demo REACT_APP_IPFS_GATEWAY=https://centrifuge.mypinata.cloud/ From b24b6b39612b1f8fc63f970b453d3662d0e33152 Mon Sep 17 00:00:00 2001 From: sophian Date: Wed, 16 Oct 2024 16:08:59 -0400 Subject: [PATCH 26/26] Fix import from ethers --- centrifuge-app/src/pages/Loan/PricingValues.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/centrifuge-app/src/pages/Loan/PricingValues.tsx b/centrifuge-app/src/pages/Loan/PricingValues.tsx index d40a5d6924..4d095fa314 100644 --- a/centrifuge-app/src/pages/Loan/PricingValues.tsx +++ b/centrifuge-app/src/pages/Loan/PricingValues.tsx @@ -1,7 +1,7 @@ import { CurrencyBalance, Loan, Pool, TinlakeLoan } from '@centrifuge/centrifuge-js' import { useCentrifugeApi, useCentrifugeQuery } from '@centrifuge/centrifuge-react' import { Card, Stack, Text } from '@centrifuge/fabric' -import { utils } from 'ethers' +import { toUtf8String } from 'ethers' import { first, map } from 'rxjs' import { Tooltips } from '../../components/Tooltips' import { formatDate, getAge } from '../../utils/date' @@ -28,7 +28,7 @@ export function PricingValues({ loan, pool }: Props) { const currentAssetPrice = Object.entries(info.content) .filter(([key]) => { if ('priceId' in pricing && 'isin' in pricing.priceId) { - return utils.toUtf8String(JSON.parse(key).isin) === pricing.priceId.isin + return toUtf8String(JSON.parse(key).isin) === pricing.priceId.isin } else { return JSON.parse(key).poolLoanId[1].toString() === loan.id.toString() }