Skip to content

Commit

Permalink
refactor: code style
Browse files Browse the repository at this point in the history
  • Loading branch information
guanbinrui committed Dec 23, 2022
1 parent 9f3f30c commit 8b7809d
Show file tree
Hide file tree
Showing 24 changed files with 439 additions and 374 deletions.
Expand Up @@ -7,6 +7,32 @@ import { TrendingPopper } from './TrendingPopper.js'
import { TrendingView } from './TrendingView.js'
import { TrendingViewProvider } from './context.js'

interface TrendingViewWrapperProps {
resultList: Web3Helper.TokenResultAll[]
address?: string
isNFTProjectPopper?: boolean
reposition?: () => void
}

function TrendingViewWrapper({ resultList, reposition, address, isNFTProjectPopper }: TrendingViewWrapperProps) {
const [result, setResult] = useState(resultList[0])
return (
<TrendingViewProvider
isNFTProjectPopper={Boolean(isNFTProjectPopper)}
isProfilePage={false}
isTokenTagPopper={!isNFTProjectPopper}
isPreciseSearch={false}>
<TrendingView
setResult={setResult}
result={result}
resultList={resultList}
onUpdate={reposition}
address={address}
/>
</TrendingViewProvider>
)
}

export interface TagInspectorProps {}

export function TagInspector(props: TagInspectorProps) {
Expand Down Expand Up @@ -34,29 +60,3 @@ export function TagInspector(props: TagInspectorProps) {
</Web3ContextProvider>
)
}

interface TrendingViewWrapperProps {
resultList: Web3Helper.TokenResultAll[]
address?: string
isNFTProjectPopper?: boolean
reposition?: () => void
}

