diff --git a/centrifuge-app/.env-config/.env.altair b/centrifuge-app/.env-config/.env.altair index 884e2b033a..6ec9cad940 100644 --- a/centrifuge-app/.env-config/.env.altair +++ b/centrifuge-app/.env-config/.env.altair @@ -20,3 +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 +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 8e98e86a2e..ebd76eb3d0 100644 --- a/centrifuge-app/.env-config/.env.catalyst +++ b/centrifuge-app/.env-config/.env.catalyst @@ -19,4 +19,6 @@ 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 +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 887b028ef7..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-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/ @@ -20,3 +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=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 887b028ef7..01b83d2086 100644 --- a/centrifuge-app/.env-config/.env.development +++ b/centrifuge-app/.env-config/.env.development @@ -20,3 +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=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 d7cac13f79..1b02c6a9f8 100644 --- a/centrifuge-app/.env-config/.env.example +++ b/centrifuge-app/.env-config/.env.example @@ -20,3 +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=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 08482b5a59..ec02a1f3e2 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/ @@ -19,4 +19,6 @@ 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 +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 7dadec3d96..b66809f417 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/ @@ -19,4 +19,6 @@ 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 +REACT_APP_TENDERLY_KEY=18aMTJlpNb1lElcYNkkunC \ 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/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/InvestRedeem.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx index 66ec5fc07c..1c53229ead 100644 --- a/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx +++ b/centrifuge-app/src/components/InvestRedeem/InvestRedeem.tsx @@ -17,7 +17,6 @@ import { } from '@centrifuge/fabric' import * as React from 'react' import { useNavigate } from 'react-router-dom' -import { ethConfig } from '../../config' import { formatBalance } from '../../utils/formatting' import { useAddress } from '../../utils/useAddress' import { useGmp } from '../../utils/useGmp' @@ -63,7 +62,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)) } diff --git a/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx b/centrifuge-app/src/components/InvestRedeem/InvestRedeemLiquidityPoolsProvider.tsx index 43a5ca41a3..411c5c070d 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' @@ -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}`) @@ -226,7 +226,7 @@ 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.currency.address, assets, chainId]) console.log('permit', permit) diff --git a/centrifuge-app/src/components/LiquidityEpochSection.tsx b/centrifuge-app/src/components/LiquidityEpochSection.tsx index ae19fa0549..f6963678e3 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-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/PoolOverview/KeyMetrics.tsx b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx index 46898995ae..631449df10 100644 --- a/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx +++ b/centrifuge-app/src/components/PoolOverview/KeyMetrics.tsx @@ -335,7 +335,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/Portfolio/TransferTokensDrawer.tsx b/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx index a2f929d910..8651c8f440 100644 --- a/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx +++ b/centrifuge-app/src/components/Portfolio/TransferTokensDrawer.tsx @@ -24,10 +24,10 @@ import { TabsItem, Text, } from '@centrifuge/fabric' -import { isAddress as isEvmAddress } from '@ethersproject/address' import { isAddress } from '@polkadot/util-crypto' import BN from 'bn.js' import Decimal from 'decimal.js-light' +import { isAddress as isEvmAddress } from 'ethers' import { Field, FieldProps, Form, FormikProvider, useFormik } from 'formik' import React, { useEffect } from 'react' import { useQuery } from 'react-query' 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-app/src/config.ts b/centrifuge-app/src/config.ts index 009171b5c0..e4e0f0d1e9 100644 --- a/centrifuge-app/src/config.ts +++ b/centrifuge-app/src/config.ts @@ -96,6 +96,8 @@ 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 +const tenderlyKey = import.meta.env.REACT_APP_TENDERLY_KEY export const ethConfig = { rpcUrl: `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, @@ -129,7 +131,12 @@ export const evmChains: EvmChains = { decimals: 18, }, blockExplorerUrl: 'https://etherscan.io/', - urls: [`https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`], + urls: [ + `https://mainnet.gateway.tenderly.co/${tenderlyKey}`, + `https://eth-mainnet.g.alchemy.com/v2/${alchemyKey}`, + `https://eth.api.onfinality.io/rpc?apikey=${onfinalityKey}`, + ], + network: 'mainnet', iconUrl: ethereumLogo, isTestnet: false, }, @@ -137,7 +144,11 @@ 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}`, + ], + network: 'sepolia', iconUrl: sepoliaLogo, isTestnet: true, }, @@ -147,6 +158,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://basescan.org/', urls: ['https://mainnet.base.org'], iconUrl: baseLogo, + network: 'base-mainnet', isTestnet: false, }, 84532: { @@ -155,6 +167,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://sepolia.basescan.org/', urls: [`https://sepolia.base.org`], iconUrl: baseLogo, + network: 'base-sepolia', isTestnet: true, }, 42161: { @@ -167,6 +180,7 @@ export const evmChains: EvmChains = { blockExplorerUrl: 'https://arbiscan.io/', urls: ['https://arb1.arbitrum.io/rpc'], iconUrl: arbitrumLogo, + network: 'arbitrum-mainnet', isTestnet: false, }, 42220: { @@ -180,6 +194,7 @@ export const evmChains: EvmChains = { urls: ['https://forno.celo.org'], iconUrl: celoLogo, isTestnet: false, + network: 'celo-mainnet', }, 44787: { name: 'Celo Alfajores', @@ -192,6 +207,7 @@ export const evmChains: EvmChains = { urls: ['https://alfajores-forno.celo-testnet.org'], iconUrl: celoLogo, isTestnet: true, + network: 'celo-alfajores', }, } 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 96f516a45f..b09dce545f 100644 --- a/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx +++ b/centrifuge-app/src/pages/IssuerPool/Investors/InvestorStatus.tsx @@ -22,8 +22,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, { useMemo } from 'react' import { useParams } from 'react-router' import { DataTable } from '../../../components/DataTable' 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() } diff --git a/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts b/centrifuge-app/src/pages/Onboarding/queries/useSignRemark.ts index 3848352845..0cff17925a 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' @@ -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, 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 81c966a843..d949554bc4 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' import { useGmp } from '../useGmp' @@ -36,7 +36,7 @@ export function useEvmTransaction>( gmpOptions?: { poolId: string; trancheId: string } ) { 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-app/src/utils/tinlake/useTinlakeBalances.ts b/centrifuge-app/src/utils/tinlake/useTinlakeBalances.ts index 835587bcb9..811ffe445d 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 { JsonRpcProvider } 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: JsonRpcProvider) { +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..c8b1f22280 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 c8961c07e9..1fe722cea4 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' @@ -345,12 +344,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) => { @@ -827,6 +826,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..c37bf78ad6 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 edd0675983..66698a1844 100644 --- a/centrifuge-app/src/utils/useCFGTokenPrice.ts +++ b/centrifuge-app/src/utils/useCFGTokenPrice.ts @@ -1,12 +1,12 @@ -import { ethers } from 'ethers' +import { useWallet } from '@centrifuge/centrifuge-react' +import { Contract, Provider } from 'ethers' import { useQuery } from 'react-query' import { Dec } from './Decimal' -async function getWCFGPrice() { +async function getWCFGPrice(provider: Provider) { 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,9 +15,9 @@ async function getWCFGPrice() { } export const useCFGTokenPrice = () => { - const { data: CFGPrice } = useQuery('wCFGPrice', () => { - return getWCFGPrice() - }) + const { getProvider } = useWallet().evm + const provider = getProvider(1) + const { data: CFGPrice } = useQuery('wCFGPrice', () => getWCFGPrice(provider)) return CFGPrice } diff --git a/centrifuge-app/src/utils/useLiquidityPools.ts b/centrifuge-app/src/utils/useLiquidityPools.ts index 0e47535635..1d70dca9fe 100644 --- a/centrifuge-app/src/utils/useLiquidityPools.ts +++ b/centrifuge-app/src/utils/useLiquidityPools.ts @@ -25,17 +25,20 @@ 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 && 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-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/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/package.json b/centrifuge-js/package.json index b824f6e0d5..fc25bd3acd 100644 --- a/centrifuge-js/package.json +++ b/centrifuge-js/package.json @@ -28,18 +28,12 @@ "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", "@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/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 227924a9ce..5314d2b02b 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 { 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' +import type { JsonRpcSigner, TransactionRequest } from 'ethers' import 'isomorphic-fetch' import { Observable, @@ -17,6 +17,7 @@ import { firstValueFrom, from, map, + mergeAll, mergeWith, of, share, @@ -295,19 +296,67 @@ type Events = ISubmittableResult['events'] const txCompletedEvents: Record> = {} const blockEvents: Record> = {} +const parachainUrlCache = new Set() export class CentrifugeBase { config: Config - parachainUrl: string relayChainUrl: string subqueryUrl: string + rpcEndpoints: string[] 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()) + } + + private async findHealthyWs(): Promise { + 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, reject) => { + const ws = new WebSocket(url) + const timer = setTimeout(() => { + ws.close() + console.log(`Connection to ${url} timed out`) + reject() + }, timeoutMs) + + ws.onopen = () => { + clearTimeout(timer) + ws.close() + resolve(url) + } + + ws.onerror = () => { + clearTimeout(timer) + ws.close() + console.log(`Connection to ${url} failed`) + reject() + } + }) + } + + private async getCachedParachainUrl(): Promise { + const match = this.rpcEndpoints.find((url) => parachainUrlCache.has(url)) + if (match) { + return match + } + const healthyUrl = await this.findHealthyWs() + if (!healthyUrl) { + throw new Error('No healthy parachain URL available') + } + parachainUrlCache.add(healthyUrl) + return healthyUrl } async getChainId() { @@ -457,9 +506,11 @@ 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') this.getTxCompletedEvents().next(result.events) + if (result.status === 'InBlock') { + ;(await this.getTxCompletedEvents()).next(result.events) + } }), takeWhile((result) => { return result.status !== 'InBlock' && !result.error @@ -596,39 +647,50 @@ 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() + return txCompletedEvents[parachainUrl] || (txCompletedEvents[parachainUrl] = new Subject()) } getEvents() { return this.getBlockEvents().pipe( - mergeWith(this.getTxCompletedEvents()), + mergeWith(from(this.getTxCompletedEvents()).pipe(mergeAll())), 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-js/src/modules/liquidityPools.ts b/centrifuge-js/src/modules/liquidityPools.ts index e59a4e8b21..ea2195089d 100644 --- a/centrifuge-js/src/modules/liquidityPools.ts +++ b/centrifuge-js/src/modules/liquidityPools.ts @@ -1,10 +1,6 @@ -import { Interface } from '@ethersproject/abi' -import { isAddress as isEvmAddress } from '@ethersproject/address' -import { BigNumber } from '@ethersproject/bignumber' -import { Contract, ContractInterface } from '@ethersproject/contracts' -import type { JsonRpcProvider, TransactionRequest, TransactionResponse } from '@ethersproject/providers' import BN from 'bn.js' -import { signERC2612Permit } from 'eth-permit' +import type { TransactionRequest, TransactionResponse } from 'ethers' +import { Contract, Interface, Provider, ethers, isAddress as isEvmAddress } from 'ethers' import set from 'lodash/set' import { combineLatestWith, firstValueFrom, from, map, startWith, switchMap } from 'rxjs' import { Centrifuge } from '../Centrifuge' @@ -12,6 +8,7 @@ import { TransactionOptions } from '../types' import { addressToHex } from '../utils' 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' @@ -19,7 +16,7 @@ const PERMIT_TYPEHASH = '0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c6 const NULL_ADDRESS = '0x0000000000000000000000000000000000000000' type EvmQueryOptions = { - rpcProvider?: JsonRpcProvider + rpcProvider?: Provider } export type Permit = { @@ -28,8 +25,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 @@ -58,7 +55,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) @@ -77,7 +74,8 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { function centrifugeRouter(chainId: number) { const centrifugeRouter = getCentrifugeRouterAddress(chainId) - const getEstimate = from(contract(centrifugeRouter, 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 } @@ -109,13 +107,15 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { switchMap(({ estimate, centrifugeRouter }) => { const isToSameNetwork = typeof destinationNetwork !== 'string' && chainId === destinationNetwork.evm if (isToSameNetwork) { - return pending(contract(currencyAddress, ABI.Currency).transfer(receiverAddress, amount.toString(), options)) + return pending( + contract(currencyAddress, new Interface(ABI.Currency)).transfer(receiverAddress, amount.toString(), options) + ) } const domain = destinationNetwork === 'centrifuge' ? 0 : 1 const destinationId = destinationNetwork === 'centrifuge' ? 0 : destinationNetwork.evm const address = isEvmAddress(receiverAddress) ? receiverAddress.padEnd(66, '0') : addressToHex(receiverAddress) return pending( - contract(centrifugeRouter, ABI.CentrifugeRouter).transferTrancheTokens( + contract(centrifugeRouter, new Interface(ABI.CentrifugeRouter)).transferTrancheTokens( vault, domain, destinationId, @@ -193,7 +193,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, + }) ) } @@ -203,7 +206,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, }) @@ -217,7 +220,9 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const [currencyAddress, amount, chainId] = args const centrifugeRouterAddress = getCentrifugeRouterAddress(chainId) - return pending(contract(currencyAddress, ABI.Currency).approve(centrifugeRouterAddress, amount.toString(), options)) + return pending( + contract(currencyAddress, new Interface(ABI.Currency)).approve(centrifugeRouterAddress, amount, options) + ) } async function getCentrifugeRouterAllowance( @@ -242,7 +247,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const data = await multicall<{ decimals: number - allowance: BigNumber + allowance: bigint }>(calls, { rpcProvider: options?.rpcProvider ?? inst.config.evmSigner?.provider!, }) @@ -253,11 +258,10 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { } 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 - const chainId = await inst.config.evmSigner.getChainId() if (currencyAddress.toLowerCase() === '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') { // USDC has custom version domainOrCurrency = { name: 'USD Coin', version: '2', chainId, verifyingContract: currencyAddress } @@ -301,7 +305,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, @@ -320,7 +324,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, @@ -368,7 +372,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, @@ -383,7 +387,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, }) @@ -398,7 +402,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, }) @@ -413,10 +417,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, + } + ) ) }) ) @@ -428,10 +437,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, + } + ) ) }) ) @@ -443,11 +457,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, + } + ) ) }) ) @@ -462,7 +481,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, @@ -505,15 +524,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) @@ -545,7 +564,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 @@ -594,7 +617,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 === 0n]], })) as Call[]), ], { @@ -642,7 +665,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 [] @@ -692,7 +719,7 @@ export function getLiquidityPoolsModule(inst: Centrifuge) { const currencyData = await multicall<{ currencies: { currencySupportsPermit?: boolean }[] trancheTokenSymbol: string - trancheTokenDecimals: number + trancheTokenDecimals: BigInt }>( [ ...Object.values(currenciesByLpAddress).flatMap( @@ -730,7 +757,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-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 c13b3c5ddd..0ed530b3a9 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 '..' diff --git a/centrifuge-js/src/modules/tinlake.ts b/centrifuge-js/src/modules/tinlake.ts index bd919f1a97..1a87488050 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, Interface, 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 = {} @@ -69,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) { @@ -199,7 +198,9 @@ export function getTinlakeModule(inst: Centrifuge) { : toBN(await coordinator.epochSeniorAsset()) const minDropRatio = toBN(await assessor.minSeniorRatio()) + const maxDropRatio = toBN(await assessor.maxSeniorRatio()) + const maxReserve = toBN(await assessor.maxReserve()) return { reserve, netAssetValue, seniorAsset, minDropRatio, maxDropRatio, maxReserve } @@ -221,6 +222,7 @@ export function getTinlakeModule(inst: Centrifuge) { const feed = contract(contractAddresses, contractVersions, 'FEED') const epochNAV = toBN(await feed.currentNAV()) + const epochReserve = toBN(await contract(contractAddresses, contractVersions, 'RESERVE').totalBalance()) const epochSeniorTokenPrice = toBN( await assessor['calcSeniorTokenPrice(uint256,uint256)'](epochNAV.toString(), epochReserve.toString()) @@ -231,16 +233,20 @@ export function getTinlakeModule(inst: Centrifuge) { return { dropInvest: toBN(await seniorTranche.totalSupply()), + dropRedeem: toBN(await seniorTranche.totalRedeem()) .mul(epochSeniorTokenPrice) .div(e27), + tinInvest: toBN(await juniorTranche.totalSupply()), + tinRedeem: toBN(await juniorTranche.totalRedeem()) .mul(epochJuniorTokenPrice) .div(e27), } } const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + const orderState = await coordinator.order() return { @@ -259,9 +265,14 @@ export function getTinlakeModule(inst: Centrifuge) { return { dropInvest: toBN(await coordinator.weightSeniorSupply()), + dropRedeem: toBN(await coordinator.weightSeniorRedeem()), + tinInvest: toBN(await coordinator.weightJuniorSupply()), + tinRedeem: toBN(await coordinator.weightJuniorRedeem()), + + seniorAsset: toBN(await coordinator.weightSeniorAsset()), } } @@ -272,6 +283,7 @@ export function getTinlakeModule(inst: Centrifuge) { options: TransactionRequest = {} ) { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + return pending(coordinator.closeEpoch({ ...options, gasLimit: 5000000 })) } @@ -283,6 +295,7 @@ export function getTinlakeModule(inst: Centrifuge) { ) { const submissionTx = (async () => { const coordinator = contract(contractAddresses, contractVersions, 'COORDINATOR') + if ((await coordinator.submissionPeriod()) !== true) throw new Error('Not in submission period') const state = await getEpochState(contractAddresses, contractVersions, []) const orders = await getOrders(contractAddresses, contractVersions, []) @@ -363,6 +376,7 @@ export function getTinlakeModule(inst: Centrifuge) { } const lastEpochClosed = toBN(await coordinator.lastEpochClosed()).toNumber() + const minimumEpochTime = toBN(await coordinator.minimumEpochTime()).toNumber() if (submissionPeriod === false) { if (lastEpochClosed + minimumEpochTime < latestBlockTimestamp) return 'can-be-closed' 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 0cb8b2e8a7..d4595d2abc 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 { JsonRpcProvider } 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: JsonRpcProvider + 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) @@ -52,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, @@ -60,7 +62,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-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/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 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/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} > diff --git a/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx b/centrifuge-react/src/components/WalletMenu/WalletMenu.tsx index 7aaa8fafa4..f1b3b6fc15 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 ed32897722..cb2c099dc3 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 { JsonRpcProvider } 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 { 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): JsonRpcProvider + 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: Record = {} +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') @@ -156,7 +171,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, @@ -241,10 +256,20 @@ 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)) - ) + const defaultUrl = (evmChains as any)[chainId].urls[0] + const network = (evmChains as any)[chainId].network + if (!cachedProviders.has(chainId)) { + 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) 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 27807e43ea..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 @@ -47,11 +48,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 { diff --git a/centrifuge-react/src/components/WalletProvider/evm/utils.ts b/centrifuge-react/src/components/WalletProvider/evm/utils.ts index 4d1ae68b16..4ac5f87802 100644 --- a/centrifuge-react/src/components/WalletProvider/evm/utils.ts +++ b/centrifuge-react/src/components/WalletProvider/evm/utils.ts @@ -1,14 +1,14 @@ 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 { BrowserProvider } from 'ethers' import * as React from 'react' import { useQuery } from 'react-query' import { useWallet } from '../WalletProvider' @@ -37,7 +37,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,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) @@ -61,8 +58,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/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) } diff --git a/fabric/src/components/TextInput/index.tsx b/fabric/src/components/TextInput/index.tsx index 9f91c83a5a..98e112b882 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 d3195e5b19..b24b41f85a 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,14 @@ "@sendgrid/mail": "^7.7.0", "bn.js": "^5.2.1", "dotenv": "16.0.3", + "ethers": "^6.13.2", "rxjs": "^7.8.0" }, "scripts": { "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\"", 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..ccd31ddb8c 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 @@ -1806,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 @@ -1824,10 +1815,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 +1914,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 +2780,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 +2793,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 +2813,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 +2830,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 +2840,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 +11742,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" @@ -16432,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" @@ -16507,6 +16157,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 +17908,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 +24672,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 +24812,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" @@ -27671,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 @@ -28519,24 +28178,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 +28204,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 53e991bbf928faf5dc6efac9b8eb9ab6497c69feeb94f963d648b7a3530a720b19ec2e0ec037344257e05a4f35bd9ad04d9de6f289615ffb133282031b18c61c + checksum: 442badcce1f1178ec87a0b5372ae2e9771e07c4929a3180321901f226127f252441e8689d765aa5cfba5f50ac60dd830954afc5aeae81609aefa11d3ddf5cecf languageName: node linkType: hard