diff --git a/README.md b/README.md index af71fda..330b8c8 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ app.use(VueDapp, { autoConnect: true, // Automatically connect MetaMask wallet when the page is loaded networks: { 80001: { - chainId: ethers.utils.hexValue(80001), + chainId: ethers.toQuantity(80001), blockExplorerUrls: ['https://mumbai.polygonscan.com/'], chainName: 'Mumbai', rpcUrls: ['https://rpc-mumbai.maticvigil.com/'], diff --git a/demo/src/App.vue b/demo/src/App.vue index 9722745..7ee25e0 100644 --- a/demo/src/App.vue +++ b/demo/src/App.vue @@ -100,12 +100,12 @@ const supportedChainId = Object.keys(availableNetworks.value).map((key) => const selectedChainId = ref(0) onActivated(() => { - selectedChainId.value = chainId.value as number + selectedChainId.value = Number(chainId.value) }) const isChainChanged = ref(false) onChanged(() => { - selectedChainId.value = chainId.value as number + selectedChainId.value = Number(chainId.value) isChainChanged.value = true }) diff --git a/demo/src/main.ts b/demo/src/main.ts index e94efc8..01c9047 100644 --- a/demo/src/main.ts +++ b/demo/src/main.ts @@ -12,7 +12,7 @@ app.use(VueDapp, { dumb: false, networks: { 137: { - chainId: ethers.utils.hexValue(137), + chainId: ethers.toQuantity(137), blockExplorerUrls: ['https://polygonscan.com'], chainName: 'Polygon', rpcUrls: ['https://rpc-mainnet.maticvigil.com'], @@ -23,7 +23,7 @@ app.use(VueDapp, { }, }, 80001: { - chainId: ethers.utils.hexValue(80001), + chainId: ethers.toQuantity(80001), blockExplorerUrls: ['https://mumbai.polygonscan.com/'], chainName: 'Mumbai', rpcUrls: ['https://rpc-mumbai.maticvigil.com/'], @@ -34,7 +34,7 @@ app.use(VueDapp, { }, }, 42161: { - chainId: ethers.utils.hexValue(42161), + chainId: ethers.toQuantity(42161), blockExplorerUrls: ['https://arbiscan.io'], chainName: 'Arbitrum One', rpcUrls: ['https://arb1.arbitrum.io/rpc'], diff --git a/docs/api/plugin-options.md b/docs/api/plugin-options.md index 1702001..4643567 100644 --- a/docs/api/plugin-options.md +++ b/docs/api/plugin-options.md @@ -31,7 +31,7 @@ app.use(VueDapp, { autoConnect: true, networks: { 80001: { - chainId: ethers.utils.hexValue(80001), + chainId: ethers.toQuantity(80001), blockExplorerUrls: ['https://mumbai.polygonscan.com/'], chainName: 'Mumbai', rpcUrls: ['https://rpc-mumbai.maticvigil.com/'], @@ -42,7 +42,7 @@ app.use(VueDapp, { }, }, 42161: { - chainId: ethers.utils.hexValue(42161), + chainId: ethers.toQuantity(42161), blockExplorerUrls: ['https://arbiscan.io'], chainName: 'Arbitrum One', rpcUrls: ['https://arb1.arbitrum.io/rpc'], diff --git a/docs/index.md b/docs/index.md index 217702d..48a5aa7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -42,7 +42,7 @@ app.use(VueDapp, { autoConnect: true, // Automatically connect MetaMask wallet when the page is loaded networks: { 80001: { - chainId: ethers.utils.hexValue(80001), + chainId: ethers.toQuantity(80001), blockExplorerUrls: ['https://mumbai.polygonscan.com/'], chainName: 'Mumbai', rpcUrls: ['https://rpc-mumbai.maticvigil.com/'], diff --git a/package.json b/package.json index 777ac62..9363437 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-dapp", - "version": "0.9.1", + "version": "0.10.0", "description": "Vue 3 library for building Dapps on Ethereum", "repository": "https://github.com/vu3th/vue-dapp", "bugs": { @@ -44,7 +44,7 @@ "@walletconnect/ethereum-provider": "^2.7.7", "@walletconnect/modal": "^2.4.5", "@web3modal/standalone": "^2.4.1", - "ethers": ">=5.6.8", + "ethers": ">=6.6.3", "vue": ">=3.2.0" }, "peerDependenciesMeta": { @@ -91,6 +91,7 @@ "eslint": "^8.29.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.2.1", + "ethers": "^6.6.3", "husky": "^8.0.1", "jsdom": "^20.0.3", "lint-staged": "^12.4.2", diff --git a/src/composables/useEthers.ts b/src/composables/useEthers.ts index d4406b1..e1922ed 100644 --- a/src/composables/useEthers.ts +++ b/src/composables/useEthers.ts @@ -1,17 +1,13 @@ import { computed, markRaw, ref, Ref } from 'vue' -import { - Web3Provider, - Network, - ExternalProvider, -} from '@ethersproject/providers' -import { BigNumber, Signer } from 'ethers' +import { Web3Provider } from '@ethersproject/providers' +import { BrowserProvider, Eip1193Provider, Signer, Network } from 'ethers' import { NETWORK_DETAILS } from '../constants' import { ActivateEthersError, AddEthereumChainParameter } from '../connectors' export type { Web3Provider, Signer, Network } const isActivated = ref(false) -const provider = ref(null) +const provider = ref(null) const signer = ref(null) const network = ref(null) const address = ref('') @@ -34,18 +30,19 @@ const deactivate = () => { balance.value = BigInt(0) } -async function activate(externalProvider: ExternalProvider) { +async function activate(externalProvider: Eip1193Provider) { if (!externalProvider) throw new ActivateEthersError('provider not found') - const _provider = new Web3Provider(externalProvider) - const _signer = _provider.getSigner() + const _provider = new BrowserProvider(externalProvider) + const _signer = await _provider.getSigner() - let _network: any = null + let _network: Network | null = null let _address = '' - let _balance = BigNumber.from(0) + let _balance = BigInt(0) const data = await getData() - ;[_network, _address, _balance] = data! + ;[_network, _address] = data! + _balance = await _provider.getBalance(_address) /** * @issue #27 @@ -56,11 +53,7 @@ async function activate(externalProvider: ExternalProvider) { */ async function getData(timeout = 5000) { return Promise.race([ - Promise.all([ - _provider.getNetwork(), - _signer.getAddress(), - _signer.getBalance(), - ]), + Promise.all([_provider.getNetwork(), _signer.getAddress()]), new Promise((resolve, reject) => setTimeout(() => { reject(new ActivateEthersError('Operation timed out')) @@ -79,14 +72,14 @@ async function activate(externalProvider: ExternalProvider) { provider.value = markRaw(_provider) signer.value = markRaw(_signer) - network.value = _network + network.value = markRaw(_network) address.value = _address - balance.value = _balance.toBigInt() + balance.value = _balance // Put it outside the timer as the lookup method can occasionally take longer than 5000ms // Question: what if people don't need this variable but it lead to more connecting time? try { - dnsAlias.value = await lookupDNS(_network?.chainId, _address) + dnsAlias.value = await lookupDNS(Number(_network?.chainId), _address) } catch (err: any) { throw new ActivateEthersError('Failed to look up DNS') } @@ -98,8 +91,10 @@ async function activate(externalProvider: ExternalProvider) { updateBalanceInterval = setInterval(async () => { if (!signer.value) return try { - const _balance = await signer?.value.getBalance() - balance.value = _balance.toBigInt() + const _balance = await provider.value?.getBalance(address.value) + if (typeof _balance === 'bigint') { + balance.value = _balance + } } catch (error: any) { console.warn('Failed to update balance') } @@ -149,7 +144,7 @@ export function useEthers() { isActivated, provider: provider as Ref, // for fixing index.d.ts compiled error, see issue/10: signer: signer as Ref, - network, + network: network as Ref, address, dnsAlias, balance, diff --git a/src/composables/useEthersHooks.ts b/src/composables/useEthersHooks.ts index 682b8bc..0fc15f9 100644 --- a/src/composables/useEthersHooks.ts +++ b/src/composables/useEthersHooks.ts @@ -1,6 +1,5 @@ import { ref, watch } from 'vue' -import { Signer } from '@ethersproject/abstract-signer' -import { Network } from '@ethersproject/networks' +import { Signer, Network } from 'ethers' import { useEthers, Web3Provider } from './useEthers' export type EthersHooksContext = { diff --git a/src/composables/useMulticall.ts b/src/composables/useMulticall.ts index 15c6e96..f399f53 100644 --- a/src/composables/useMulticall.ts +++ b/src/composables/useMulticall.ts @@ -1,8 +1,7 @@ import { ref } from 'vue' -import { Contract, ContractInterface } from '@ethersproject/contracts' +import { Contract, ContractInterface, Provider } from 'ethers' import { MULTICALL2_ABI, MULTICALL2_ADDRESS } from '../constants' import { Multicall2 } from '../types/multicall2/Multicall2' -import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers' import { Result, Interface } from '@ethersproject/abi' export type ContractCall = { @@ -12,7 +11,7 @@ export type ContractCall = { args?: any[] } -export function useMulticall(provider: Web3Provider | JsonRpcProvider) { +export function useMulticall(provider: Provider) { const results = ref([]) const blockNumber = ref(0) @@ -20,7 +19,7 @@ export function useMulticall(provider: Web3Provider | JsonRpcProvider) { MULTICALL2_ADDRESS, MULTICALL2_ABI, provider, - ) as Multicall2 + ) as unknown as Multicall2 interface Call { target: string @@ -69,5 +68,6 @@ function getInterface(contractInterface: ContractInterface): Interface { if (Interface.isInterface(contractInterface)) { return contractInterface } + // @ts-ignore return new Interface(contractInterface) } diff --git a/src/composables/useWallet.ts b/src/composables/useWallet.ts index f16351d..cf9a56f 100644 --- a/src/composables/useWallet.ts +++ b/src/composables/useWallet.ts @@ -1,5 +1,5 @@ import { ref, reactive, markRaw } from 'vue' -import { providers } from 'ethers' +import { ethers } from 'ethers' import { AutoConnectError, ConnectError, @@ -15,7 +15,7 @@ export type ConnectionStatus = 'none' | 'connecting' | 'loading' | 'connected' const wallet = reactive({ connector: null as Connector | null, - provider: null as providers.ExternalProvider | null, + provider: null as ethers.Eip1193Provider | null, error: '', status: 'none' as ConnectionStatus, }) diff --git a/src/connectors/coinbaseWallet.ts b/src/connectors/coinbaseWallet.ts index 99a3944..e930d31 100644 --- a/src/connectors/coinbaseWallet.ts +++ b/src/connectors/coinbaseWallet.ts @@ -1,7 +1,7 @@ import { Connector } from './connector' import type { CoinbaseWalletProvider } from '@coinbase/wallet-sdk' import type { CoinbaseWalletSDKOptions } from '@coinbase/wallet-sdk/dist/CoinbaseWalletSDK' -import { getAddress, hexValue } from 'ethers/lib/utils' +import { ethers, getAddress } from 'ethers' import { AddChainError, ProviderNotFoundError, @@ -118,7 +118,7 @@ export class CoinbaseWalletConnector extends Connector< async switchChain(chainId: number) { if (!this.#provider) throw new ProviderNotFoundError() const provider = this.#provider - const id = hexValue(chainId) + const id = ethers.toQuantity(chainId) try { await provider.request({ diff --git a/src/connectors/connector.ts b/src/connectors/connector.ts index b01f65f..e5cf17f 100644 --- a/src/connectors/connector.ts +++ b/src/connectors/connector.ts @@ -1,5 +1,5 @@ import type { CoinbaseWalletProvider } from '@coinbase/wallet-sdk' -import { providers } from 'ethers' +import { ethers } from 'ethers' export type ConnectorData = { account: string @@ -7,7 +7,7 @@ export type ConnectorData = { } export abstract class Connector< - Provider = providers.ExternalProvider | CoinbaseWalletProvider, + Provider = ethers.Eip1193Provider | CoinbaseWalletProvider, Options = any, > { // Connector name diff --git a/src/connectors/metaMask.ts b/src/connectors/metaMask.ts index 1870cf5..0907d73 100644 --- a/src/connectors/metaMask.ts +++ b/src/connectors/metaMask.ts @@ -1,4 +1,4 @@ -import { hexValue } from 'ethers/lib/utils' +import { ethers } from 'ethers' import type { NETWORK_DETAILS } from '../constants' import { Connector } from './connector' import { @@ -211,7 +211,7 @@ export class MetaMaskConnector extends Connector< async switchChain(chainId: number) { if (!this.#provider) throw new ProviderNotFoundError() - const id = hexValue(chainId) + const id = ethers.toQuantity(chainId) const { availableNetworks } = useEthers() as any const _availableNetworks = JSON.parse( JSON.stringify(availableNetworks.value), diff --git a/src/connectors/safe.ts b/src/connectors/safe.ts index 3a7ed55..34890fd 100644 --- a/src/connectors/safe.ts +++ b/src/connectors/safe.ts @@ -1,7 +1,7 @@ import type { SafeAppProvider } from '@gnosis.pm/safe-apps-provider' import type { Opts as SafeOpts, SafeInfo } from '@gnosis.pm/safe-apps-sdk' import type SafeAppsSDK from '@gnosis.pm/safe-apps-sdk' -import { getAddress } from 'ethers/lib/utils' +import { getAddress } from 'ethers' import { normalizeChainId } from '../utils' import { Connector } from './connector' import { diff --git a/src/connectors/walletConnect.ts b/src/connectors/walletConnect.ts index d5f25ec..e0c5daa 100644 --- a/src/connectors/walletConnect.ts +++ b/src/connectors/walletConnect.ts @@ -1,5 +1,5 @@ import { Connector } from './connector' -import { getAddress, hexValue } from 'ethers/lib/utils' +import { getAddress, ethers } from 'ethers' import { ProviderNotFoundError, ProviderRpcError, @@ -120,7 +120,7 @@ export class WalletConnectConnector extends Connector< throw new SwitchChainNotSupportedError() } - const id = hexValue(chainId) + const id = ethers.toQuantity(chainId) try { await this.#provider.request({ diff --git a/src/utils/format.ts b/src/utils/format.ts index b5ba009..1039d3f 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -1,5 +1,4 @@ -import { BigNumber } from 'ethers' -import { formatEther, isAddress } from 'ethers/lib/utils' +import { formatEther, isAddress, BigNumberish } from 'ethers' import { checkChainId } from './check' import { useEthers } from '../composables' @@ -11,7 +10,7 @@ export function shortenAddress(address: string): string { } } -export function displayEther(balance: BigNumber | bigint, fixed = 2) { +export function displayEther(balance: BigNumberish | bigint, fixed = 2) { return (+formatEther(balance)).toFixed(fixed) } diff --git a/yarn.lock b/yarn.lock index d5d89f0..675f930 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.9.2": + version "1.9.2" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz#60111a5d9db45b2e5cbb6231b0bb8d97e8659316" + integrity sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg== + "@algolia/autocomplete-core@1.9.2": version "1.9.2" resolved "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.2.tgz" @@ -973,11 +978,21 @@ dependencies: "@noble/hashes" "1.3.1" +"@noble/hashes@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== + "@noble/hashes@1.3.1", "@noble/hashes@^1.3.0": version "1.3.1" resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/secp256k1@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -1785,6 +1800,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe" integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg== +"@types/node@18.15.13": + version "18.15.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" + integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== + "@types/node@^12.12.54": version "12.20.55" resolved "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz" @@ -2545,6 +2565,11 @@ aes-js@3.0.0: resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -4501,6 +4526,19 @@ ethers@^5.6.8: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +ethers@^6.6.3: + version "6.6.3" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.6.3.tgz#9bf11d1bd0f18c7c55087d1a52fdc8f3c33c8bab" + integrity sha512-g8wLXeRWSGDD0T+wsL3pvyc3aYnmxEEAwH8LSoDTDRhRsmJeNs9YMXlNU7ax2caO+zHkeI9MkHiz6rwxEjN4Mw== + dependencies: + "@adraffy/ens-normalize" "1.9.2" + "@noble/hashes" "1.1.2" + "@noble/secp256k1" "1.7.1" + "@types/node" "18.15.13" + aes-js "4.0.0-beta.5" + tslib "2.4.0" + ws "8.5.0" + event-pubsub@5.0.3: version "5.0.3" resolved "https://registry.npmjs.org/event-pubsub/-/event-pubsub-5.0.3.tgz" @@ -8959,6 +8997,11 @@ tslib@1.14.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^2, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0: version "2.5.3" resolved "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz" @@ -9464,6 +9507,11 @@ ws@7.4.6: resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + ws@^7.4.0, ws@^7.4.5, ws@^7.5.1: version "7.5.9" resolved "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz"