diff --git a/packages/mask/src/plugins/ArtBlocks/hooks/usePurchaseCallback.ts b/packages/mask/src/plugins/ArtBlocks/hooks/usePurchaseCallback.ts index 247496f2c7c1..e9f6614dbe62 100644 --- a/packages/mask/src/plugins/ArtBlocks/hooks/usePurchaseCallback.ts +++ b/packages/mask/src/plugins/ArtBlocks/hooks/usePurchaseCallback.ts @@ -14,15 +14,13 @@ export function usePurchaseCallback(chainId: ChainId, projectId: string, amount: return useAsyncFn(async () => { if (!genArt721MinterContract) return - const value = new BigNumber(schema === SchemaType.Native ? amount : 0).toFixed() - const config = { - from: account, - value, - } const tx = await encodeTransaction( genArt721MinterContract, genArt721MinterContract.methods.purchase(projectId), - config, + { + from: account, + value: new BigNumber(schema === SchemaType.Native ? amount : 0).toFixed(), + }, ) return connection.sendTransaction(tx) }, [account, amount, chainId, genArt721MinterContract, connection]) diff --git a/packages/plugins/EVM/src/state/Connection/connection.ts b/packages/plugins/EVM/src/state/Connection/connection.ts index 00dc70d240a7..cab8c876f7e5 100644 --- a/packages/plugins/EVM/src/state/Connection/connection.ts +++ b/packages/plugins/EVM/src/state/Connection/connection.ts @@ -57,7 +57,7 @@ import { Providers } from './provider' import type { ERC1155Metadata, ERC721Metadata, EVM_Connection, EVM_Web3ConnectionOptions } from './types' import { getReceiptStatus } from './utils' import { Web3StateSettings } from '../../settings' -import { getSubscriptionCurrentValue } from '@masknet/shared-base' +import { getSubscriptionCurrentValue, PartialRequired } from '@masknet/shared-base' const EMPTY_STRING = () => Promise.resolve('') const ZERO = () => Promise.resolve(0) @@ -109,14 +109,9 @@ class Connection implements EVM_Connection { // Hijack RPC requests and process them with koa like middleware private get hijackedRequest() { - return (requestArguments: RequestArguments, options?: EVM_Web3ConnectionOptions) => { + return (requestArguments: RequestArguments, initial?: EVM_Web3ConnectionOptions) => { return new Promise(async (resolve, reject) => { - const context = createContext(this, requestArguments, { - account: this.account, - chainId: this.chainId, - providerType: this.providerType, - ...options, - }) + const context = createContext(this, requestArguments, this.getOptions(initial)) try { await dispatch(context, async () => { @@ -163,36 +158,56 @@ class Connection implements EVM_Connection { } } - getWeb3(options?: EVM_Web3ConnectionOptions) { + private getOptions( + initial?: EVM_Web3ConnectionOptions, + overrides?: Partial, + ): PartialRequired { + return { + account: this.account, + chainId: this.chainId, + providerType: this.providerType, + ...initial, + overrides: { + from: this.account, + chainId: this.chainId, + ...initial?.overrides, + ...overrides?.overrides, + } + } + } + + getWeb3(initial?: EVM_Web3ConnectionOptions) { const web3 = createWeb3( - createWeb3Provider((requestArguments: RequestArguments) => this.hijackedRequest(requestArguments, options)), + createWeb3Provider((requestArguments: RequestArguments) => + this.hijackedRequest(requestArguments, this.getOptions(initial)), + ), ) return Promise.resolve(web3) } - getWeb3Provider(options?: EVM_Web3ConnectionOptions) { + getWeb3Provider(initial?: EVM_Web3ConnectionOptions) { const web3Provider = createWeb3Provider((requestArguments: RequestArguments) => - this.hijackedRequest(requestArguments, options), + this.hijackedRequest(requestArguments, this.getOptions(initial)), ) return Promise.resolve(web3Provider) } - async connect(options?: EVM_Web3ConnectionOptions): Promise> { + async connect(initial?: EVM_Web3ConnectionOptions): Promise> { return this.hijackedRequest>( { method: EthereumMethodType.MASK_LOGIN, params: [], }, - options, + this.getOptions(initial), ) } - async disconnect(options?: EVM_Web3ConnectionOptions): Promise { + async disconnect(initial?: EVM_Web3ConnectionOptions): Promise { await this.hijackedRequest( { method: EthereumMethodType.MASK_LOGOUT, params: [], }, - options, + this.getOptions(initial), ) } async transferFungibleToken( @@ -200,12 +215,13 @@ class Connection implements EVM_Connection { recipient: string, amount: string, memo?: string, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise { + const options = this.getOptions(initial) // Native - if (!address || isNativeTokenAddress(options?.chainId ?? this.chainId, address)) { + if (!address || isNativeTokenAddress(options.chainId, address)) { const tx: Transaction = { - from: options?.account ?? this.account, + from: options.account, to: recipient, value: toHex(amount), data: memo ? toHex(memo) : undefined, @@ -214,7 +230,7 @@ class Connection implements EVM_Connection { { ...tx, gas: await this.estimateTransaction(tx, 50000, options), - ...options?.overrides, + ...options.overrides, }, options, ) @@ -223,7 +239,7 @@ class Connection implements EVM_Connection { // ERC20 const contract = await this.getERC20Contract(address, options) const tx = contract?.methods.transfer(recipient, toHex(amount)) - return sendTransaction(contract, tx, options?.overrides) + return sendTransaction(contract, tx, options.overrides) } async transferNonFungibleToken( address: string, @@ -231,50 +247,52 @@ class Connection implements EVM_Connection { tokenId: string, amount?: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise { - const account = options?.account ?? this.account + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 if (actualSchema === SchemaType.ERC1155) { const contract = await this.getERC1155Contract(address, options) - const tx = contract?.methods.safeTransferFrom(account, recipient, tokenId, amount ?? '', '0x') - return sendTransaction(contract, tx, options?.overrides) + const tx = contract?.methods.safeTransferFrom(options.account, recipient, tokenId, amount ?? '', '0x') + return sendTransaction(contract, tx, options.overrides) } // ERC721 const contract = await this.getERC721Contract(address, options) - const tx = contract?.methods.transferFrom(account, recipient, tokenId) - return sendTransaction(contract, tx, options?.overrides) + const tx = contract?.methods.transferFrom(options.account, recipient, tokenId) + return sendTransaction(contract, tx, options.overrides) } - async getGasPrice(options?: EVM_Web3ConnectionOptions): Promise { + async getGasPrice(initial?: EVM_Web3ConnectionOptions): Promise { return this.hijackedRequest( { method: EthereumMethodType.ETH_GAS_PRICE, }, - options, + this.getOptions(initial), ) } - async getSchemaType(address: string, options?: EVM_Web3ConnectionOptions): Promise { + async getSchemaType(address: string, initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) const ERC165_INTERFACE_ID = '0x01ffc9a7' const ERC721_ENUMERABLE_INTERFACE_ID = '0x780e9d63' const ERC1155_ENUMERABLE_INTERFACE_ID = '0xd9b67a26' - const account = options?.account ?? this.account const erc165Contract = await this.getWeb3Contract(address, ERC165ABI as AbiItem[], options) - const isERC165 = await erc165Contract?.methods.supportsInterface(ERC165_INTERFACE_ID).call({ from: account }) + const isERC165 = await erc165Contract?.methods + .supportsInterface(ERC165_INTERFACE_ID) + .call({ from: options.account }) const isERC721 = await erc165Contract?.methods .supportsInterface(ERC721_ENUMERABLE_INTERFACE_ID) - .call({ from: account }) + .call({ from: options.account }) if (isERC165 && isERC721) return SchemaType.ERC721 const isERC1155 = await erc165Contract?.methods .supportsInterface(ERC1155_ENUMERABLE_INTERFACE_ID) - .call({ from: account }) + .call({ from: options.account }) if (isERC165 && isERC1155) return SchemaType.ERC1155 const isERC20 = (await this.getCode(address, options)) !== '0x' @@ -286,9 +304,9 @@ class Connection implements EVM_Connection { address: string, tokenId: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { - const actualChainId = options?.chainId ?? this.chainId + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) const allSettled = await Promise.allSettled([ this.getNonFungibleTokenMetadata(address, tokenId, schema, options), @@ -309,7 +327,7 @@ class Connection implements EVM_Connection { } return createNonFungibleToken( - actualChainId, + options.chainId, address, actualSchema ?? SchemaType.ERC721, tokenId, @@ -324,8 +342,9 @@ class Connection implements EVM_Connection { owner: string, tokenId: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ) { + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 @@ -343,7 +362,7 @@ class Connection implements EVM_Connection { address: string, tokenId?: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ) { const processURI = (uri: string) => { // e.g, @@ -359,7 +378,7 @@ class Connection implements EVM_Connection { return uri } - const actualChainId = options?.chainId ?? this.chainId + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 @@ -372,7 +391,7 @@ class Connection implements EVM_Connection { fetch: this.context?.fetch, }) return createNonFungibleTokenMetadata( - actualChainId, + options.chainId, response.name, '', response.description, @@ -390,7 +409,7 @@ class Connection implements EVM_Connection { fetch: this.context?.fetch, }) return createNonFungibleTokenMetadata( - actualChainId, + options.chainId, response.name, '', response.description, @@ -402,9 +421,9 @@ class Connection implements EVM_Connection { async getNonFungibleTokenContract( address: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { - const actualChainId = options?.chainId ?? this.chainId + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 @@ -420,7 +439,7 @@ class Connection implements EVM_Connection { ) as string[] return createNonFungibleTokenContract( - actualChainId, + options.chainId, SchemaType.ERC1155, address, name ?? 'Unknown Token', @@ -438,7 +457,7 @@ class Connection implements EVM_Connection { const [name, symbol] = results.map((result) => (result.status === 'fulfilled' ? result.value : '')) as string[] return createNonFungibleTokenContract( - actualChainId, + options.chainId, SchemaType.ERC721, address, name ?? 'Unknown Token', @@ -448,9 +467,9 @@ class Connection implements EVM_Connection { async getNonFungibleTokenCollection( address: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { - const actualChainId = options?.chainId ?? this.chainId + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 @@ -462,60 +481,59 @@ class Connection implements EVM_Connection { const contract = await this.getERC721Contract(address, options) const results = await Promise.allSettled([contract?.methods.name().call() ?? EMPTY_STRING]) const [name] = results.map((result) => (result.status === 'fulfilled' ? result.value : '')) as string[] - return createNonFungibleTokenCollection(actualChainId, address, name ?? 'Unknown Token', '') + return createNonFungibleTokenCollection(options.chainId, address, name ?? 'Unknown Token', '') } - async switchChain(options?: EVM_Web3ConnectionOptions): Promise { - await Providers[options?.providerType ?? this.providerType].switchChain(options?.chainId) + async switchChain(initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) + await Providers[options.providerType].switchChain(options.chainId) } - async getNativeTokenBalance(options?: EVM_Web3ConnectionOptions): Promise { - const account = options?.account ?? this.account - if (!isValidAddress(account)) return '0' - return this.getBalance(options?.account ?? this.account, options) + async getNativeTokenBalance(initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) + if (!isValidAddress(options.account)) return '0' + return this.getBalance(options.account, options) } - async getFungibleTokenBalance(address: string, options?: EVM_Web3ConnectionOptions): Promise { - const actualAccount = options?.account ?? this.account - const actualChainId = options?.chainId ?? this.chainId + async getFungibleTokenBalance(address: string, initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) // Native - if (!address || isNativeTokenAddress(actualChainId, address)) return this.getNativeTokenBalance(options) + if (!address || isNativeTokenAddress(options.chainId, address)) return this.getNativeTokenBalance(options) // ERC20 const contract = await this.getERC20Contract(address, options) - return contract?.methods.balanceOf(actualAccount).call() ?? '0' + return contract?.methods.balanceOf(options.account).call() ?? '0' } async getNonFungibleTokenBalance( address: string, tokenId?: string, schema?: SchemaType, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise { - const actualAccount = options?.account ?? this.account + const options = this.getOptions(initial) const actualSchema = schema ?? (await this.getSchemaType(address, options)) // ERC1155 if (actualSchema === SchemaType.ERC1155) { const contract = await this.getERC1155Contract(address, options) - return contract?.methods?.balanceOf(actualAccount, tokenId ?? '').call() ?? '0' + return contract?.methods?.balanceOf(options.account, tokenId ?? '').call() ?? '0' } // ERC721 const contract = await this.getERC721Contract(address, options) - return contract?.methods.balanceOf(actualAccount).call() ?? '0' + return contract?.methods.balanceOf(options.account).call() ?? '0' } async getFungibleTokensBalance( listOfAddress: string[], - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { if (!listOfAddress.length) return {} - const account = options?.account ?? this.account - const actualChainId = options?.chainId ?? this.chainId - const { NATIVE_TOKEN_ADDRESS = '' } = getTokenConstants(actualChainId) - const { BALANCE_CHECKER_ADDRESS } = getEthereumConstants(actualChainId) + const options = this.getOptions(initial) + const { NATIVE_TOKEN_ADDRESS = '' } = getTokenConstants(options.chainId) + const { BALANCE_CHECKER_ADDRESS } = getEthereumConstants(options.chainId) const entities: Array<[string, string]> = [] if (listOfAddress.some(currySameAddress(NATIVE_TOKEN_ADDRESS))) { - entities.push([NATIVE_TOKEN_ADDRESS, await this.getBalance(this.account, options)]) + entities.push([NATIVE_TOKEN_ADDRESS, await this.getBalance(options.account, options)]) } const listOfNonNativeAddress = listOfAddress.filter((x) => !isSameAddress(NATIVE_TOKEN_ADDRESS, x)) @@ -526,10 +544,10 @@ class Connection implements EVM_Connection { BalanceCheckerABI as AbiItem[], options, ) - const balances = await contract?.methods.balances([account], listOfNonNativeAddress).call({ + const balances = await contract?.methods.balances([options.account], listOfNonNativeAddress).call({ // cannot check the sender's balance in the same contract from: undefined, - chainId: numberToHex(actualChainId), + chainId: numberToHex(options.account), }) listOfNonNativeAddress.forEach((x, i) => { @@ -541,39 +559,42 @@ class Connection implements EVM_Connection { async getNonFungibleTokensBalance( listOfAddress: string[], - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { if (!listOfAddress.length) return {} - const { BALANCE_CHECKER_ADDRESS } = getEthereumConstants(this.chainId) + const options = this.getOptions(initial) + const { BALANCE_CHECKER_ADDRESS } = getEthereumConstants(options.chainId) const contract = await this.getWeb3Contract( BALANCE_CHECKER_ADDRESS ?? '', BalanceCheckerABI as AbiItem[], options, ) - const result = await contract?.methods.balances([options?.account ?? this.account], listOfAddress).call({ + const result = await contract?.methods.balances([options.account], listOfAddress).call({ // cannot check the sender's balance in the same contract from: undefined, - chainId: numberToHex(options?.chainId ?? this.chainId), + chainId: numberToHex(options.chainId), }) if (result?.length !== listOfAddress.length) return {} return Object.fromEntries(listOfAddress.map<[string, string]>((x, i) => [x, result[i]])) } - getNativeToken(options?: EVM_Web3ConnectionOptions): Promise> { - const token = createNativeToken(options?.chainId ?? this.chainId) + getNativeToken(initial?: EVM_Web3ConnectionOptions): Promise> { + const options = this.getOptions(initial) + const token = createNativeToken(options.chainId) if (!token) throw new Error('Failed to create native token.') return Promise.resolve(token) } async getFungibleToken( address: string, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ): Promise> { + const options = this.getOptions(initial) + // Native - if (!address || isNativeTokenAddress(options?.chainId ?? this.chainId, address)) - return this.getNativeToken(options) + if (!address || isNativeTokenAddress(options.chainId, address)) return this.getNativeToken(options) // ERC20 const contract = await this.getERC20Contract(address, options) @@ -589,7 +610,7 @@ class Connection implements EVM_Connection { result.status === 'fulfilled' ? result.value : '', ) as string[] return createERC20Token( - options?.chainId ?? this.chainId, + options.chainId, address, parseStringOrBytes32(name, nameBytes32, 'Unknown Token'), parseStringOrBytes32(symbol, symbolBytes32, 'UNKNOWN'), @@ -600,25 +621,30 @@ class Connection implements EVM_Connection { async getWeb3Contract( address: string, ABI: AbiItem[], - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ) { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) return createContract(web3, address, ABI) } - async getERC20Contract(address: string, options?: EVM_Web3ConnectionOptions) { + async getERC20Contract(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.getWeb3Contract(address, ERC20ABI as AbiItem[], options) } - async getERC721Contract(address: string, options?: EVM_Web3ConnectionOptions) { + async getERC721Contract(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.getWeb3Contract(address, ERC721ABI as AbiItem[], options) } - async getERC1155Contract(address: string, options?: EVM_Web3ConnectionOptions) { + async getERC1155Contract(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.getWeb3Contract(address, ERC1155ABI as AbiItem[], options) } - async getAccount(options?: EVM_Web3ConnectionOptions) { + async getAccount(initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) const accounts = await this.hijackedRequest( { method: EthereumMethodType.ETH_ACCOUNTS, @@ -628,7 +654,8 @@ class Connection implements EVM_Connection { return first(accounts) ?? '' } - async getChainId(options?: EVM_Web3ConnectionOptions) { + async getChainId(initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) const chainId = await this.hijackedRequest( { method: EthereumMethodType.ETH_CHAIN_ID, @@ -638,7 +665,8 @@ class Connection implements EVM_Connection { return Number.parseInt(chainId, 16) } - getBlock(noOrId: number | string, options?: EVM_Web3ConnectionOptions) { + getBlock(noOrId: number | string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_GET_BLOCK_BY_NUMBER, @@ -648,7 +676,8 @@ class Connection implements EVM_Connection { ) } - getBlockNumber(options?: EVM_Web3ConnectionOptions) { + getBlockNumber(initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_BLOCK_NUMBER, @@ -657,13 +686,15 @@ class Connection implements EVM_Connection { ) } - async getBlockTimestamp(options?: EVM_Web3ConnectionOptions): Promise { + async getBlockTimestamp(initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) const blockNumber = await this.getBlockNumber(options) const block = await this.getBlock(blockNumber) return Number.parseInt(block.timestamp, 16) } - getBalance(address: string, options?: EVM_Web3ConnectionOptions) { + getBalance(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_GET_BALANCE, @@ -673,7 +704,8 @@ class Connection implements EVM_Connection { ) } - getCode(address: string, options?: EVM_Web3ConnectionOptions) { + getCode(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_GET_CODE, @@ -683,7 +715,8 @@ class Connection implements EVM_Connection { ) } - async getTransaction(hash: string, options?: EVM_Web3ConnectionOptions) { + async getTransaction(hash: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_GET_TRANSACTION_BY_HASH, @@ -693,14 +726,15 @@ class Connection implements EVM_Connection { ) } - async estimateTransaction(transaction: Transaction, fallback = 21000, options?: EVM_Web3ConnectionOptions) { + async estimateTransaction(transaction: Transaction, fallback = 21000, initial?: EVM_Web3ConnectionOptions) { try { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_ESTIMATE_GAS, params: [ { - from: options?.account ?? this.account, + from: options.account, ...transaction, }, ], @@ -712,7 +746,8 @@ class Connection implements EVM_Connection { } } - getTransactionReceipt(hash: string, options?: EVM_Web3ConnectionOptions) { + getTransactionReceipt(hash: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_GET_TRANSACTION_RECEIPT, @@ -722,11 +757,13 @@ class Connection implements EVM_Connection { ) } - async getTransactionStatus(id: string, options?: EVM_Web3ConnectionOptions): Promise { + async getTransactionStatus(id: string, initial?: EVM_Web3ConnectionOptions): Promise { + const options = this.getOptions(initial) return getReceiptStatus(await this.getTransactionReceipt(id, options)) } - async getTransactionNonce(address: string, options?: EVM_Web3ConnectionOptions) { + async getTransactionNonce(address: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) const count = await this.hijackedRequest( { method: EthereumMethodType.ETH_GET_TRANSACTION_COUNT, @@ -740,17 +777,17 @@ class Connection implements EVM_Connection { signMessage( dataToSign: string, signType?: 'personalSign' | 'typedDataSign' | Omit, - options?: EVM_Web3ConnectionOptions, + initial?: EVM_Web3ConnectionOptions, ) { - const account = options?.account ?? this.account - if (!account) throw new Error('Unknown account.') + const options = this.getOptions(initial) + if (!options.account) throw new Error('Unknown account.') switch (signType) { case 'personalSign': return this.hijackedRequest( { method: EthereumMethodType.PERSONAL_SIGN, - params: [dataToSign, account, ''].filter((x) => typeof x !== 'undefined'), + params: [dataToSign, options.account, ''].filter((x) => typeof x !== 'undefined'), }, options, ) @@ -758,7 +795,7 @@ class Connection implements EVM_Connection { return this.hijackedRequest( { method: EthereumMethodType.ETH_SIGN_TYPED_DATA, - params: [account, dataToSign], + params: [options.account, dataToSign], }, options, ) @@ -771,14 +808,16 @@ class Connection implements EVM_Connection { dataToVerify: string, signature: string, signType?: string, - options?: ConnectionOptions, + initial?: ConnectionOptions, ) { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const dataToSign = await web3.eth.personal.ecRecover(dataToVerify, signature) return dataToSign === dataToVerify } - async signTransaction(transaction: Transaction, options?: EVM_Web3ConnectionOptions) { + async signTransaction(transaction: Transaction, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) const signed = await this.hijackedRequest( { method: EthereumMethodType.ETH_SIGN_TRANSACTION, @@ -789,18 +828,19 @@ class Connection implements EVM_Connection { return signed.rawTransaction ?? '' } - signTransactions(transactions: Transaction[], options?: EVM_Web3ConnectionOptions) { - return Promise.all(transactions.map((x) => this.signTransaction(x))) + signTransactions(transactions: Transaction[], initial?: EVM_Web3ConnectionOptions) { + return Promise.all(transactions.map((x) => this.signTransaction(x, initial))) } - callTransaction(transaction: Transaction, options?: EVM_Web3ConnectionOptions) { + callTransaction(transaction: Transaction, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_CALL, params: [ { ...transaction, - ...options?.overrides, + ...options.overrides, }, 'latest', ], @@ -808,7 +848,8 @@ class Connection implements EVM_Connection { options, ) } - async sendTransaction(transaction: Transaction, options?: EVM_Web3ConnectionOptions) { + async sendTransaction(transaction: Transaction, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) // send a transaction which will add into the internal transaction list and start to watch it for confirmation const hash = await this.hijackedRequest( { @@ -816,7 +857,7 @@ class Connection implements EVM_Connection { params: [ { ...transaction, - ...options?.overrides, + ...options.overrides, }, ], }, @@ -840,7 +881,8 @@ class Connection implements EVM_Connection { }) } - sendSignedTransaction(signature: string, options?: EVM_Web3ConnectionOptions) { + sendSignedTransaction(signature: string, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.ETH_SEND_RAW_TRANSACTION, @@ -850,7 +892,8 @@ class Connection implements EVM_Connection { ) } - replaceRequest(hash: string, transaction: Transaction, options?: EVM_Web3ConnectionOptions) { + replaceRequest(hash: string, transaction: Transaction, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.MASK_REPLACE_TRANSACTION, @@ -860,7 +903,8 @@ class Connection implements EVM_Connection { ) } - cancelRequest(hash: string, transaction: Transaction, options?: EVM_Web3ConnectionOptions) { + cancelRequest(hash: string, transaction: Transaction, initial?: EVM_Web3ConnectionOptions) { + const options = this.getOptions(initial) return this.hijackedRequest( { method: EthereumMethodType.MASK_REPLACE_TRANSACTION, diff --git a/packages/plugins/EVM/src/state/Hub/hub.ts b/packages/plugins/EVM/src/state/Hub/hub.ts index 5a95c60fafc9..5b0afbd853ec 100644 --- a/packages/plugins/EVM/src/state/Hub/hub.ts +++ b/packages/plugins/EVM/src/state/Hub/hub.ts @@ -1,3 +1,4 @@ +import type { PartialRequired } from '@masknet/shared-base' import { Alchemy_EVM, CoinGecko, @@ -45,72 +46,85 @@ import type { EVM_Hub } from './types' class Hub implements EVM_Hub { constructor( - private chainId?: ChainId, - private account?: string, + private chainId: ChainId, + private account: string, private sourceType?: SourceType, private currencyType?: CurrencyType, ) {} + private getOptions( + initial?: HubOptions, + overrides?: Partial>, + ): PartialRequired, 'chainId' | 'account'> { + return { + chainId: this.chainId, + account: this.account, + sourceType: this.sourceType, + currencyType: this.currencyType, + ...initial, + ...overrides, + } + } + async getFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const expectedChainId = options?.chainId ?? chainId - const { FUNGIBLE_TOKEN_LISTS = [] } = getTokenListConstants(expectedChainId) - return TokenList.fetchFungibleTokensFromTokenLists(expectedChainId, FUNGIBLE_TOKEN_LISTS) + const options = this.getOptions(initial, { + chainId, + }) + const { FUNGIBLE_TOKEN_LISTS = [] } = getTokenListConstants(options.chainId) + return TokenList.fetchFungibleTokensFromTokenLists(options.chainId, FUNGIBLE_TOKEN_LISTS) } async getNonFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { throw new Error('Method not implemented.') } - async getGasOptions( - chainId: ChainId, - options?: HubOptions | undefined, - ): Promise> { - const expectedChainId = options?.chainId ?? chainId - + async getGasOptions(chainId: ChainId, initial?: HubOptions): Promise> { + const options = this.getOptions(initial, { + chainId, + }) try { - const isEIP1559 = chainResolver.isSupport(expectedChainId, 'EIP1559') - if (isEIP1559) return await MetaSwap.getGasOptions(expectedChainId) - return await DeBank.getGasOptions(expectedChainId) + const isEIP1559 = chainResolver.isSupport(options.chainId, 'EIP1559') + if (isEIP1559) return await MetaSwap.getGasOptions(options.chainId) + return await DeBank.getGasOptions(options.chainId) } catch (error) { - return EthereumWeb3.getGasOptions(expectedChainId) + return EthereumWeb3.getGasOptions(options.chainId) } } - getFungibleAsset( - address: string, - options?: HubOptions | undefined, - ): Promise> { + getFungibleAsset(address: string, initial?: HubOptions): Promise> { throw new Error('Method not implemented.') } async getFungibleAssets( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const { indicator, sourceType } = options ?? {} + const options = this.getOptions(initial, { + account, + }) // only the first page is available - if ((indicator ?? 0) > 0) return createPageable([], createIndicator(options?.indicator)) + if ((options.indicator ?? 0) > 0) return createPageable([], createIndicator(options.indicator)) const providers = { [SourceType.DeBank]: DeBank, [SourceType.Zerion]: Zerion, } const predicate = createPredicate(Object.keys(providers) as Array) - const filteredProviders = predicate(sourceType) ? [providers[sourceType]] : [DeBank, Zerion] + const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : [DeBank, Zerion] return attemptUntil( - filteredProviders.map((x) => () => x.getAssets(account, { chainId: this.chainId, ...options })), - createPageable([], createIndicator(options?.indicator)), + filteredProviders.map((x) => () => x.getAssets(options.account, options)), + createPageable([], createIndicator(options.indicator)), ) } async getNonFungibleAsset( address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise | undefined> { - const { sourceType } = options ?? {} + const options = this.getOptions(initial) const providers = { [SourceType.OpenSea]: OpenSea, [SourceType.Rarible]: Rarible, @@ -118,8 +132,8 @@ class Hub implements EVM_Hub { } const predicate = createPredicate(Object.keys(providers) as Array) const defaultProviders = - options?.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] - const filteredProviders = predicate(sourceType) ? [providers[sourceType]] : defaultProviders + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] + const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : defaultProviders return attemptUntil( filteredProviders.map((x) => () => x.getAsset(address, tokenId, options)), undefined, @@ -127,9 +141,11 @@ class Hub implements EVM_Hub { } async getNonFungibleTokens( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const { sourceType } = options ?? {} + const options = this.getOptions(initial, { + account, + }) const providers = { [SourceType.OpenSea]: OpenSea, [SourceType.Rarible]: Rarible, @@ -137,50 +153,51 @@ class Hub implements EVM_Hub { } const predicate = createPredicate(Object.keys(providers) as Array) const defaultProviders = - options?.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] - const filteredProviders = predicate(sourceType) ? [providers[sourceType]] : defaultProviders + options.chainId === ChainId.Mainnet ? [OpenSea, Alchemy_EVM, Rarible] : [Alchemy_EVM, OpenSea, Rarible] + const filteredProviders = predicate(options.sourceType) ? [providers[options.sourceType]] : defaultProviders return attemptUntil( - filteredProviders.map((x) => () => x.getAssets(account, { chainId: this.chainId, ...options })), - createPageable([], createIndicator(options?.indicator)), + filteredProviders.map((x) => () => x.getAssets(options.account, options)), + createPageable([], createIndicator(options.indicator)), ) } getNonFungibleCollections( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - return OpenSea.getCollections(account, { ...options, chainId: options?.chainId ?? this.chainId }) + const options = this.getOptions(initial, { + account, + }) + return OpenSea.getCollections(options.account, options) } - getFungibleTokenPrice( - chainId: ChainId, - address: string, - options?: HubOptions | undefined, - ): Promise { - const expectedChainId = options?.chainId ?? chainId - const expectedCurrencyType = options?.currencyType ?? this.currencyType - const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(expectedChainId) + getFungibleTokenPrice(chainId: ChainId, address: string, initial?: HubOptions): Promise { + const options = this.getOptions(initial, { + chainId, + }) + const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(options.chainId) if (isNativeTokenAddress(address)) { - return CoinGecko.getTokenPriceByCoinId(COIN_ID, expectedCurrencyType) + return CoinGecko.getTokenPriceByCoinId(COIN_ID, options.currencyType) } - - return CoinGecko.getTokenPrice(PLATFORM_ID, address, expectedCurrencyType) + return CoinGecko.getTokenPrice(PLATFORM_ID, address, options.currencyType) } getNonFungibleTokenPrice( chainId: ChainId, address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } async getFungibleTokenIconURLs( chainId: ChainId, address: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { - const expectedChainId = options?.chainId ?? chainId - const { TOKEN_ASSET_BASE_URI = [] } = getTokenAssetBaseURLConstants(expectedChainId) + const options = this.getOptions(initial, { + chainId, + }) + const { TOKEN_ASSET_BASE_URI = [] } = getTokenAssetBaseURLConstants(options.chainId) const checkSummedAddress = formatEthereumAddress(address) if (isSameAddress(getTokenConstants().NATIVE_TOKEN_ADDRESS, checkSummedAddress)) { @@ -197,20 +214,28 @@ class Hub implements EVM_Hub { chainId: ChainId, address: string, tokenId?: string | undefined, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } async getTransactions( chainId: ChainId, account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const expectedChainId = options?.chainId ?? chainId - return DeBank.getTransactions(account, { chainId: expectedChainId }) + const options = this.getOptions(initial, { + account, + chainId, + }) + return DeBank.getTransactions(options.account, options) } } -export function createHub(chainId?: ChainId, account?: string, sourceType?: SourceType, currencyType?: CurrencyType) { +export function createHub( + chainId = ChainId.Mainnet, + account = '', + sourceType?: SourceType, + currencyType?: CurrencyType, +) { return new Hub(chainId, account, sourceType, currencyType) } diff --git a/packages/plugins/Flow/src/state/Connection/connection.ts b/packages/plugins/Flow/src/state/Connection/connection.ts index f4b794a18554..328857ac99e0 100644 --- a/packages/plugins/Flow/src/state/Connection/connection.ts +++ b/packages/plugins/Flow/src/state/Connection/connection.ts @@ -12,7 +12,7 @@ import { NonFungibleTokenMetadata, TransactionStatusType, } from '@masknet/web3-shared-base' -import { toHex } from '@masknet/shared-base' +import { PartialRequired, toHex } from '@masknet/shared-base' import { Providers } from './provider' import type { FlowWeb3Connection as BaseConnection, FlowConnectionOptions } from './types' import { Web3StateSettings } from '../../settings' @@ -26,60 +26,71 @@ class Connection implements BaseConnection { private context?: Plugin.Shared.SharedContext, ) {} - private _getWeb3Provider(options?: FlowConnectionOptions) { - return Providers[options?.providerType ?? this.providerType] + private getOptions( + initial?: FlowConnectionOptions, + overrides?: Partial, + ): PartialRequired { + return { + account: this.account, + chainId: this.chainId, + providerType: this.providerType, + ...initial, + ...overrides, + } + } + + private _getWeb3Provider(initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) + return Providers[options.providerType] } - getWeb3(options?: FlowConnectionOptions) { - return this._getWeb3Provider(options).createWeb3({ - account: options?.account ?? this.account, - chainId: options?.chainId ?? this.chainId, - }) - } - getWeb3Provider(options?: FlowConnectionOptions) { - return this._getWeb3Provider(options).createWeb3Provider({ - account: options?.account ?? this.account, - chainId: options?.chainId ?? this.chainId, - }) - } - async connect(options?: FlowConnectionOptions): Promise> { + getWeb3(initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) + return this._getWeb3Provider(options).createWeb3(options) + } + getWeb3Provider(initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) + return this._getWeb3Provider(options).createWeb3Provider(options) + } + async connect(initial?: FlowConnectionOptions): Promise> { + const options = this.getOptions(initial) return { account: '', chainId: ChainId.Mainnet, - ...(await Web3StateSettings.value.Provider?.connect( - options?.chainId ?? this.chainId, - options?.providerType ?? this.providerType, - )), + ...(await Web3StateSettings.value.Provider?.connect(options.chainId, options.providerType)), } } - async disconnect(options?: FlowConnectionOptions): Promise { - await Web3StateSettings.value.Provider?.disconnect(options?.providerType ?? this.providerType) + async disconnect(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) + await Web3StateSettings.value.Provider?.disconnect(options.providerType) } - getGasPrice(options?: FlowConnectionOptions): Promise { + getGasPrice(initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - getSchemaType(address: string, options?: FlowConnectionOptions): Promise { + getSchemaType(address: string, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } getNonFungibleTokenContract( address: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } getNonFungibleTokenCollection( address: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } - async getBlock(no: number, options?: FlowConnectionOptions): Promise { + async getBlock(no: number, initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) return web3.send([web3.getBlock(), web3.atBlockHeight(no)]).then(web3.decode) } - async getBlockTimestamp(options?: FlowConnectionOptions): Promise { + async getBlockTimestamp(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const blockHeader: BlockHeaderObject = await web3.send([web3.getBlockHeader()]).then(web3.decode) return getUnixTime(new Date(blockHeader.timestamp as unknown as string)) @@ -89,7 +100,7 @@ class Connection implements BaseConnection { recipient: string, amount: string, memo?: string, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise { throw new Error('Method not implemented.') } @@ -99,51 +110,51 @@ class Connection implements BaseConnection { tokenId: string, amount: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise { throw new Error('Method not implemented.') } - getNativeToken(options?: FlowConnectionOptions): Promise> { + getNativeToken(initial?: FlowConnectionOptions): Promise> { throw new Error('Method not implemented.') } - getNativeTokenBalance(options?: FlowConnectionOptions): Promise { + getNativeTokenBalance(initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - getFungibleTokenBalance(address: string, options?: FlowConnectionOptions): Promise { + getFungibleTokenBalance(address: string, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } getNonFungibleTokenBalance( address: string, tokenId?: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise { throw new Error('Method not implemented.') } getFungibleTokensBalance( listOfAddress: string[], - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } getNonFungibleTokensBalance( listOfAddress: string[], - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } - getCode(address: string, options?: FlowConnectionOptions): Promise { + getCode(address: string, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - getFungibleToken(address: string, options?: FlowConnectionOptions): Promise> { + getFungibleToken(address: string, initial?: FlowConnectionOptions): Promise> { throw new Error('Method not implemented.') } getNonFungibleToken( address: string, tokenId: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } @@ -152,7 +163,7 @@ class Connection implements BaseConnection { owner: string, tokenId: string, schema?: SchemaType | undefined, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise { throw new Error('Method not implemented.') } @@ -160,36 +171,42 @@ class Connection implements BaseConnection { address: string, tokenId: string, schemaType?: SchemaType, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } - async getAccount(options?: FlowConnectionOptions): Promise { + async getAccount(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) return web3.currentUser().addr ?? '' } - async getChainId(options?: FlowConnectionOptions): Promise { - return options?.chainId ?? this.chainId + async getChainId(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) + return options.chainId } - async getBlockNumber(options?: FlowConnectionOptions): Promise { + async getBlockNumber(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const blockHeader = await web3.send([web3.getBlockHeader()]).then(web3.decode) return blockHeader.height } - async getBalance(address: string, options?: FlowConnectionOptions): Promise { + async getBalance(address: string, initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const account = await web3.send([web3.getAccount(address)]).then(web3.decode) return account.balance.toFixed() } - async getTransaction(id: string, options?: FlowConnectionOptions) { + async getTransaction(id: string, initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) return web3.getTransaction(id) } - async getTransactionReceipt(id: string, options?: FlowConnectionOptions) { + async getTransactionReceipt(id: string, initial?: FlowConnectionOptions) { return null } - async getTransactionStatus(id: string, options?: FlowConnectionOptions): Promise { + async getTransactionStatus(id: string, initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const { status } = web3.getTransactionStatus(id) const status_ = status as TransactionStatusCode @@ -208,16 +225,19 @@ class Connection implements BaseConnection { unreachable(status_) } } - async getTransactionNonce(address: string, options?: FlowConnectionOptions): Promise { + async getTransactionNonce(address: string, initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const account = web3.getAccount(address) const key = first(account.keys) return key?.sequenceNumber ?? 0 } - async switchChain(options?: FlowConnectionOptions): Promise { - await Providers[options?.providerType ?? this.providerType].switchChain(options?.chainId) + async switchChain(initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) + await Providers[options.providerType].switchChain(options.chainId) } - async signMessage(dataToSign: string, signType?: string, options?: FlowConnectionOptions) { + async signMessage(dataToSign: string, signType?: string, initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const data = new TextEncoder().encode(dataToSign) const signed = first(await web3.currentUser.signUserMessage(toHex(data))) @@ -228,41 +248,44 @@ class Connection implements BaseConnection { dataToVerify: string, signature: string, signType?: string, - options?: FlowConnectionOptions, + initial?: FlowConnectionOptions, ): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) - if (!options?.account) throw new Error('No account found.') + if (!options.account) throw new Error('No account found.') return web3.verifyUserSignatures(dataToVerify, [ { - addr: options?.account, + addr: options.account, keyId: 1, signature, }, ]) } - async callTransaction(query: QueryOptions, options?: FlowConnectionOptions) { + async callTransaction(query: QueryOptions, initial?: FlowConnectionOptions) { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) return web3.query(query) } - async sendTransaction(mutation: MutateOptions, options?: FlowConnectionOptions): Promise { + async sendTransaction(mutation: MutateOptions, initial?: FlowConnectionOptions): Promise { + const options = this.getOptions(initial) const web3 = await this.getWeb3(options) const id = await web3.mutate(mutation) await web3.tx(id).onceSealed() return id } - signTransaction(mutation: MutateOptions, options?: FlowConnectionOptions): Promise { + signTransaction(mutation: MutateOptions, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - signTransactions(mutations: MutateOptions[], options?: FlowConnectionOptions): Promise { + signTransactions(mutations: MutateOptions[], initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - sendSignedTransaction(signature: never, options?: FlowConnectionOptions): Promise { + sendSignedTransaction(signature: never, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - replaceRequest(hash: string, config: MutateOptions, options?: FlowConnectionOptions): Promise { + replaceRequest(hash: string, config: MutateOptions, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } - cancelRequest(hash: string, config: MutateOptions, options?: FlowConnectionOptions): Promise { + cancelRequest(hash: string, config: MutateOptions, initial?: FlowConnectionOptions): Promise { throw new Error('Method not implemented.') } } diff --git a/packages/plugins/Flow/src/state/Hub/hub.ts b/packages/plugins/Flow/src/state/Hub/hub.ts index 7c13489558ab..ed5b828afe30 100644 --- a/packages/plugins/Flow/src/state/Hub/hub.ts +++ b/packages/plugins/Flow/src/state/Hub/hub.ts @@ -1,3 +1,4 @@ +import type { PartialRequired } from '@masknet/shared-base' import { Alchemy_FLOW } from '@masknet/web3-providers' import type { FungibleToken, @@ -24,15 +25,31 @@ class Hub implements FlowHub { private currencyType?: CurrencyType, ) {} + private getOptions( + initial?: HubOptions, + overrides?: Partial>, + ): PartialRequired, 'chainId' | 'account'> { + return { + chainId: this.chainId, + account: this.account, + sourceType: this.sourceType, + currencyType: this.currencyType, + ...initial, + ...overrides, + } + } + async getFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const expectedChainId = options?.chainId ?? chainId - const { FLOW_ADDRESS = '', FUSD_ADDRESS = '', TETHER_ADDRESS = '' } = getTokenConstants(expectedChainId) + const options = this.getOptions(initial, { + chainId, + }) + const { FLOW_ADDRESS = '', FUSD_ADDRESS = '', TETHER_ADDRESS = '' } = getTokenConstants(options.chainId) return [ createFungibleToken( - expectedChainId, + options.chainId, FLOW_ADDRESS, 'Flow', 'FLOW', @@ -40,7 +57,7 @@ class Hub implements FlowHub { new URL('../../assets/flow.png', import.meta.url).toString(), ), createFungibleToken( - expectedChainId, + options.chainId, FUSD_ADDRESS, 'Flow USD', 'FUSD', @@ -48,7 +65,7 @@ class Hub implements FlowHub { new URL('../../assets/FUSD.png', import.meta.url).toString(), ), createFungibleToken( - expectedChainId, + options.chainId, TETHER_ADDRESS, 'Tether USD', 'tUSD', @@ -59,49 +76,45 @@ class Hub implements FlowHub { } async getNonFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { throw new Error('Method not implemented.') } - getGasOptions( - chainId: ChainId, - options?: HubOptions | undefined, - ): Promise> { + getGasOptions(chainId: ChainId, initial?: HubOptions): Promise> { throw new Error('Method not implemented.') } - getFungibleAsset( - address: string, - options?: HubOptions | undefined, - ): Promise> { + getFungibleAsset(address: string, initial?: HubOptions): Promise> { throw new Error('Method not implemented.') } async getFungibleAssets( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - const expectedChainId = options?.chainId ?? this.chainId - return FlowRPC.getFungibleAssets(expectedChainId, account) + const options = this.getOptions(initial, { + account, + }) + return FlowRPC.getFungibleAssets(options.chainId, options.account) } async getNonFungibleAsset( address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ownerAddress?: string, contractName?: string, ): Promise | undefined> { + const options = this.getOptions(initial) return Alchemy_FLOW.getAsset(address, tokenId, options, ownerAddress, contractName) } getNonFungibleTokens( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - return Alchemy_FLOW.getAssets(account, options) + const options = this.getOptions(initial, { + account, + }) + return Alchemy_FLOW.getAssets(options.account, options) } - getFungibleTokenPrice( - chainId: ChainId, - address: string, - options?: HubOptions | undefined, - ): Promise { + getFungibleTokenPrice(chainId: ChainId, address: string, initial?: HubOptions): Promise { // The Flow chain is unlisted in CoinGecko. throw new Error('Method not implemented.') } @@ -109,14 +122,14 @@ class Hub implements FlowHub { chainId: ChainId, address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } async getFungibleTokenIconURLs( chainId: ChainId, address: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } @@ -124,14 +137,14 @@ class Hub implements FlowHub { chainId: ChainId, address: string, tokenId?: string | undefined, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } getTransactions( chainId: ChainId, account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { throw new Error('Method not implemented.') } diff --git a/packages/plugins/Solana/src/state/Connection/connection.ts b/packages/plugins/Solana/src/state/Connection/connection.ts index ed21206d568f..dd7a28e48c74 100644 --- a/packages/plugins/Solana/src/state/Connection/connection.ts +++ b/packages/plugins/Solana/src/state/Connection/connection.ts @@ -27,6 +27,7 @@ import { isNativeTokenAddress } from '../../utils' import { Providers } from './provider' import { createTransferInstruction, getOrCreateAssociatedTokenAccount } from './spl-token' import type { SolanaConnection as BaseConnection, SolanaWeb3ConnectionOptions } from './types' +import type { PartialRequired } from '@masknet/shared-base' class Connection implements BaseConnection { private connections: Map = new Map() @@ -38,47 +39,58 @@ class Connection implements BaseConnection { private context?: Plugin.Shared.SharedContext, ) {} - private _getWeb3Provider(options?: SolanaWeb3ConnectionOptions) { - return Providers[options?.providerType ?? this.providerType] + private getOptions( + initial?: SolanaWeb3ConnectionOptions, + overrides?: Partial, + ): PartialRequired { + return { + account: this.account, + chainId: this.chainId, + providerType: this.providerType, + ...initial, + ...overrides, + } + } + + private _getWeb3Provider(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return Providers[options.providerType] } - private async _attachRecentBlockHash(transaction: Transaction, options?: SolanaWeb3ConnectionOptions) { - const chainId = options?.chainId ?? ChainId.Mainnet - const connection = this.connections.get(chainId) ?? new SolConnection(NETWORK_ENDPOINTS[chainId]) + private async _attachRecentBlockHash(transaction: Transaction, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + const connection = + this.connections.get(options.chainId) ?? new SolConnection(NETWORK_ENDPOINTS[options.chainId]) const blockHash = await connection.getRecentBlockhash() transaction.recentBlockhash = blockHash.blockhash return transaction } - async getWeb3(options?: SolanaWeb3ConnectionOptions) { - return this._getWeb3Provider(options).createWeb3({ - account: options?.account ?? this.account, - chainId: options?.chainId ?? this.chainId, - }) + async getWeb3(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return this._getWeb3Provider(options).createWeb3(options) } - getWeb3Provider(options?: SolanaWeb3ConnectionOptions) { - return this._getWeb3Provider(options).createWeb3Provider({ - account: options?.account ?? this.account, - chainId: options?.chainId ?? this.chainId, - }) + getWeb3Provider(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return this._getWeb3Provider(options).createWeb3Provider(options) } - async connect(options?: SolanaWeb3ConnectionOptions): Promise> { + async connect(initial?: SolanaWeb3ConnectionOptions): Promise> { + const options = this.getOptions(initial) return { account: '', chainId: ChainId.Mainnet, - ...(await Web3StateSettings.value.Provider?.connect( - options?.chainId ?? this.chainId, - options?.providerType ?? this.providerType, - )), + ...(await Web3StateSettings.value.Provider?.connect(options.chainId, options.providerType)), } } - async disconnect(options?: SolanaWeb3ConnectionOptions): Promise { - await Web3StateSettings.value.Provider?.disconnect(options?.providerType ?? this.providerType) + async disconnect(initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial) + await Web3StateSettings.value.Provider?.disconnect(options.providerType) } - private async transferSol(recipient: string, amount: string, options?: SolanaWeb3ConnectionOptions) { - if (!options?.account) throw new Error('No payer provides.') + private async transferSol(recipient: string, amount: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + if (!options.account) throw new Error('No payer provides.') const payerPubkey = new PublicKey(options.account) const recipientPubkey = new PublicKey(recipient) const transaction = new Transaction().add( @@ -97,11 +109,12 @@ class Connection implements BaseConnection { address: string, recipient: string, amount: string, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { - if (!options?.account) throw new Error('No payer provides.') - const chainId = options.chainId ?? ChainId.Mainnet - const connection = this.connections.get(chainId) ?? new SolConnection(NETWORK_ENDPOINTS[chainId]) + const options = this.getOptions(initial) + if (!options.account) throw new Error('No payer provides.') + const connection = + this.connections.get(options.chainId) ?? new SolConnection(NETWORK_ENDPOINTS[options.chainId]) const payerPubkey = new PublicKey(options.account) const recipientPubkey = new PublicKey(recipient) @@ -141,8 +154,9 @@ class Connection implements BaseConnection { recipient: string, amount: string, memo?: string, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { + const options = this.getOptions(initial) if (isNativeTokenAddress(address)) { return this.transferSol(recipient, amount, options) } @@ -154,63 +168,69 @@ class Connection implements BaseConnection { mintAddress: string, amount: string, schema?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { + const options = this.getOptions(initial) return this.transferSplToken(mintAddress, recipient, amount, options) } - getGasPrice(options?: SolanaWeb3ConnectionOptions): Promise { + getGasPrice(initial?: SolanaWeb3ConnectionOptions): Promise { throw new Error('Method not implemented.') } - getSchemaType(address: string, options?: SolanaWeb3ConnectionOptions): Promise { + getSchemaType(address: string, initial?: SolanaWeb3ConnectionOptions): Promise { throw new Error('Method not implemented.') } getNonFungibleTokenContract( address: string, schemaType?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } getNonFungibleTokenCollection( address: string, schemaType?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } - async switchChain(options?: SolanaWeb3ConnectionOptions) { - await Providers[options?.providerType ?? this.providerType].switchChain(options?.chainId) + async switchChain(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + await Providers[options.providerType].switchChain(options.chainId) } - getNativeToken(options?: SolanaWeb3ConnectionOptions): Promise> { - const token = createNativeToken(options?.chainId ?? ChainId.Mainnet) + getNativeToken(initial?: SolanaWeb3ConnectionOptions): Promise> { + const options = this.getOptions(initial) + const token = createNativeToken(options.chainId) return Promise.resolve(token) } - async getNativeTokenBalance(options?: SolanaWeb3ConnectionOptions): Promise { - if (!options?.account) return '0' + async getNativeTokenBalance(initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial) + if (!options.account) return '0' const connection = this.getWeb3Connection(options) const balance = await connection.getBalance(new PublicKey(options.account)) return balance.toString() } - async getFungibleTokenBalance(address: string, options?: SolanaWeb3ConnectionOptions): Promise { - if (!options?.account) return '0' + async getFungibleTokenBalance(address: string, initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial) + if (!options.account) return '0' if (isNativeTokenAddress(address)) { return this.getNativeTokenBalance(options) } - return SolanaRPC.getSplTokenBalance(options?.chainId ?? ChainId.Mainnet, options.account, address) + return SolanaRPC.getSplTokenBalance(options.chainId, options.account, address) } getNonFungibleTokenBalance( address: string, tokenId?: string, schemaType?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { throw new Error('Method not implemented.') } async getFungibleTokensBalance( listOfAddress: string[], - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { - if (!options?.chainId || !options.account) return {} + const options = this.getOptions(initial) + if (!options.account) return {} const splTokens = await SolanaRPC.getSplTokenList(options.chainId, options.account) const records = splTokens.reduce( (map: Record, asset) => ({ ...map, [asset.address]: asset.balance }), @@ -223,68 +243,81 @@ class Connection implements BaseConnection { } getNonFungibleTokensBalance( listOfAddress: string[], - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } - getCode(address: string, options?: SolanaWeb3ConnectionOptions): Promise { + getCode(address: string, initial?: SolanaWeb3ConnectionOptions): Promise { throw new Error('Method not implemented.') } - getWeb3Connection(options?: SolanaWeb3ConnectionOptions) { - const chainId = options?.chainId ?? this.chainId - const connection = this.connections.get(chainId) ?? new SolConnection(NETWORK_ENDPOINTS[chainId]) - this.connections.set(chainId, connection) + getWeb3Connection(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + const connection = + this.connections.get(options.chainId) ?? new SolConnection(NETWORK_ENDPOINTS[options.chainId]) + this.connections.set(options.chainId, connection) return connection } - getAccount(options?: SolanaWeb3ConnectionOptions) { - return Promise.resolve(options?.account ?? this.account) + getAccount(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return Promise.resolve(options.account) } - getAccountInfo(account: string, options?: SolanaWeb3ConnectionOptions) { + getAccountInfo(account: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial, { + account, + }) return this.getWeb3Connection(options).getAccountInfo(decodeAddress(account)) } - getChainId(options?: SolanaWeb3ConnectionOptions) { - return Promise.resolve(options?.chainId ?? this.chainId) + getChainId(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return Promise.resolve(options.chainId) } - async getBlock(no: number, options?: SolanaWeb3ConnectionOptions): Promise { + async getBlock(no: number, initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial) return this.getWeb3Connection(options).getBlock(no) } - async getBlockNumber(options?: SolanaWeb3ConnectionOptions) { + async getBlockNumber(initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) return this.getWeb3Connection(options).getSlot() } - async getBlockTimestamp(options?: SolanaWeb3ConnectionOptions): Promise { + async getBlockTimestamp(initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial) const slot = await this.getBlockNumber(options) const response = await this.getWeb3Connection(options).getBlockTime(slot) return response ?? 0 } - async getBalance(account: string, options?: SolanaWeb3ConnectionOptions) { + async getBalance(account: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) const balance = await this.getWeb3Connection(options).getBalance(decodeAddress(account)) return balance.toFixed() } - getTransaction(id: string, options?: SolanaWeb3ConnectionOptions) { + getTransaction(id: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) return this.getWeb3Connection(options).getTransaction(id) } - async getTransactionReceipt(id: string, options?: SolanaWeb3ConnectionOptions) { + async getTransactionReceipt(id: string, initial?: SolanaWeb3ConnectionOptions) { return null } - async getTransactionStatus(id: string, options?: SolanaWeb3ConnectionOptions) { + async getTransactionStatus(id: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) const response = await this.getWeb3Connection(options).getSignatureStatus(id) if (response.value?.err) return TransactionStatusType.FAILED if (response.value?.confirmations && response.value.confirmations > 0) return TransactionStatusType.SUCCEED return TransactionStatusType.NOT_DEPEND } - async signMessage(dataToSign: string, signType?: string, options?: SolanaWeb3ConnectionOptions) { + async signMessage(dataToSign: string, signType?: string, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) return this._getWeb3Provider(options).signMessage(dataToSign) } @@ -292,41 +325,50 @@ class Connection implements BaseConnection { dataToVerify: string, signature: string, signType?: string, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { + const options = this.getOptions(initial) return this._getWeb3Provider(options).verifyMessage(dataToVerify, signature) } - async signTransaction(transaction: Transaction, options?: SolanaWeb3ConnectionOptions) { + async signTransaction(transaction: Transaction, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) return this._getWeb3Provider(options).signTransaction(transaction) } - signTransactions(transactions: Transaction[], options?: SolanaWeb3ConnectionOptions) { - return Promise.all(transactions.map((x) => this.signTransaction(x))) + signTransactions(transactions: Transaction[], initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) + return Promise.all(transactions.map((x) => this.signTransaction(x, options))) } - callTransaction(transaction: Transaction, options?: SolanaWeb3ConnectionOptions): Promise { + callTransaction(transaction: Transaction, initial?: SolanaWeb3ConnectionOptions): Promise { throw new Error('Method not implemented.') } - async sendTransaction(transaction: Transaction, options?: SolanaWeb3ConnectionOptions) { + async sendTransaction(transaction: Transaction, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) const signedTransaction = await this.signTransaction(transaction) return sendAndConfirmRawTransaction(this.getWeb3Connection(options), signedTransaction.serialize()) } - sendSignedTransaction(signature: Transaction, options?: SolanaWeb3ConnectionOptions) { + sendSignedTransaction(signature: Transaction, initial?: SolanaWeb3ConnectionOptions) { + const options = this.getOptions(initial) return sendAndConfirmRawTransaction(this.getWeb3Connection(options), signature.serialize()) } - async getTransactionNonce(account: string, options?: SolanaWeb3ConnectionOptions): Promise { + async getTransactionNonce(account: string, initial?: SolanaWeb3ConnectionOptions): Promise { + const options = this.getOptions(initial, { + account, + }) const response = await this.getWeb3Connection(options).getNonce(decodeAddress(account)) return response?.nonce ? Number.parseInt(response.nonce, 10) : 0 } async getFungibleToken( address: string, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { + const options = this.getOptions(initial) if (!address || isNativeTokenAddress(address)) { return this.getNativeToken() } @@ -336,7 +378,7 @@ class Connection implements BaseConnection { token ?? ({ address, - chainId: options?.chainId, + chainId: options.chainId, } as FungibleToken) ) } @@ -344,12 +386,12 @@ class Connection implements BaseConnection { address: string, tokenId: string, schemaType?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { + const options = this.getOptions(initial) const asset = await MagicEden.getAsset(address, tokenId, options) - const chainId = options?.chainId ?? ChainId.Mainnet return createNonFungibleToken( - chainId, + options.chainId, address, SchemaType.NonFungible, tokenId, @@ -364,7 +406,7 @@ class Connection implements BaseConnection { owner: string, tokenId: string, schema?: SchemaType | undefined, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise { throw new Error('Method not implemented.') } @@ -372,7 +414,7 @@ class Connection implements BaseConnection { address: string, tokenId: string, schemaType?: SchemaType, - options?: SolanaWeb3ConnectionOptions, + initial?: SolanaWeb3ConnectionOptions, ): Promise> { throw new Error('Method not implemented.') } diff --git a/packages/plugins/Solana/src/state/Hub/hub.ts b/packages/plugins/Solana/src/state/Hub/hub.ts index 1352ebd06058..f4005e4ac5fe 100644 --- a/packages/plugins/Solana/src/state/Hub/hub.ts +++ b/packages/plugins/Solana/src/state/Hub/hub.ts @@ -1,3 +1,4 @@ +import type { PartialRequired } from '@masknet/shared-base' import { CoinGecko, MagicEden } from '@masknet/web3-providers' import { CurrencyType, @@ -23,91 +24,102 @@ class Hub implements SolanaHub { private account: string, private sourceType?: SourceType, private currencyType?: CurrencyType, - private sizePerPage = 50, - private maxPageSize = 25, ) {} + private getOptions( + initial?: HubOptions, + overrides?: Partial>, + ): PartialRequired, 'chainId' | 'account'> { + return { + chainId: this.chainId, + account: this.account, + sourceType: this.sourceType, + currencyType: this.currencyType, + ...initial, + ...overrides, + } + } + async getFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { return SolanaRPC.getAllSplTokens() } async getNonFungibleTokensFromTokenList( chainId: ChainId, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { throw new Error('Method not implemented.') } - getGasOptions( - chainId: ChainId, - options?: HubOptions | undefined, - ): Promise> { + getGasOptions(chainId: ChainId, initial?: HubOptions): Promise> { throw new Error('Method not implemented.') } - getFungibleAsset( - address: string, - options?: HubOptions | undefined, - ): Promise> { + getFungibleAsset(address: string, initial?: HubOptions): Promise> { throw new Error('Method not implemented.') } async getNonFungibleAsset( address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise | undefined> { + const options = this.getOptions(initial) return MagicEden.getAsset(address, tokenId, options) } async getFungibleAssets( account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { - return SolanaRPC.getFungibleAssets(account, options) + const options = this.getOptions(initial, { + account, + }) + return SolanaRPC.getFungibleAssets(options.account, options) } getNonFungibleTokens( account: string, - options?: HubOptions, + initial?: HubOptions, ): Promise>> { + const options = this.getOptions(initial, { + account, + }) try { - return MagicEden.getTokens(account, options) + return MagicEden.getTokens(options.account, options) } catch { - return SolanaRPC.getNonFungibleAssets(account, options) + return SolanaRPC.getNonFungibleAssets(options.account, options) } } getNonFungibleCollections( account: string, - options?: HubOptions, + initial?: HubOptions, ): Promise>> { - return MagicEden.getCollections(account, options) + const options = this.getOptions(initial, { + account, + }) + return MagicEden.getCollections(options.account, options) } - getFungibleTokenPrice( - chainId: ChainId, - address: string, - options?: HubOptions | undefined, - ): Promise { - const expectedChainId = options?.chainId ?? chainId - const expectedCurrencyType = options?.currencyType ?? this.currencyType - const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(expectedChainId) - const { SOL_ADDRESS } = getTokenConstants(expectedChainId) + getFungibleTokenPrice(chainId: ChainId, address: string, initial?: HubOptions): Promise { + const options = this.getOptions(initial) + const { PLATFORM_ID = '', COIN_ID = '' } = getCoinGeckoConstants(options.chainId) + const { SOL_ADDRESS } = getTokenConstants(options.chainId) if (isSameAddress(address, SOL_ADDRESS)) { - return CoinGecko.getTokenPriceByCoinId(COIN_ID, expectedCurrencyType) + return CoinGecko.getTokenPriceByCoinId(COIN_ID, options.currencyType) } - return CoinGecko.getTokenPrice(PLATFORM_ID, address, expectedCurrencyType) + return CoinGecko.getTokenPrice(PLATFORM_ID, address, options.currencyType) } getNonFungibleTokenPrice( chainId: ChainId, address: string, tokenId: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } async getFungibleTokenIconURLs( chainId: ChainId, address: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { return [] } @@ -115,14 +127,14 @@ class Hub implements SolanaHub { chainId: ChainId, address: string, tokenId?: string | undefined, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise { throw new Error('Method not implemented.') } getTransactions( chainId: ChainId, account: string, - options?: HubOptions | undefined, + initial?: HubOptions, ): Promise>> { throw new Error('Method not implemented.') } @@ -133,8 +145,6 @@ export function createHub( account = '', sourceType?: SourceType, currencyType?: CurrencyType, - sizePerPage?: number, - maxPageSize?: number, ) { - return new Hub(chainId, account, sourceType, currencyType, sizePerPage, maxPageSize) + return new Hub(chainId, account, sourceType, currencyType) } diff --git a/packages/shared-base/src/utils/index.ts b/packages/shared-base/src/utils/index.ts index f57bc7384a2a..ae4622c11e19 100644 --- a/packages/shared-base/src/utils/index.ts +++ b/packages/shared-base/src/utils/index.ts @@ -8,7 +8,10 @@ export * from './subscription' export * from './getAssetAsBlobURL' export * from './personas' export * from './createValueRefWithReady' + export enum MimeTypes { JSON = 'application/json', Binary = 'application/octet-stream', } + +export type PartialRequired = Omit & Pick, RequiredKeys> diff --git a/packages/web3-shared/base/src/specs/index.ts b/packages/web3-shared/base/src/specs/index.ts index 0b21d7e84fe1..cb265e957d13 100644 --- a/packages/web3-shared/base/src/specs/index.ts +++ b/packages/web3-shared/base/src/specs/index.ts @@ -586,94 +586,94 @@ export interface Connection< Web3ConnectionOptions = ConnectionOptions, > { /** Get web3 instance */ - getWeb3(options?: Web3ConnectionOptions): Promise + getWeb3(initial?: Web3ConnectionOptions): Promise /** Get web3 provider instance */ - getWeb3Provider(options?: Web3ConnectionOptions): Promise + getWeb3Provider(initial?: Web3ConnectionOptions): Promise /** Get gas price */ - getGasPrice(options?: Web3ConnectionOptions): Promise + getGasPrice(initial?: Web3ConnectionOptions): Promise /** Get schema type of given token address. */ - getSchemaType(address: string, options?: Web3ConnectionOptions): Promise + getSchemaType(address: string, initial?: Web3ConnectionOptions): Promise /** Get a native fungible token. */ - getNativeToken(options?: Web3ConnectionOptions): Promise> + getNativeToken(initial?: Web3ConnectionOptions): Promise> /** Get a fungible token. */ - getFungibleToken(address: string, options?: Web3ConnectionOptions): Promise> + getFungibleToken(address: string, initial?: Web3ConnectionOptions): Promise> /** Get an non-fungible token. */ getNonFungibleToken( address: string, tokenId: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise> getNonFungibleTokenOwnership( address: string, owner: string, tokenId: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise getNonFungibleTokenMetadata( address: string, tokenId: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise> /** Get an non-fungible token contract. */ getNonFungibleTokenContract( address: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise> /** Get an non-fungible token collection. */ getNonFungibleTokenCollection( address: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise> /** Get native fungible token balance. */ - getNativeTokenBalance(options?: Web3ConnectionOptions): Promise + getNativeTokenBalance(initial?: Web3ConnectionOptions): Promise /** Get fungible token balance */ - getFungibleTokenBalance(address: string, options?: Web3ConnectionOptions): Promise + getFungibleTokenBalance(address: string, initial?: Web3ConnectionOptions): Promise /** Get non-fungible token balance */ - getNonFungibleTokenBalance(address: string, tokenId?: string, schema?: SchemaType, options?: Web3ConnectionOptions): Promise + getNonFungibleTokenBalance(address: string, tokenId?: string, schema?: SchemaType, initial?: Web3ConnectionOptions): Promise /** Get fungible token balance */ - getFungibleTokensBalance(listOfAddress: string[], options?: Web3ConnectionOptions): Promise> + getFungibleTokensBalance(listOfAddress: string[], initial?: Web3ConnectionOptions): Promise> /** Get non-fungible token balance */ getNonFungibleTokensBalance( listOfAddress: string[], - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise> /** Get the currently connected account. */ - getAccount(options?: Web3ConnectionOptions): Promise + getAccount(initial?: Web3ConnectionOptions): Promise /** Get the currently chain id. */ - getChainId(options?: Web3ConnectionOptions): Promise + getChainId(initial?: Web3ConnectionOptions): Promise /** Get the latest block by number. */ - getBlock(no: number, options?: Web3ConnectionOptions): Promise + getBlock(no: number, initial?: Web3ConnectionOptions): Promise /** Get the latest block number. */ - getBlockNumber(options?: Web3ConnectionOptions): Promise + getBlockNumber(initial?: Web3ConnectionOptions): Promise /** Get the latest block unix timestamp. */ - getBlockTimestamp(options?: Web3ConnectionOptions): Promise + getBlockTimestamp(initial?: Web3ConnectionOptions): Promise /** Get the latest balance of the account. */ - getBalance(address: string, options?: Web3ConnectionOptions): Promise + getBalance(address: string, initial?: Web3ConnectionOptions): Promise /** Get the detailed of transaction by id. */ - getTransaction(id: string, options?: Web3ConnectionOptions): Promise + getTransaction(id: string, initial?: Web3ConnectionOptions): Promise /** Get the latest transaction status. */ - getTransactionStatus(id: string, options?: Web3ConnectionOptions): Promise + getTransactionStatus(id: string, initial?: Web3ConnectionOptions): Promise /** Get the latest transaction nonce. */ - getTransactionNonce(address: string, options?: Web3ConnectionOptions): Promise + getTransactionNonce(address: string, initial?: Web3ConnectionOptions): Promise /** Get the transaction receipt. */ - getTransactionReceipt(id: string, options?: Web3ConnectionOptions): Promise + getTransactionReceipt(id: string, initial?: Web3ConnectionOptions): Promise /** Get the source code of a on-chain program. */ - getCode(address: string, options?: Web3ConnectionOptions): Promise + getCode(address: string, initial?: Web3ConnectionOptions): Promise /** Switch to sub network */ - switchChain?: (options?: Web3ConnectionOptions) => Promise + switchChain?: (initial?: Web3ConnectionOptions) => Promise /** Sign message */ - signMessage(dataToSign: string, signType?: string, options?: Web3ConnectionOptions): Promise + signMessage(dataToSign: string, signType?: string, initial?: Web3ConnectionOptions): Promise /** Verify message */ verifyMessage( dataToVerify: string, signature: Signature, signType?: string, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise /** Transfer fungible token to */ transferFungibleToken( @@ -681,7 +681,7 @@ export interface Connection< recipient: string, amount: string, memo?: string, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise /** Transfer non-fungible token to */ transferNonFungibleToken( @@ -690,26 +690,26 @@ export interface Connection< tokenId: string, amount: string, schema?: SchemaType, - options?: Web3ConnectionOptions, + initial?: Web3ConnectionOptions, ): Promise /** Sign a transaction */ - signTransaction(transaction: Transaction, options?: Web3ConnectionOptions): Promise + signTransaction(transaction: Transaction, initial?: Web3ConnectionOptions): Promise /** Sign multiple transactions */ - signTransactions(transactions: Transaction[], options?: Web3ConnectionOptions): Promise + signTransactions(transactions: Transaction[], initial?: Web3ConnectionOptions): Promise /** Query a transaction */ - callTransaction(transaction: Transaction, options?: Web3ConnectionOptions): Promise + callTransaction(transaction: Transaction, initial?: Web3ConnectionOptions): Promise /** Send a transaction and wait for mining */ - sendTransaction(transaction: Transaction, options?: Web3ConnectionOptions): Promise + sendTransaction(transaction: Transaction, initial?: Web3ConnectionOptions): Promise /** Send a signed transaction */ - sendSignedTransaction(signature: TransactionSignature, options?: Web3ConnectionOptions): Promise + sendSignedTransaction(signature: TransactionSignature, initial?: Web3ConnectionOptions): Promise /** Build connection */ - connect(options?: Web3ConnectionOptions): Promise> + connect(initial?: Web3ConnectionOptions): Promise> /** Break connection */ - disconnect(options?: Web3ConnectionOptions): Promise + disconnect(initial?: Web3ConnectionOptions): Promise /** Replace request */ - replaceRequest(hash: string, config: Transaction, options?: Web3ConnectionOptions): Promise + replaceRequest(hash: string, config: Transaction, initial?: Web3ConnectionOptions): Promise /** Cancel request */ - cancelRequest(hash: string, config: Transaction, options?: Web3ConnectionOptions): Promise + cancelRequest(hash: string, config: Transaction, initial?: Web3ConnectionOptions): Promise } export interface HubIndicator { @@ -740,74 +740,74 @@ export interface Hub Promise>> /** Get the non-fungible from built-in token list */ getNonFungibleTokensFromTokenList?: ( chainId: ChainId, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise>> /** Get all gas options */ - getGasOptions?: (chainId: ChainId, options?: Web3HubOptions) => Promise> + getGasOptions?: (chainId: ChainId, initial?: Web3HubOptions) => Promise> /** Get a fungible asset */ getFungibleAsset?: ( address: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise | undefined> /** Get an non-fungible asset */ getNonFungibleAsset?: ( address: string, tokenId: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise | undefined> /** Get fungible assets of given account with pagination supported. */ getFungibleAssets?: ( account: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise>> /** Get non-fungible assets of given account with pagination supported. */ getNonFungibleAssets?: ( account: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise>> /** Get fungible tokens of given account with pagination supported. */ getFungibleTokens?: ( account: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise | Error>> /** Get non-fungible tokens of given account with pagination supported. */ getNonFungibleTokens?: ( account: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise>> /** Get price of a fungible token */ - getFungibleTokenPrice?: (chainId: ChainId, address: string, options?: Web3HubOptions) => Promise + getFungibleTokenPrice?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise /** Get price of an non-fungible token */ getNonFungibleTokenPrice?: ( chainId: ChainId, address: string, tokenId: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise /** Get token icon urls of a fungible token */ - getFungibleTokenIconURLs?: (chainId: ChainId, address: string, options?: Web3HubOptions) => Promise + getFungibleTokenIconURLs?: (chainId: ChainId, address: string, initial?: Web3HubOptions) => Promise /** Get token icon urls of an non-fungible token */ getNonFungibleTokenIconURLs?: ( chainId: ChainId, address: string, tokenId?: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise /** Get non-fungible collections of given account with pagination supported */ getNonFungibleCollections?: ( account: string, - options?: Web3HubOptions + initial?: Web3HubOptions ) => Promise>> /** Get the most recent transactions */ getTransactions: ( chainId: ChainId, account: string, - options?: Web3HubOptions, + initial?: Web3HubOptions, ) => Promise>> } @@ -985,11 +985,11 @@ export interface ConnectionState< >, > { /** Get web3 SDK */ - getWeb3?: (options?: Web3ConnectionOptions) => Promise + getWeb3?: (initial?: Web3ConnectionOptions) => Promise /** Get web3 provider instance */ - getWeb3Provider?: (options?: Web3ConnectionOptions) => Promise + getWeb3Provider?: (initial?: Web3ConnectionOptions) => Promise /** Get connection */ - getConnection?: (options?: Web3ConnectionOptions) => Promise + getConnection?: (initial?: Web3ConnectionOptions) => Promise } export interface WalletState { /** The currently stored wallet by MaskWallet. */ diff --git a/packages/web3-shared/evm/utils/contract.ts b/packages/web3-shared/evm/utils/contract.ts index 2b52ee150843..ef8c78398685 100644 --- a/packages/web3-shared/evm/utils/contract.ts +++ b/packages/web3-shared/evm/utils/contract.ts @@ -6,27 +6,23 @@ import type { PayableTransactionObject, PayableTx, } from '@masknet/web3-contracts/types/types' -import type { SendOptions } from 'web3-eth-contract' import type { Transaction } from '../types' import { isValidAddress } from './address' export async function encodeTransaction( contract: BaseContract, transaction: PayableTransactionObject | NonPayableTransactionObject, - options?: SendOptions & { - maxPriorityFeePerGas?: string - maxFeePerGas?: string - }, + overrides?: Partial, ) { const encoded: Transaction = { from: contract.defaultAccount ?? undefined, to: contract.options.address, data: transaction.encodeABI(), - ...options, + ...overrides, } if (!encoded.gas) { - encoded.gas = await transaction.estimateGas(options) + encoded.gas = await transaction.estimateGas(overrides as PayableTx) } return encoded @@ -38,11 +34,8 @@ export async function sendTransaction( overrides?: Partial, ) { if (!contract || !transaction) throw new Error('Invalid contract or transaction.') - const tx = await encodeTransaction(contract, transaction) - const receipt = await transaction.send({ - ...tx, - ...overrides, - } as PayableTx) + const tx = await encodeTransaction(contract, transaction, overrides) + const receipt = await transaction.send(tx as PayableTx) return receipt?.transactionHash ?? '' }