function TrendingViewWrapper({ resultList, reposition, address, isNFTProjectPopper }: TrendingViewWrapperProps) {
const [result, setResult] = useState(resultList[0])
return (
<TrendingViewProvider
isNFTProjectPopper={Boolean(isNFTProjectPopper)}
isProfilePage={false}
isTokenTagPopper={!isNFTProjectPopper}
isPreciseSearch={false}>
<TrendingView
setResult={setResult}
result={result}
resultList={resultList}
onUpdate={reposition}
address={address}
/>
</TrendingViewProvider>
)
}
@@ -1,20 +1,9 @@
import { first } from 'lodash-es'
import type { AbiItem } from 'web3-utils'
import type { BundlerAPI, ContractAccountAPI } from '@masknet/web3-providers/types'
import type { BundlerAPI, AbstractAccountAPI } from '@masknet/web3-providers/types'
import type { NetworkPluginID } from '@masknet/shared-base'
import {
ChainId,
createContract,
EthereumMethodType,
isValidAddress,
ProviderType,
UserTransaction,
ContractWallet as ContractWalletLib,
ContractTransaction,
isEmptyHex,
} from '@masknet/web3-shared-evm'
import { createContract, EthereumMethodType, isValidAddress, ProviderType } from '@masknet/web3-shared-evm'
import { Web3 } from '@masknet/web3-providers'
import { isSameAddress } from '@masknet/web3-shared-base'
import WalletABI from '@masknet/web3-contracts/abis/Wallet.json'
import type { Wallet as WalletContract } from '@masknet/web3-contracts/types/Wallet.js'
import type { Middleware, Context } from '../types.js'
Expand All @@ -25,54 +14,28 @@ import { SharedContextSettings } from '../../../settings/index.js'
export class ContractWallet implements Middleware<Context> {
constructor(
protected providerType: ProviderType,
protected contractAccount: ContractAccountAPI.Provider<NetworkPluginID.PLUGIN_EVM>,
protected account: AbstractAccountAPI.Provider<NetworkPluginID.PLUGIN_EVM>,
protected bundler: BundlerAPI.Provider,
protected options: {
getLogicContractAddress(chainId: ChainId): string
},
) {}

private createProvider(context: Context) {
return Providers[context.providerType] as BaseContractWalletProvider | undefined
}

private createWallet(context: Context) {
const web3 = Web3.createWeb3(context.chainId)
const contract = createContract<WalletContract>(web3, context.account, WalletABI as AbiItem[])
if (!contract) throw new Error('Failed to create wallet contract.')
return contract
}

private async getEntryPoint(chainId: ChainId) {
const entryPoints = await this.bundler.getSupportedEntryPoints(chainId)
const entryPoint = first(entryPoints)
if (!entryPoint || !isValidAddress(entryPoint)) throw new Error(`Not supported ${chainId}`)
return entryPoint
}

private async getInitCode(chainId: ChainId, owner: string) {
const contractWallet = new ContractWalletLib(
chainId,
owner,
this.options.getLogicContractAddress(chainId),
await this.getEntryPoint(chainId),
)
if (isEmptyHex(contractWallet.initCode)) throw new Error('Failed to create initCode.')
return contractWallet.initCode
}

private async getDeployedAccounts(chainId: ChainId, owner: string) {
const accounts = await this.contractAccount.getAccountsByOwner(chainId, owner)
return accounts.filter((x) => isSameAddress(x.creator, owner))
private getProvider(context: Context) {
return Providers[context.providerType] as BaseContractWalletProvider | undefined
}

private async getNonce(context: Context) {
const walletContract = this.createWallet(context)
return walletContract.methods.nonce()
return walletContract.methods.nonce().call()
}

private getOwner(context: Context) {
const provider = this.createProvider(context)
const provider = this.getProvider(context)
if (!provider) throw new Error('Invalid provider')

return {
Expand All @@ -81,33 +44,11 @@ export class ContractWallet implements Middleware<Context> {
}
}

private async sendUserOperation(context: Context, op = context.userOperation): Promise<string> {
private getSigner(context: Context) {
const { owner, identifier } = this.getOwner(context)
if (!owner) throw new Error('Failed to sign user operation.')

const { config } = context
if (!op && !config) throw new Error('No user operation to be sent.')

// setup user operation
const entryPoint = await this.getEntryPoint(context.chainId)
const userTransaction =
(op ? await UserTransaction.fromUserOperation(context.chainId, entryPoint, op) : undefined) ||
(config ? await UserTransaction.fromTransaction(context.chainId, entryPoint, config) : undefined)
if (!userTransaction) throw new Error('Failed to create user transaction.')

// fill in initCode
if (isEmptyHex(userTransaction.initCode) && userTransaction.nonce === 0) {
const initCode = await this.getInitCode(context.chainId, owner)
const accounts = await this.getDeployedAccounts(context.chainId, owner)

await userTransaction.fill({
initCode,
nonce: accounts.filter((x) => x.deployed).length,
})
}

// sign user operation
await userTransaction.sign(async (message: string) => {
return async (message: string) => {
if (identifier) {
return SharedContextSettings.value.personaSignPayMessage({
message,
Expand All @@ -118,33 +59,41 @@ export class ContractWallet implements Middleware<Context> {
account: owner,
providerType: this.providerType,
})
})
return this.bundler.sendUserOperation(context.chainId, userTransaction.toUserOperation())
}
}

private async changeOwner(context: Context) {
const recipient = first<string>(context.requestArguments.params)
if (!recipient) throw new Error('No recipient address.')

return new ContractTransaction(this.createWallet(context)).send((x) => x.methods.changeOwner(recipient))
private async sendUserOperation(context: Context, op = context.userOperation): Promise<string> {
if (op)
return this.account.sendUserOperation(
context.chainId,
this.getOwner(context).owner,
op,
this.getSigner(context),
)
if (context.config)
return this.account.sendTransaction(
context.chainId,
this.getOwner(context).owner,
context.config,
this.getSigner(context),
)

throw new Error('No user operation to be sent.')
}

private async deploy(context: Context) {
const { owner } = this.getOwner(context)
if (!isValidAddress(owner)) throw new Error('Invalid owner address.')
return this.account.deploy(context.chainId, this.getOwner(context).owner, this.getSigner(context))
}

const initCode = await this.getInitCode(context.chainId, owner)
const accounts = await this.getDeployedAccounts(context.chainId, owner)
private async changeOwner(context: Context) {
const recipient = first<string>(context.requestArguments.params)
if (!recipient) throw new Error('No recipient address.')

return this.sendUserOperation(context, {
sender: context.account,
nonce: accounts.filter((x) => x.deployed).length,
initCode,
})
return this.account.transfer(context.chainId, this.getOwner(context).owner, recipient, this.getSigner(context))
}

async fn(context: Context, next: () => Promise<void>) {
const provider = this.createProvider(context)
const provider = this.getProvider(context)

// not a SC wallet provider
if (!provider?.owner) {
Expand Down
@@ -1,4 +1,4 @@
import { ChainId, getSmartPayConstants, ProviderType } from '@masknet/web3-shared-evm'
import { ProviderType } from '@masknet/web3-shared-evm'
import { SmartPayAccount, SmartPayBundler } from '@masknet/web3-providers'
import type { Context, Middleware } from '../types.js'
import { NoneWallet } from '../interceptors/None.js'
Expand All @@ -14,11 +14,7 @@ export class Interceptor implements Middleware<Context> {
[ProviderType.None]: [new NoneWallet()],
[ProviderType.MaskWallet]: [
new Popups(),
new ContractWallet(ProviderType.MaskWallet, SmartPayAccount, SmartPayBundler, {
getLogicContractAddress(chainId: ChainId) {
return getSmartPayConstants(chainId).LOGIC_WALLET_CONTRACT_ADDRESS ?? ''
},
}),
new ContractWallet(ProviderType.MaskWallet, SmartPayAccount, SmartPayBundler),
new MaskWallet(),
],
[ProviderType.MetaMask]: [new MetaMask()],
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/SmartPay/src/hooks/useDeploy.ts
Expand Up @@ -8,13 +8,13 @@ import {
import { NetworkPluginID } from '@masknet/shared-base'
import { useWeb3Connection, useWeb3State } from '@masknet/web3-hooks-base'
import { SmartPayFunder } from '@masknet/web3-providers'
import type { ContractAccountAPI } from '@masknet/web3-providers/types'
import type { AbstractAccountAPI } from '@masknet/web3-providers/types'
import { ProviderType, ChainId } from '@masknet/web3-shared-evm'
import { SignAccount, SignAccountType } from '../type.js'

export function useDeploy(
signAccount?: SignAccount,
contractAccount?: ContractAccountAPI.ContractAccount<NetworkPluginID.PLUGIN_EVM>,
contractAccount?: AbstractAccountAPI.AbstractAccount<NetworkPluginID.PLUGIN_EVM>,
nonce?: number,
onSuccess?: () => void,
) {
Expand Down
3 changes: 3 additions & 0 deletions packages/web3-helpers/src/index.ts
Expand Up @@ -44,6 +44,7 @@ export declare namespace Web3Helper {
TransactionDetailed: EVM.TransactionDetailed
TransactionSignature: EVM.TransactionSignature
TransactionParameter: EVM.TransactionParameter
UserOperation: EVM.UserOperation
Web3Provider: EVM.Web3Provider
Web3: EVM.Web3
}
Expand All @@ -62,6 +63,7 @@ export declare namespace Web3Helper {
TransactionDetailed: Flow.TransactionDetailed
TransactionSignature: Flow.TransactionSignature
TransactionParameter: Flow.TransactionParameter
UserOperation: Flow.Operation
Web3Provider: Flow.Web3Provider
Web3: Flow.Web3
}
Expand All @@ -80,6 +82,7 @@ export declare namespace Web3Helper {
TransactionDetailed: Solana.TransactionDetailed
TransactionSignature: Solana.TransactionSignature
TransactionParameter: Solana.TransactionParameter
UserOperation: Solana.Operation
Web3Provider: Solana.Web3Provider
Web3: Solana.Web3
}
Expand Down
38 changes: 38 additions & 0 deletions packages/web3-providers/src/EVM/apis/Web3API.ts
@@ -0,0 +1,38 @@
import { first, memoize } from 'lodash-es'
import Web3SDK from 'web3'
import type { HttpProvider } from 'web3-core'
import {
AddressType,
ChainId,
createWeb3Provider,
createWeb3Request,
getRPCConstants,
isValidAddress,
Web3Provider,
} from '@masknet/web3-shared-evm'
import type { Web3BaseAPI } from '../../entry-types.js'

const createWeb3SDK = memoize(
(url: string) => new Web3SDK(url),
(url) => url.toLowerCase(),
)

export class Web3API implements Web3BaseAPI.Provider<ChainId, AddressType, Web3Provider, Web3SDK> {
async getAddressType(chainId: ChainId, address: string): Promise<AddressType | undefined> {
if (!isValidAddress(address)) return
const code = await this.createWeb3(chainId).eth.getCode(address)
return code === '0x' ? AddressType.ExternalOwned : AddressType.Contract
}

createWeb3(chainId: ChainId) {
const RPC_URL = first(getRPCConstants(chainId).RPC_URLS)
if (!RPC_URL) throw new Error('Failed to create web3 provider.')
return createWeb3SDK(RPC_URL)
}

createProvider(chainId: ChainId) {
const web3 = this.createWeb3(chainId)
const provider = web3.currentProvider as HttpProvider
return createWeb3Provider(createWeb3Request(provider.send))
}
}

0 comments on commit 8b7809d

Please sign in to comment.