From b68f9c5ed0fd6098f12382f9d1762d26fd829739 Mon Sep 17 00:00:00 2001 From: lukachi Date: Sat, 2 Mar 2024 15:40:23 +0200 Subject: [PATCH 1/4] remove private properties --- packages/tools/src/event-emitter.ts | 14 +- packages/w3p/src/provider-detector.ts | 52 +++-- packages/w3p/src/provider.ts | 70 +++--- .../w3p/src/providers/wrapped/_base-evm.ts | 70 +++--- .../w3p/src/providers/wrapped/_base-solana.ts | 70 +++--- .../w3p/src/providers/wrapped/_event-bus.ts | 26 +-- .../providers/wrapped/evm-wallet-connect.ts | 202 +++++++++--------- .../w3p/src/providers/wrapped/fallback-evm.ts | 38 ++-- packages/w3p/src/providers/wrapped/near.ts | 64 +++--- 9 files changed, 268 insertions(+), 338 deletions(-) diff --git a/packages/tools/src/event-emitter.ts b/packages/tools/src/event-emitter.ts index 51f89fd9..2d7b59f0 100644 --- a/packages/tools/src/event-emitter.ts +++ b/packages/tools/src/event-emitter.ts @@ -6,14 +6,10 @@ import type { } from '@/types' export class EventEmitter { - #handlers: EventHandlersMap = {} - - get handlers(): EventHandlersMap { - return this.#handlers - } + handlers: EventHandlersMap = {} public on>(key: K, fn: EventHandler): void { - this.#handlers[key] = (this.#handlers[key] || [])?.concat(fn) + this.handlers[key] = (this.handlers[key] || [])?.concat(fn) } public once>(key: K, fn: EventHandler): void { @@ -25,16 +21,16 @@ export class EventEmitter { } public off>(key: K, fn: EventHandler): void { - this.#handlers[key] = (this.#handlers[key] || [])?.filter(f => f !== fn) + this.handlers[key] = (this.handlers[key] || [])?.filter(f => f !== fn) } public emit>(key: K, data?: T[K]): void | never { - ;(this.#handlers[key] || [])?.forEach((fn: EventHandler) => { + ;(this.handlers[key] || [])?.forEach((fn: EventHandler) => { fn(data) }) } public clear(): void { - this.#handlers = {} + this.handlers = {} } } diff --git a/packages/w3p/src/provider-detector.ts b/packages/w3p/src/provider-detector.ts index e2a14964..1aadddcd 100644 --- a/packages/w3p/src/provider-detector.ts +++ b/packages/w3p/src/provider-detector.ts @@ -28,16 +28,16 @@ type ProviderDetectorConfig = { } export class ProviderDetector> { - #providers: ProviderInstance[] - #rawProviders: RawProvider[] - #isInitiated = false + pureProviders: ProviderInstance[] + rawProviders: RawProvider[] + isInitiated = false public static errorHandlers?: ErrorHandlersMap public static cfg: ProviderDetectorConfig constructor() { - this.#providers = [] - this.#rawProviders = [] + this.pureProviders = [] + this.rawProviders = [] ProviderDetector.setCfg({ isWrapDefaultProviders: true, @@ -56,18 +56,14 @@ export class ProviderDetector> { } public async init(): Promise> { - this.#detectRawProviders() - await this.#defineProviders() - this.#isInitiated = true + this.detectRawProviders() + await this.defineProviders() + this.isInitiated = true return this } - get isInitiated(): boolean { - return this.#isInitiated - } - public get providers(): Record { - return this.#providers.reduce((acc, el) => { + return this.pureProviders.reduce((acc, el) => { const name = el.name.toLowerCase() as PROVIDERS acc[name] = { @@ -79,7 +75,7 @@ export class ProviderDetector> { } public get isEnabled(): boolean { - return Boolean(this.#providers.length) + return Boolean(this.pureProviders.length) } public getProvider(provider: PROVIDERS | T): ProviderInstance | undefined { @@ -87,10 +83,10 @@ export class ProviderDetector> { } public addProvider(provider: ProviderInstance): void { - this.#providers.push(provider) + this.pureProviders.push(provider) } - #detectRawProviders(): void { + detectRawProviders(): void { const ethProviders = window?.ethereum ? window?.ethereum?.providers || [window?.ethereum] : [] @@ -104,7 +100,7 @@ export class ProviderDetector> { ), ) - this.#rawProviders = [ + this.rawProviders = [ ...(ProviderDetector.cfg?.isWrapDefaultProviders && proxyEthProviders ? proxyEthProviders : ethProviders), @@ -113,22 +109,22 @@ export class ProviderDetector> { ] as RawProvider[] } - async #defineProviders(): Promise { - if (this.#rawProviders.length) { - this.#designateProviders() + async defineProviders(): Promise { + if (this.rawProviders.length) { + this.designateProviders() } else { await sleep(3000) - await this.#detectRawProviders() - this.#designateProviders() + await this.detectRawProviders() + this.designateProviders() } } - #designateProviders(): void { - if (!this.#rawProviders.length) return + designateProviders(): void { + if (!this.rawProviders.length) return - const browserProviders = this.#rawProviders.map(el => { + const browserProviders = this.rawProviders.map(el => { const appropriatedProviderName: PROVIDERS = - this.#getAppropriateProviderName(el) + this.getAppropriateProviderName(el) return { name: appropriatedProviderName, @@ -136,12 +132,12 @@ export class ProviderDetector> { } as ProviderInstance }) - this.#providers = browserProviders.filter( + this.pureProviders = browserProviders.filter( (el, idx, arr) => arr.findIndex(sec => sec.name === el.name) === idx, ) } - #getAppropriateProviderName(provider: RawProvider): PROVIDERS { + getAppropriateProviderName(provider: RawProvider): PROVIDERS { const providerName = Object.entries(PROVIDER_CHECKS).find(el => { const [, value] = el diff --git a/packages/w3p/src/provider.ts b/packages/w3p/src/provider.ts index ec284385..d85dcbe9 100644 --- a/packages/w3p/src/provider.ts +++ b/packages/w3p/src/provider.ts @@ -39,28 +39,28 @@ export type CreateProviderOpts> = { * ``` */ export class Provider implements IProvider { - readonly #proxyConstructor: ProviderProxyConstructor - #selectedProvider?: PROVIDERS - #proxy?: ProviderProxy + readonly proxyConstructor: ProviderProxyConstructor + selectedProvider?: PROVIDERS + proxy?: ProviderProxy public static chainsDetails?: Record constructor(proxyConstructor: ProviderProxyConstructor) { - this.#selectedProvider = undefined - this.#proxy = undefined - this.#proxyConstructor = proxyConstructor + this.selectedProvider = undefined + this.proxy = undefined + this.proxyConstructor = proxyConstructor } public get rawProvider() { - return this.#proxy?.rawProvider + return this.proxy?.rawProvider } public get chainType() { - return this.#proxy?.chainType + return this.proxy?.chainType } public get providerType() { - return this.#selectedProvider + return this.selectedProvider } public get isConnected() { @@ -68,11 +68,11 @@ export class Provider implements IProvider { } public get address() { - return this.#proxy?.address + return this.proxy?.address } public get chainId() { - return this.#proxy?.chainId + return this.proxy?.chainId } public get chainDetails() { @@ -83,31 +83,31 @@ export class Provider implements IProvider { if (!provider.instance) throw new errors.ProviderInjectedInstanceNotFoundError() - this.#proxy = new this.#proxyConstructor(provider.instance) + this.proxy = new this.proxyConstructor(provider.instance) Object.entries(listeners || {}).forEach(([key, value]) => { - this.#proxy?.[key as keyof ProviderListeners]?.( + this.proxy?.[key as keyof ProviderListeners]?.( value as (e?: ProviderEventPayload) => void, ) }) - this.#selectedProvider = provider.name - await this.#proxy?.init() + this.selectedProvider = provider.name + await this.proxy?.init() return this } public async connect() { - if (!this.#proxy) throw new errors.ProviderNotInitializedError() + if (!this.proxy) throw new errors.ProviderNotInitializedError() - await this.#proxy?.connect?.() + await this.proxy?.connect?.() } public async switchChain(chainId: ChainId) { - await this.#proxy?.switchChain?.(chainId) + await this.proxy?.switchChain?.(chainId) } public async addChain(chain: Chain) { - await this.#proxy?.addChain?.(chain) + await this.proxy?.addChain?.(chain) } public static setChainsDetails(chains: Record) { @@ -115,8 +115,8 @@ export class Provider implements IProvider { } public async signAndSendTx(txRequestBody: TxRequestBody) { - if (this.#proxy?.signAndSendTx) { - return this.#proxy?.signAndSendTx?.( + if (this.proxy?.signAndSendTx) { + return this.proxy?.signAndSendTx?.( txRequestBody, ) as Promise } @@ -125,59 +125,59 @@ export class Provider implements IProvider { } public getHashFromTx(txResponse: TransactionResponse) { - return this.#proxy?.getHashFromTx?.(txResponse) ?? '' + return this.proxy?.getHashFromTx?.(txResponse) ?? '' } public getTxUrl(chain: Chain, txHash: string) { - return this.#proxy?.getTxUrl?.(chain, txHash) ?? '' + return this.proxy?.getTxUrl?.(chain, txHash) ?? '' } public getAddressUrl(chain: Chain, address: string) { - return this.#proxy?.getAddressUrl?.(chain, address) ?? '' + return this.proxy?.getAddressUrl?.(chain, address) ?? '' } public async signMessage(message: string) { - return this.#proxy?.signMessage?.(message) ?? '' + return this.proxy?.signMessage?.(message) ?? '' } public onAccountChanged(cb: (e?: ProviderEventPayload) => void): void { - this.#proxy?.onAccountChanged(cb) + this.proxy?.onAccountChanged(cb) } public onChainChanged(cb: (e?: ProviderEventPayload) => void): void { - this.#proxy?.onChainChanged?.(cb) + this.proxy?.onChainChanged?.(cb) } public onConnect(cb: (e?: ProviderEventPayload) => void): void { - this.#proxy?.onConnect(cb) + this.proxy?.onConnect(cb) } public onDisconnect(cb: (e?: ProviderEventPayload) => void): void { - this.#proxy?.onDisconnect(cb) + this.proxy?.onDisconnect(cb) } public onInitiated(cb: (e?: ProviderEventPayload) => void): void { - this.#proxy?.onInitiated(cb) + this.proxy?.onInitiated(cb) } public clearHandlers(): void { - this.#proxy?.clearHandlers() + this.proxy?.clearHandlers() } public onBeforeTxSent(cb: (e?: ProviderEventPayload) => void) { - this.#proxy?.onBeforeTxSent(cb) + this.proxy?.onBeforeTxSent(cb) } public onTxSent(cb: (e?: ProviderEventPayload) => void) { - this.#proxy?.onTxSent(cb) + this.proxy?.onTxSent(cb) } public onTxConfirmed(cb: (e?: ProviderEventPayload) => void) { - this.#proxy?.onTxConfirmed(cb) + this.proxy?.onTxConfirmed(cb) } public async disconnect() { - await this.#proxy?.disconnect?.() + await this.proxy?.disconnect?.() } } diff --git a/packages/w3p/src/providers/wrapped/_base-evm.ts b/packages/w3p/src/providers/wrapped/_base-evm.ts index 2fe16a7e..36a62e40 100644 --- a/packages/w3p/src/providers/wrapped/_base-evm.ts +++ b/packages/w3p/src/providers/wrapped/_base-evm.ts @@ -29,25 +29,21 @@ import type { import { ProviderEventBus } from './_event-bus' export class BaseEVMProvider extends ProviderEventBus implements ProviderProxy { - readonly #provider: providers.Web3Provider - #rawProvider: RawProvider + readonly provider: providers.Web3Provider + rawProvider: RawProvider - #chainId?: ChainId - #address?: string + chainId?: ChainId + address?: string constructor(provider: RawProvider) { super() - this.#provider = new providers.Web3Provider( + this.provider = new providers.Web3Provider( provider as providers.ExternalProvider, 'any', ) - this.#rawProvider = provider - } - - get rawProvider(): RawProvider { - return this.#rawProvider + this.rawProvider = provider } get chainType(): CHAIN_TYPES { @@ -55,46 +51,38 @@ export class BaseEVMProvider extends ProviderEventBus implements ProviderProxy { } get isConnected(): boolean { - return Boolean(this.#chainId && this.#address) - } - - get chainId(): ChainId | undefined { - return this.#chainId - } - - get address(): string | undefined { - return this.#address + return Boolean(this.chainId && this.address) } - get #defaultEventPayload() { + get defaultEventPayload() { return { - address: this.#address, - chainId: this.#chainId, + address: this.address, + chainId: this.chainId, isConnected: this.isConnected, } } async init(): Promise { - await this.#setListeners() - const currentAccounts = await this.#provider.listAccounts() - const network = await this.#provider.getNetwork() + await this.setListeners() + const currentAccounts = await this.provider.listAccounts() + const network = await this.provider.getNetwork() - this.#address = currentAccounts[0] - this.#chainId = hexToDecimal(network.chainId as ChainId) + this.address = currentAccounts[0] + this.chainId = hexToDecimal(network.chainId as ChainId) - this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.defaultEventPayload) } async switchChain(chainId: ChainId): Promise { - await requestSwitchEthChain(this.#provider, chainId) + await requestSwitchEthChain(this.provider, chainId) } async addChain(chain: Chain): Promise { - await requestAddEthChain(this.#provider, chain) + await requestAddEthChain(this.provider, chain) } async connect(): Promise { - await connectEthAccounts(this.#provider) + await connectEthAccounts(this.provider) } getAddressUrl(chain: Chain, address: string): string { @@ -114,7 +102,7 @@ export class BaseEVMProvider extends ProviderEventBus implements ProviderProxy { this.emit(PROVIDER_EVENT_BUS_EVENTS.BeforeTxSent, { txBody: tx, }) - const transactionResponse = await this.#provider + const transactionResponse = await this.provider .getSigner() .sendTransaction(tx as Deferrable) @@ -132,34 +120,34 @@ export class BaseEVMProvider extends ProviderEventBus implements ProviderProxy { } async signMessage(message: string): Promise { - return this.#provider.getSigner().signMessage(message) + return this.provider.getSigner().signMessage(message) } - async #setListeners() { - const stubProvider = this.#provider.provider as providers.BaseProvider + async setListeners() { + const stubProvider = this.provider.provider as providers.BaseProvider stubProvider.on(PROVIDER_EVENTS.AccountsChanged, async () => { - const currentAccounts = await this.#provider.listAccounts() - this.#address = currentAccounts[0] ?? '' + const currentAccounts = await this.provider.listAccounts() + this.address = currentAccounts[0] ?? '' this.emit( PROVIDER_EVENT_BUS_EVENTS.AccountChanged, - this.#defaultEventPayload, + this.defaultEventPayload, ) this.emit( this.isConnected ? PROVIDER_EVENT_BUS_EVENTS.Connect : PROVIDER_EVENT_BUS_EVENTS.Disconnect, - this.#defaultEventPayload, + this.defaultEventPayload, ) }) stubProvider.on(PROVIDER_EVENTS.ChainChanged, (chainId: ChainId) => { - this.#chainId = hexToDecimal(chainId) + this.chainId = hexToDecimal(chainId) this.emit( PROVIDER_EVENT_BUS_EVENTS.ChainChanged, - this.#defaultEventPayload, + this.defaultEventPayload, ) }) } diff --git a/packages/w3p/src/providers/wrapped/_base-solana.ts b/packages/w3p/src/providers/wrapped/_base-solana.ts index da858c5a..624bf13b 100644 --- a/packages/w3p/src/providers/wrapped/_base-solana.ts +++ b/packages/w3p/src/providers/wrapped/_base-solana.ts @@ -33,17 +33,17 @@ export class BaseSolanaProvider extends ProviderEventBus implements ProviderProxy { - readonly #provider: SolanaProvider - #rawProvider: RawProvider + readonly provider: SolanaProvider + rawProvider: RawProvider - #chainId?: ChainId - #address?: string + chainId?: ChainId + address?: string constructor(provider: RawProvider) { super() - this.#provider = provider as SolanaProvider + this.provider = provider as SolanaProvider - this.#rawProvider = provider + this.rawProvider = provider } get chainType(): CHAIN_TYPES { @@ -51,47 +51,31 @@ export class BaseSolanaProvider } get isConnected(): boolean { - return Boolean(this.#chainId && this.#address) + return Boolean(this.chainId && this.address) } - get chainId(): ChainId | undefined { - return this.#chainId - } - - get address(): string | undefined { - return this.#address - } - - get provider(): SolanaProvider { - return this.#provider - } - - get rawProvider(): RawProvider { - return this.#rawProvider - } - - get #defaultEventPayload() { + get defaultEventPayload() { return { - chainId: this.#chainId, - address: this.#address, + chainId: this.chainId, + address: this.address, isConnected: this.isConnected, } } async init(): Promise { - this.#setListeners() - this.#address = getAddress(this.#provider.publicKey) - this.#chainId = SOLANA_CHAINS.DevNet + this.setListeners() + this.address = getAddress(this.provider.publicKey) + this.chainId = SOLANA_CHAINS.DevNet - this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.defaultEventPayload) } async switchChain(chainId: ChainId) { try { - this.#chainId = chainId + this.chainId = chainId this.emit( PROVIDER_EVENT_BUS_EVENTS.ChainChanged, - this.#defaultEventPayload, + this.defaultEventPayload, ) } catch (error) { handleSolError(error as SolanaProviderRpcError) @@ -100,7 +84,7 @@ export class BaseSolanaProvider async connect(): Promise { try { - await this.#provider.connect() + await this.provider.connect() } catch (error) { handleSolError(error as SolanaProviderRpcError) } @@ -127,25 +111,25 @@ export class BaseSolanaProvider throw new TypeError('Method should be implemented in extender class') } - #setListeners() { - this.#provider.on(PROVIDER_EVENTS.Connect, () => { - this.#address = getAddress(this.#provider.publicKey) + setListeners() { + this.provider.on(PROVIDER_EVENTS.Connect, () => { + this.address = getAddress(this.provider.publicKey) - this.emit(PROVIDER_EVENT_BUS_EVENTS.Connect, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Connect, this.defaultEventPayload) }) - this.#provider.on(PROVIDER_EVENTS.Disconnect, () => { - this.#address = getAddress(this.#provider.publicKey) + this.provider.on(PROVIDER_EVENTS.Disconnect, () => { + this.address = getAddress(this.provider.publicKey) - this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.defaultEventPayload) }) - this.#provider.on(PROVIDER_EVENTS.AccountChanged, () => { - this.#address = getAddress(this.#provider.publicKey) + this.provider.on(PROVIDER_EVENTS.AccountChanged, () => { + this.address = getAddress(this.provider.publicKey) this.emit( PROVIDER_EVENT_BUS_EVENTS.AccountChanged, - this.#defaultEventPayload, + this.defaultEventPayload, ) }) } diff --git a/packages/w3p/src/providers/wrapped/_event-bus.ts b/packages/w3p/src/providers/wrapped/_event-bus.ts index 610a31cd..2f024cda 100644 --- a/packages/w3p/src/providers/wrapped/_event-bus.ts +++ b/packages/w3p/src/providers/wrapped/_event-bus.ts @@ -4,52 +4,48 @@ import { PROVIDER_EVENT_BUS_EVENTS } from '@/enums' import type { ProviderEventMap, ProviderEventPayload } from '@/types' export class ProviderEventBus { - readonly #emitter = new EventEmitter() - - public get emitter(): EventEmitter { - return this.#emitter - } + readonly emitter = new EventEmitter() public emit( event: PROVIDER_EVENT_BUS_EVENTS, payload: ProviderEventPayload, ): void { - this.#emitter.emit(event, payload) + this.emitter.emit(event, payload) } public onBeforeTxSent(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.BeforeTxSent, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.BeforeTxSent, cb) } public onTxSent(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.TxSent, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.TxSent, cb) } public onTxConfirmed(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.TxConfirmed, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.TxConfirmed, cb) } public onInitiated(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.once(PROVIDER_EVENT_BUS_EVENTS.Initiated, cb) + this.emitter.once(PROVIDER_EVENT_BUS_EVENTS.Initiated, cb) } public onConnect(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.Connect, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.Connect, cb) } public onDisconnect(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.Disconnect, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.Disconnect, cb) } public onAccountChanged(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.AccountChanged, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.AccountChanged, cb) } public onChainChanged(cb: (e?: ProviderEventPayload) => void): void { - this.#emitter.on(PROVIDER_EVENT_BUS_EVENTS.ChainChanged, cb) + this.emitter.on(PROVIDER_EVENT_BUS_EVENTS.ChainChanged, cb) } public clearHandlers(): void { - this.#emitter.clear() + this.emitter.clear() } } diff --git a/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts b/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts index 3882c80e..a0bb2622 100644 --- a/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts +++ b/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts @@ -39,17 +39,17 @@ export class WalletConnectEvmProvider extends ProviderEventBus implements ProviderProxy { - #rawProvider: UniversalProvider | null - #ethProvider: providers.Web3Provider | null + universalProvider: UniversalProvider | null + ethProvider: providers.Web3Provider | null - #w3Modal: WalletConnectModal + w3Modal: WalletConnectModal - #chainId?: ChainId - #address?: string + chainId?: ChainId + address?: string - readonly #projectId: string - readonly #relayUrl?: string - readonly #logger?: string + readonly projectId: string + readonly relayUrl?: string + readonly logger?: string constructor(provider: RawProvider) { super() @@ -60,13 +60,13 @@ export class WalletConnectEvmProvider throw new errors.ProviderParseError() } - this.#projectId = projectId - this.#relayUrl = relayUrl - this.#logger = logger - this.#rawProvider = null - this.#ethProvider = null - this.#w3Modal = new WalletConnectModal({ - projectId: this.#projectId, + this.projectId = projectId + this.relayUrl = relayUrl + this.logger = logger + this.universalProvider = null + this.ethProvider = null + this.w3Modal = new WalletConnectModal({ + projectId: this.projectId, }) } @@ -75,10 +75,7 @@ export class WalletConnectEvmProvider } get rawProvider(): RawProvider { - if (!this.#rawProvider) { - throw new errors.ProviderNotInitializedError() - } - return this.#rawProvider as unknown as RawProvider + return this.universalProvider as unknown as RawProvider } get chainType(): CHAIN_TYPES { @@ -86,105 +83,97 @@ export class WalletConnectEvmProvider } get isConnected(): boolean { - return Boolean(this.#chainId) || Boolean(this.#address) - } - - get chainId(): ChainId | undefined { - return this.#chainId - } - - get address(): string | undefined { - return this.#address + return Boolean(this.chainId) || Boolean(this.address) } async init(): Promise { - this.#rawProvider = await UniversalProvider.init({ - logger: this.#logger, - relayUrl: this.#relayUrl, - projectId: this.#projectId, + this.universalProvider = await UniversalProvider.init({ + logger: this.logger, + relayUrl: this.relayUrl, + projectId: this.projectId, }) - if (this.#rawProvider?.session) { - this.#ethProvider = new providers.Web3Provider(this.#rawProvider) + if (this.universalProvider?.session) { + this.ethProvider = new providers.Web3Provider(this.universalProvider) } - await this.#checkForPersistedSession() + await this.checkForPersistedSession() - await this.#setListeners() + await this.setListeners() await this.setCustomRpcs() - this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.defaultEventPayload) } async connect(): Promise { - if (!this.#rawProvider) { + if (!this.universalProvider) { throw new errors.ProviderNotInitializedError() } try { - await this.#rawProvider.connect({ + await this.universalProvider.connect({ namespaces: createWalletConnectEthNamespace(), optionalNamespaces: createWalletConnectEthNamespace(), skipPairing: true, }) - await this.#rawProvider.enable() + await this.universalProvider.enable() - this.#ethProvider = new providers.Web3Provider(this.#rawProvider) + this.ethProvider = new providers.Web3Provider(this.universalProvider) - const accounts = await this.#rawProvider.request({ + const accounts = await this.universalProvider.request({ method: 'eth_requestAccounts', }) - this.#chainId = - this.#rawProvider?.session?.namespaces?.eip155?.chains?.[0]?.split( + this.chainId = + this.universalProvider?.session?.namespaces?.eip155?.chains?.[0]?.split( ':', )[1] - this.#address = accounts?.[0] + this.address = accounts?.[0] this.emit( PROVIDER_EVENT_BUS_EVENTS.AccountChanged, - this.#defaultEventPayload, + this.defaultEventPayload, ) this.emit( this.isConnected ? PROVIDER_EVENT_BUS_EVENTS.Connect : PROVIDER_EVENT_BUS_EVENTS.Disconnect, - this.#defaultEventPayload, + this.defaultEventPayload, ) - this.#w3Modal.closeModal() + this.w3Modal.closeModal() } catch (e) { - this.#w3Modal.closeModal() + this.w3Modal.closeModal() throw e } } async disconnect() { - if (!this.#rawProvider) { + if (!this.universalProvider) { throw new errors.ProviderNotInitializedError() } - await this.#rawProvider.disconnect() - this.#chainId = undefined - this.#address = undefined - this.#ethProvider = null - this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.#defaultEventPayload) + await this.universalProvider.disconnect() + this.chainId = undefined + this.address = undefined + this.ethProvider = null + this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.defaultEventPayload) } - async #checkForPersistedSession() { - if (!this.#rawProvider) { + async checkForPersistedSession() { + if (!this.universalProvider) { throw new errors.ProviderNotInitializedError() } - if (!this.#rawProvider?.session) return + if (!this.universalProvider?.session) return - this.#chainId = this.#rawProvider?.namespaces?.eip155.defaultChain + this.chainId = this.universalProvider?.namespaces?.eip155.defaultChain - this.#address = - this.#rawProvider?.session?.namespaces?.eip155?.accounts?.[0]?.split( + this.address = + this.universalProvider?.session?.namespaces?.eip155?.accounts?.[0]?.split( ':', )?.[2] } @@ -208,7 +197,7 @@ export class WalletConnectEvmProvider */ async switchChain(chainId: ChainId): Promise { - if (!this.#ethProvider) { + if (!this.ethProvider) { throw new errors.ProviderDisconnected() } @@ -224,12 +213,12 @@ export class WalletConnectEvmProvider await this.addChain(foundChain) - this.#rawProvider?.setDefaultChain( + this.universalProvider?.setDefaultChain( `eip155:${Number(foundChain.id)}`, foundChain.rpcUrl, ) - await requestSwitchEthChain(this.#ethProvider, foundChain.id) + await requestSwitchEthChain(this.ethProvider, foundChain.id) } async setCustomRpcs() { @@ -240,7 +229,9 @@ export class WalletConnectEvmProvider Object.entries(Provider.chainsDetails).map( async ([chainId, chainInfo]) => { const rpcProvider = - this.#rawProvider?.rpcProviders?.eip155?.httpProviders?.[chainId] + this.universalProvider?.rpcProviders?.eip155?.httpProviders?.[ + chainId + ] if (rpcProvider) { await rpcProvider.connect(chainInfo.rpcUrl) } @@ -250,15 +241,15 @@ export class WalletConnectEvmProvider } async addChain(chain: Chain): Promise { - if (!this.#ethProvider) { + if (!this.ethProvider) { throw new errors.ProviderDisconnected() } - await requestAddEthChain(this.#ethProvider, chain) + await requestAddEthChain(this.ethProvider, chain) } async signAndSendTx(tx: TxRequestBody): Promise { - if (!this.#rawProvider) { + if (!this.universalProvider) { throw new errors.ProviderNotInitializedError() } @@ -266,7 +257,7 @@ export class WalletConnectEvmProvider txBody: tx, }) - const transactionResponse = await this.#ethProvider?.send( + const transactionResponse = await this.ethProvider?.send( 'eth_sendTransaction', [tx], ) @@ -285,59 +276,62 @@ export class WalletConnectEvmProvider } async signMessage(message: string): Promise { - if (!this.#ethProvider || !this.#address) { + if (!this.ethProvider || !this.address) { throw new errors.ProviderDisconnected() } - return this.#ethProvider?.send('personal_sign', [ + return this.ethProvider?.send('personal_sign', [ utils.hexlify(utils.toUtf8Bytes(message)), - this.#address.toLowerCase(), + this.address.toLowerCase(), ]) } - get #defaultEventPayload() { + get defaultEventPayload() { return { - address: this.#address, - chainId: this.#chainId, + address: this.address, + chainId: this.chainId, isConnected: this.isConnected, } } - async #setListeners() { - if (!this.#rawProvider) { + async setListeners() { + if (!this.universalProvider) { throw new errors.ProviderNotInitializedError() } - this.#rawProvider.on('session_event', (e: WalletConnectSessionEvent) => { - this.#chainId = e?.params?.chainId.split(':')[1] ?? this.#chainId - - this.#address = - e?.params?.event?.data?.[0]?.split(':')?.[2] ?? this.#address - - this.emit( - PROVIDER_EVENT_BUS_EVENTS.AccountChanged, - this.#defaultEventPayload, - ) - - this.emit( - PROVIDER_EVENT_BUS_EVENTS.ChainChanged, - this.#defaultEventPayload, - ) - - this.emit( - this.isConnected - ? PROVIDER_EVENT_BUS_EVENTS.Connect - : PROVIDER_EVENT_BUS_EVENTS.Disconnect, - this.#defaultEventPayload, - ) - }) + this.universalProvider.on( + 'session_event', + (e: WalletConnectSessionEvent) => { + this.chainId = e?.params?.chainId.split(':')[1] ?? this.chainId + + this.address = + e?.params?.event?.data?.[0]?.split(':')?.[2] ?? this.address + + this.emit( + PROVIDER_EVENT_BUS_EVENTS.AccountChanged, + this.defaultEventPayload, + ) + + this.emit( + PROVIDER_EVENT_BUS_EVENTS.ChainChanged, + this.defaultEventPayload, + ) + + this.emit( + this.isConnected + ? PROVIDER_EVENT_BUS_EVENTS.Connect + : PROVIDER_EVENT_BUS_EVENTS.Disconnect, + this.defaultEventPayload, + ) + }, + ) - this.#rawProvider.on('session_delete', () => { - this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.#defaultEventPayload) + this.universalProvider.on('session_delete', () => { + this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.defaultEventPayload) }) - this.#rawProvider.on('display_uri', (uri: string) => { - this.#w3Modal.openModal({ uri }) + this.universalProvider.on('display_uri', (uri: string) => { + this.w3Modal.openModal({ uri }) }) } } diff --git a/packages/w3p/src/providers/wrapped/fallback-evm.ts b/packages/w3p/src/providers/wrapped/fallback-evm.ts index 042d0d84..cb70e036 100644 --- a/packages/w3p/src/providers/wrapped/fallback-evm.ts +++ b/packages/w3p/src/providers/wrapped/fallback-evm.ts @@ -22,57 +22,45 @@ export class FallbackEvmProvider extends ProviderEventBus implements ProviderProxy { - #provider: providers.Web3Provider - #rawProvider: RawProvider + provider: providers.Web3Provider + rawProvider: RawProvider - #chainId?: ChainId - #address?: string + chainId?: ChainId + address?: string constructor(provider: RawProvider) { super() - this.#provider = provider as unknown as providers.Web3Provider - this.#rawProvider = provider + this.provider = provider as unknown as providers.Web3Provider + this.rawProvider = provider } static get providerType(): string { return PROVIDERS.Fallback } - get rawProvider(): RawProvider { - return this.#rawProvider - } - get chainType(): CHAIN_TYPES { return CHAIN_TYPES.EVM } get isConnected(): boolean { - return Boolean(this.#chainId) - } - - get chainId(): ChainId | undefined { - return this.#chainId - } - - get address(): string | undefined { - return this.#address + return Boolean(this.chainId) } - get #defaultEventPayload() { + get defaultEventPayload() { return { - address: this.#address, - chainId: this.#chainId, + address: this.address, + chainId: this.chainId, isConnected: this.isConnected, } } async init(): Promise { - const network = await this.#provider.getNetwork() + const network = await this.provider.getNetwork() - this.#chainId = hexToDecimal(network.chainId as ChainId) + this.chainId = hexToDecimal(network.chainId as ChainId) - this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.defaultEventPayload) } getAddressUrl(chain: Chain, address: string): string { diff --git a/packages/w3p/src/providers/wrapped/near.ts b/packages/w3p/src/providers/wrapped/near.ts index 0ac32235..96a2c313 100644 --- a/packages/w3p/src/providers/wrapped/near.ts +++ b/packages/w3p/src/providers/wrapped/near.ts @@ -20,76 +20,64 @@ import type { import { ProviderEventBus } from './_event-bus' export class NearProvider extends ProviderEventBus implements ProviderProxy { - readonly #provider: NearRawProvider - #rawProvider: RawProvider + readonly provider: NearRawProvider + rawProvider: RawProvider - #chainId?: ChainId - #address?: string + chainId?: ChainId + address?: string constructor(provider: RawProvider) { super() - this.#provider = provider as NearRawProvider - this.#rawProvider = provider + this.provider = provider as NearRawProvider + this.rawProvider = provider } static get providerType(): PROVIDERS { return PROVIDERS.Near } - get rawProvider(): RawProvider { - return this.#rawProvider - } - get isConnected(): boolean { - return Boolean(this.#chainId && this.#address) - } - - get chainId(): ChainId | undefined { - return this.#chainId - } - - get address(): string | undefined { - return this.#address + return Boolean(this.chainId && this.address) } - get #defaultEventPayload() { + get defaultEventPayload() { return { - chainId: this.#chainId, - address: this.#address, + chainId: this.chainId, + address: this.address, isConnected: this.isConnected, } } async init(): Promise { try { - await this.#provider.init() - this.#updateProviderState() + await this.provider.init() + this.updateProviderState() - this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Initiated, this.defaultEventPayload) } catch (error) { handleNearError(error as NearProviderRpcError) } } - #updateProviderState(): void { - const networkId = this.#provider.selector?.options.network.networkId + updateProviderState(): void { + const networkId = this.provider.selector?.options.network.networkId - this.#address = this.#provider?.accountId || '' - this.#chainId = networkId || NEAR_CHAINS.TestNet + this.address = this.provider?.accountId || '' + this.chainId = networkId || NEAR_CHAINS.TestNet } async switchChain(chainId: ChainId): Promise { - this.#chainId = chainId + this.chainId = chainId - this.emit(PROVIDER_EVENT_BUS_EVENTS.ChainChanged, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.ChainChanged, this.defaultEventPayload) } async connect(): Promise { try { - await this.#provider.signIn() - await this.#updateProviderState() + await this.provider.signIn() + await this.updateProviderState() - this.emit(PROVIDER_EVENT_BUS_EVENTS.Connect, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Connect, this.defaultEventPayload) } catch (error) { handleNearError(error as NearProviderRpcError) } @@ -97,10 +85,10 @@ export class NearProvider extends ProviderEventBus implements ProviderProxy { async disconnect(): Promise { try { - await this.#provider.signOut() - this.#updateProviderState() + await this.provider.signOut() + this.updateProviderState() - this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.#defaultEventPayload) + this.emit(PROVIDER_EVENT_BUS_EVENTS.Disconnect, this.defaultEventPayload) } catch (error) { handleNearError(error as NearProviderRpcError) } @@ -128,7 +116,7 @@ export class NearProvider extends ProviderEventBus implements ProviderProxy { txBody: txRequestBody, }) - const txResponse = (await this.#provider.signAndSendTxs( + const txResponse = (await this.provider.signAndSendTxs( txRequestBody as NearTxRequestBody, )) as TransactionResponse From 6d80cacdb69b58638cfae872a57875c8dfd34c61 Mon Sep 17 00:00:00 2001 From: lukachi Date: Sat, 2 Mar 2024 18:09:04 +0200 Subject: [PATCH 2/4] add examples for vue & react --- packages/w3p/examples/eth-contract-call.ts | 168 ------------ packages/w3p/examples/multiple-providers.ts | 239 ------------------ packages/w3p/examples/react/UiKitWeb3.tsx | 70 +++++ packages/w3p/examples/react/erc20.ts | 23 ++ packages/w3p/examples/react/web3.module.ts | 58 +++++ .../examples/vue-use-provider-composable.ts | 150 ----------- packages/w3p/examples/vue/component-script.ts | 50 ++++ packages/w3p/examples/vue/erc20.ts | 25 ++ packages/w3p/examples/vue/web3.ts | 63 +++++ packages/w3p/src/provider.ts | 3 +- 10 files changed, 291 insertions(+), 558 deletions(-) delete mode 100644 packages/w3p/examples/eth-contract-call.ts delete mode 100644 packages/w3p/examples/multiple-providers.ts create mode 100644 packages/w3p/examples/react/UiKitWeb3.tsx create mode 100644 packages/w3p/examples/react/erc20.ts create mode 100644 packages/w3p/examples/react/web3.module.ts delete mode 100644 packages/w3p/examples/vue-use-provider-composable.ts create mode 100644 packages/w3p/examples/vue/component-script.ts create mode 100644 packages/w3p/examples/vue/erc20.ts create mode 100644 packages/w3p/examples/vue/web3.ts diff --git a/packages/w3p/examples/eth-contract-call.ts b/packages/w3p/examples/eth-contract-call.ts deleted file mode 100644 index 03fa19c0..00000000 --- a/packages/w3p/examples/eth-contract-call.ts +++ /dev/null @@ -1,168 +0,0 @@ -// @ts-nocheck -import { computed } from 'vue' -import { Erc20__factory } from '@/types' -import { BigNumberish, ethers } from 'ethers' -import { useWeb3ProvidersStore } from '@/store' -import { PROVIDERS } from '@distributedlab/w3p' - -export const useErc20Contract = (address: string) => { - const web3ProvidersStore = useWeb3ProvidersStore() - - const provider = computed(() => web3ProvidersStore.provider) - - const rawProvider = computed(() => - provider.value.providerType !== PROVIDERS.Fallback - ? new ethers.providers.Web3Provider( - provider.value.rawProvider as ethers.providers.ExternalProvider, - 'any', - ) - : (provider.value - .rawProvider as unknown as ethers.providers.JsonRpcProvider), - ) - - const contractInstance = computed( - () => - (!!provider.value && - !!address && - !!rawProvider.value && - !!address && - Erc20__factory.connect(address, rawProvider.value)) || - undefined, - ) - - const contractInterface = Erc20__factory.createInterface() - - const approve = async (spender: string, amount: BigNumberish) => { - const data = contractInterface.encodeFunctionData('approve', [ - spender, - amount, - ]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const decreaseAllowance = async ( - spender: string, - subtractedValue: BigNumberish, - ) => { - const data = contractInterface.encodeFunctionData('decreaseAllowance', [ - spender, - subtractedValue, - ]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const increaseAllowance = async ( - spender: string, - addedValue: BigNumberish, - ) => { - const data = contractInterface.encodeFunctionData('increaseAllowance', [ - spender, - addedValue, - ]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const mint = async (to: string, amount: BigNumberish) => { - const data = contractInterface.encodeFunctionData('mint', [to, amount]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const renounceOwnership = async () => { - const data = contractInterface.encodeFunctionData('renounceOwnership') - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const transfer = async (address: string, amount: BigNumberish) => { - const data = contractInterface.encodeFunctionData('transfer', [ - address, - amount, - ]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const transferFrom = async ( - from: string, - to: string, - amount: BigNumberish, - ) => { - const data = contractInterface.encodeFunctionData('transferFrom', [ - from, - to, - amount, - ]) - - return provider.value.signAndSendTx({ - to: address, - data, - }) - } - - const getAllowance = async (owner: string, spender: string) => { - return contractInstance.value?.allowance(owner, spender) - } - - const getBalanceOf = async (address: string) => { - return contractInstance.value?.balanceOf(address) - } - - const getDecimals = async () => { - return contractInstance.value?.decimals() - } - - const getName = async () => { - return contractInstance.value?.name() - } - - const getOwner = async () => { - return contractInstance.value?.owner() - } - - const getSymbol = async () => { - return contractInstance.value?.symbol() - } - - const getTotalSupply = async () => { - return contractInstance.value?.totalSupply() - } - - return { - approve, - decreaseAllowance, - increaseAllowance, - mint, - renounceOwnership, - transfer, - transferFrom, - getAllowance, - getBalanceOf, - getDecimals, - getName, - getOwner, - getSymbol, - getTotalSupply, - } -} diff --git a/packages/w3p/examples/multiple-providers.ts b/packages/w3p/examples/multiple-providers.ts deleted file mode 100644 index 9f389c8c..00000000 --- a/packages/w3p/examples/multiple-providers.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { computed, watch } from 'vue' -import { defineStore } from 'pinia' -import { useUniversalStorage } from '@/composables' -import { config } from '@config' -import { - CoinbaseProvider, - MetamaskProvider, - FallbackEvmProvider, - ProviderDetector, - ProviderInstance, - PROVIDERS, - ProviderProxyConstructor, - WalletConnectEvmProvider, -} from '@distributedlab/w3p' -import { useProvider } from './vue-use-provider-composable' - -const STORE_NAME = 'web3-providers-store' - -/** - * EXTERNAL_PROVIDERS are the custom providers for specific project - * you should create it in your project if you have some custom providers - * - * enum EXTERNAL_PROVIDERS = { - * tokene = 'tokene', - * myCustomProvider = 'myCustomProvider', - * } - * - * type SUPPORTED_PROVIDERS = EXTERNAL_PROVIDERS | PROVIDERS - */ - -/** - * By default you can use just PROVIDERS - */ -type SUPPORTED_PROVIDERS = PROVIDERS - -export const useWeb3ProvidersStore = defineStore(STORE_NAME, () => { - /** - * useProvider composable is the reactive wrapper for w3p, - * you can copy https://github.com/distributed-lab/web-kit/blob/main/packages/w3p/examples/vue-use-provider-composable.ts - * and paste in your project - */ - const provider = useProvider() - - const providerDetector = computed( - () => new ProviderDetector(), - ) - - /** - * The simple solution for keep providerType in - * `localStorage` | `cookie` | `sessionStorage` or all of them - * - * Under the hood it returns ref, so pinia take it as state - * - * you can replace it with your own solution - * for example use pinia persisted state - */ - const storageState = useUniversalStorage<{ - providerType?: SUPPORTED_PROVIDERS - }>( - STORE_NAME, - { - providerType: provider.providerType?.value, - }, - { - isLocalStorage: true, - isCookieStorage: true, - }, - ) - - watch( - () => provider.providerType?.value, - () => { - storageState.value.providerType = provider.providerType?.value - }, - ) - - const isValidChain = computed( - () => - String(provider.chainId?.value).toLowerCase() === - config.SUPPORTED_CHAIN_ID.toLowerCase(), - ) - - /** - * init method shoud be called at the top level of your app to define connected provider e.g. after refreshing page, - * and if it founds providerType in storage it will try to connect to it - * Furthermore you can call init method with providerType param to connect to specific provider - * - * in common case you can show list of supported providers and choose on of them - * @param providerType - */ - async function init(providerType?: SUPPORTED_PROVIDERS) { - try { - await providerDetector.value.init() - - /** - * In the case where you have some custom provider - * you can add it by following code - * - * if (window.tokene) { - * await providerDetector.value.addProvider({ - * name: EXTERNAL_PROVIDERS.TokenE, - * instance: wrapExternalEthProvider( - * window.tokene as providers.ExternalProvider, - * ) as RawProvider, - * }) - * } - - * Since WalletConnect lacks an injected provider for - * interacting with the chain, it's required to add - * WalletConnect provider configuration with - * the following method: - * - * await providerDetector.value.addProvider({ - * name: PROVIDERS.WalletConnect, - * instance: { - * projectId: 'abcdefghijklmnopqrstuvwxyz', - * relayUrl: 'wss://relay.walletconnect.com', - * logger: 'info' - * } as RawProvider, - * }) - * - */ - - /** - * If you need to fetch some data from contracts aka view methods for unconnected users, - * you can add fallback provider - * - * if (!providerDetector.value.providers[PROVIDERS.Fallback]) { - * addProvider({ - * name: PROVIDERS.Fallback, - * instance: new providers.JsonRpcProvider( - * config.SUPPORTED_CHAIN_RPC_URL, - * 'any', - * ) as unknown as EthereumProvider, - * }) - * } - */ - - /** - * If you need to do something with chain details e.g. show link to explorer after tx sent - * - * Provider.setChainsDetails(getSupportedChainsDetails()) - */ - - /** - * If you need to do something with chain details e.g. show link to explorer after tx sent - * - * Provider.setChainsDetails(getSupportedChainsDetails()) - */ - - /** - * To define a custom RPC network that the WalletConnect provider - * will use, you need to specify the chain you want to define in - * the Provider.setChainDetails method. - * - * Provider.setChainsDetails({ - * 5: { - * id: '0x5', - * name: 'Goerli', - * rpcUrl: 'https://goerli.blockpi.network/v1/rpc/public', - * explorerUrl: 'https://goerli.etherscan.io/', - * token: { name: 'Goerli', symbol: 'GTH', decimals: 18 }, - * type: CHAIN_TYPES.EVM, - * icon: '', - * }, - * }) - */ - - /** - * All supported providers, which should be defined, because - */ - const supportedProviders: { - [key in SUPPORTED_PROVIDERS]?: ProviderProxyConstructor - } = { - [PROVIDERS.Fallback]: FallbackEvmProvider, - [PROVIDERS.Metamask]: MetamaskProvider, - [PROVIDERS.Coinbase]: CoinbaseProvider, - [PROVIDERS.WalletConnect]: WalletConnectEvmProvider, - /** - * in the case where you have some custom provider, place your ProviderProxyConstructor here - * [EXTERNAL_PROVIDERS.TokenE]: TokenEProvider as ProviderProxyConstructor, - */ - } - - const currentProviderType: SUPPORTED_PROVIDERS = - providerType ?? storageState.value.providerType ?? PROVIDERS.Fallback - - const providerProxyConstructor: ProviderProxyConstructor = - supportedProviders[currentProviderType]! - - await provider.init(providerProxyConstructor, { - providerDetector: providerDetector.value, - /** - * if you need to do something on some event, you can define handlers here - * - * listeners: { - * onTxSent, - * onTxConfirmed, - * ..., - * }, - */ - }) - - if (!provider.isConnected?.value) { - await provider.connect() - } - } catch (error) { - storageState.value.providerType = undefined - } - } - - function addProvider(provider: ProviderInstance) { - if (providerDetector.value.providers?.[provider.name]) return - - providerDetector.value.addProvider(provider) - } - - async function disconnect() { - try { - await provider.disconnect() - // eslint-disable-next-line no-empty - } catch (error) {} - - storageState.value.providerType = undefined - - await init() - } - - return { - provider, - providerDetector, - - isValidChain, - - init, - addProvider, - disconnect, - } -}) diff --git a/packages/w3p/examples/react/UiKitWeb3.tsx b/packages/w3p/examples/react/UiKitWeb3.tsx new file mode 100644 index 00000000..583e5144 --- /dev/null +++ b/packages/w3p/examples/react/UiKitWeb3.tsx @@ -0,0 +1,70 @@ +import { BN } from '@distributedlab/tools' +import { PROVIDERS } from '@distributedlab/w3p' +import { + Button, + Card, + CardActions, + CardContent, + CardHeader, + Stack, + Typography, +} from '@mui/material' + +import { useErc20 } from '@/hooks/contracts/erc20' +import { useWeb3State, web3Store } from '@/store/modules/web3.module' + +export default function UiKitWeb3() { + const { provider } = useWeb3State() + + const erc20 = useErc20(import.meta.env.VITE_ERC20_CONTRACT_ADDRESS, provider?.rawProvider) + + const loadErc20Details = async () => { + const [balance, decimals] = await Promise.all([ + erc20?.contractInstance?.balanceOf(provider?.address ?? ''), + erc20?.contractInstance?.decimals(), + ]) + + console.log('balance', balance) + console.log('decimals', decimals) + } + + const sendSimpleTx = async () => { + const txBody = { + to: import.meta.env.VITE_ERC20_CONTRACT_ADDRESS, + data: erc20?.contractInterface?.encodeFunctionData('transfer', [ + '0x4148A2eE8D42E63E8d1ADB7F4247A17658730b38', + BN.fromRaw(1, 18).value, + ]), + } + + const receipt = await provider?.signAndSendTx(txBody) + + console.log(receipt) + } + + return ( + + + + + + Address: {provider?.address} + Chain ID: {provider?.chainId} + + + + + + + + + + + ) +} diff --git a/packages/w3p/examples/react/erc20.ts b/packages/w3p/examples/react/erc20.ts new file mode 100644 index 00000000..3d283b1d --- /dev/null +++ b/packages/w3p/examples/react/erc20.ts @@ -0,0 +1,23 @@ +import { RawProvider } from '@distributedlab/w3p' +import { providers } from 'ethers' +import { useMemo } from 'react' + +import { Erc20__factory } from '@/types/contracts' + +export const useErc20 = (address: string, provider: RawProvider | undefined) => { + const contractInstance = useMemo(() => { + if (!provider) return + + return Erc20__factory.connect( + address, + new providers.Web3Provider(provider as providers.ExternalProvider), + ) + }, [address, provider]) + + const contractInterface = useMemo(() => Erc20__factory.createInterface(), []) + + return { + contractInstance, + contractInterface, + } +} diff --git a/packages/w3p/examples/react/web3.module.ts b/packages/w3p/examples/react/web3.module.ts new file mode 100644 index 00000000..49acf43f --- /dev/null +++ b/packages/w3p/examples/react/web3.module.ts @@ -0,0 +1,58 @@ +import { + createProvider, + MetamaskProvider, + Provider, + ProviderDetector, + ProviderProxyConstructor, + PROVIDERS, +} from '@distributedlab/w3p' +import { ref } from 'valtio' + +import { createStore } from '@/helpers' + +type Web3Store = { + provider: Provider | undefined +} + +const providerDetector = new ProviderDetector() + +const PROVIDERS_PROXIES: { [key in PROVIDERS]?: ProviderProxyConstructor } = { + [PROVIDERS.Metamask]: MetamaskProvider, +} + +export const [web3Store, useWeb3State] = createStore( + 'web3', + { + provider: undefined, + } as Web3Store, + state => ({ + connect: async (providerType: PROVIDERS) => { + if (!(providerType in PROVIDERS_PROXIES)) throw new TypeError('Provider not supported') + + const providerProxy = PROVIDERS_PROXIES[providerType] + + if (!providerProxy) throw new TypeError('Provider not supported') + + state.provider?.clearHandlers?.() + + state.provider = ref( + await createProvider(providerProxy, { + providerDetector, + listeners: { + onChainChanged: () => { + web3Store.connect(providerType) + }, + onAccountChanged: () => { + web3Store.connect(providerType) + }, + }, + }), + ) + + await state.provider.connect() + }, + }), + { + isPersist: false, + }, +) diff --git a/packages/w3p/examples/vue-use-provider-composable.ts b/packages/w3p/examples/vue-use-provider-composable.ts deleted file mode 100644 index ff0f7cce..00000000 --- a/packages/w3p/examples/vue-use-provider-composable.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { - type Chain, - type ChainId, - createProvider, - type CreateProviderOpts, - Provider, - type ProviderProxyConstructor, - PROVIDERS, - type RawProvider, - type TransactionResponse, - type TxRequestBody, -} from '@distributedlab/w3p' -import { onUnmounted, reactive, ref, toRefs } from 'vue' - -type ProviderState = { - address?: string - chainId?: ChainId - chainType?: string - isConnected?: boolean - providerType?: PROVIDERS - chainDetails?: Chain -} - -export const useProvider = () => { - let _provider: Provider | undefined - - const _providerReactiveState = reactive({ - address: '', - chainId: '', - chainType: '', - isConnected: false, - providerType: undefined, - chainDetails: undefined, - }) - - const rawProvider = ref() - - async function init>( - providerProxyConstructor: ProviderProxyConstructor, - createProviderOpts: CreateProviderOpts, - ) { - try { - _provider = await createProvider(providerProxyConstructor, { - providerDetector: createProviderOpts.providerDetector, - listeners: { - ...createProviderOpts.listeners, - onAccountChanged: () => { - createProviderOpts?.listeners?.onAccountChanged?.() - _updateProviderState() - }, - onChainChanged: () => { - createProviderOpts?.listeners?.onChainChanged?.() - _updateProviderState() - }, - onConnect: () => { - createProviderOpts?.listeners?.onConnect?.() - _updateProviderState() - }, - onDisconnect: () => { - createProviderOpts?.listeners?.onDisconnect?.() - _updateProviderState() - }, - }, - }) - - rawProvider.value = createProviderOpts.providerDetector?.getProvider( - providerProxyConstructor.providerType as PROVIDERS, - )?.instance - - _updateProviderState() - } catch (error) { - console.error(error) - } - } - - const _updateProviderState = () => { - _providerReactiveState.address = _provider?.address - _providerReactiveState.chainId = String(_provider?.chainId) - _providerReactiveState.chainType = _provider?.chainType - _providerReactiveState.isConnected = _provider?.isConnected - _providerReactiveState.providerType = _provider?.providerType - _providerReactiveState.chainDetails = _provider?.chainDetails - } - - const connect = async () => { - await _provider?.connect() - } - - const switchChain = async (chainId: ChainId) => { - await _provider?.switchChain(chainId) - } - - const addChain = async (chain: Chain) => { - await _provider?.addChain?.(chain) - } - - const getAddressUrl = (chain: Chain, address: string) => { - return _provider?.getAddressUrl?.(chain, address) - } - - const getHashFromTx = (txResponse: TransactionResponse) => { - return _provider?.getHashFromTx?.(txResponse) - } - - const getTxUrl = (chain: Chain, txHash: string) => { - return _provider?.getTxUrl?.(chain, txHash) - } - - const signAndSendTx = async (txRequestBody: TxRequestBody) => { - return _provider?.signAndSendTx?.(txRequestBody) - } - - const signMessage = async (message: string) => { - return _provider?.signMessage?.(message) - } - - const disconnect = async () => { - if (_provider?.disconnect) { - await _provider.disconnect() - - return - } - - _provider = undefined - } - - onUnmounted(() => { - if (_providerReactiveState.providerType) return - - _provider?.clearHandlers() - }) - - return { - ...toRefs(_providerReactiveState), - - rawProvider, - - init, - connect, - switchChain, - addChain, - getAddressUrl, - getHashFromTx, - getTxUrl, - signAndSendTx, - signMessage, - - disconnect, - } -} diff --git a/packages/w3p/examples/vue/component-script.ts b/packages/w3p/examples/vue/component-script.ts new file mode 100644 index 00000000..2e07eeb5 --- /dev/null +++ b/packages/w3p/examples/vue/component-script.ts @@ -0,0 +1,50 @@ +import { BN } from '@distributedlab/tools' +import { PROVIDERS } from '@distributedlab/w3p' +import { computed, toValue, watch } from 'vue' + +import { useErc20 } from '@/composables/contracts/erc20' +import { useWeb3Inject } from '@/injects' +import { UiButton } from '@/ui' + +const { provider, connect } = useWeb3Inject() + +watch(provider, () => { + console.log('provider', provider.value) +}) + +const erc20 = computed(() => { + const rawProvider = provider.value?.rawProvider + + if (!rawProvider) return + + const { contractInterface, contractInstance } = useErc20( + import.meta.env.VITE_ERC20_CONTRACT_ADDRESS, + rawProvider, + ) + + return { contractInterface, contractInstance: toValue(contractInstance) } +}) + +const loadErc20Details = async () => { + const [balance, decimals] = await Promise.all([ + erc20.value?.contractInstance?.balanceOf(provider.value?.address ?? ''), + erc20.value?.contractInstance?.decimals(), + ]) + + console.log('balance', balance) + console.log('decimals', decimals) +} + +const sendSimpleTx = async () => { + const txBody = { + to: import.meta.env.VITE_ERC20_CONTRACT_ADDRESS, + data: erc20.value?.contractInterface?.encodeFunctionData('transfer', [ + '0x4148A2eE8D42E63E8d1ADB7F4247A17658730b38', + BN.fromRaw(1, 18).value, + ]), + } + + const receipt = await provider.value?.signAndSendTx(txBody) + + console.log(receipt) +} diff --git a/packages/w3p/examples/vue/erc20.ts b/packages/w3p/examples/vue/erc20.ts new file mode 100644 index 00000000..41d34a16 --- /dev/null +++ b/packages/w3p/examples/vue/erc20.ts @@ -0,0 +1,25 @@ +import { RawProvider } from '@distributedlab/w3p' +import { providers } from 'ethers' +import { computed, MaybeRef, toValue } from 'vue' + +import { Erc20__factory } from '@/types/contracts' + +export const useErc20 = (address: string, provider: MaybeRef) => { + const contractInstance = computed(() => { + const providerValue = toValue(provider) + + if (!providerValue) return null + + return Erc20__factory.connect( + address, + new providers.Web3Provider(providerValue as providers.ExternalProvider), + ) + }) + + const contractInterface = Erc20__factory.createInterface() + + return { + contractInstance, + contractInterface, + } +} diff --git a/packages/w3p/examples/vue/web3.ts b/packages/w3p/examples/vue/web3.ts new file mode 100644 index 00000000..6c6c23a7 --- /dev/null +++ b/packages/w3p/examples/vue/web3.ts @@ -0,0 +1,63 @@ +import { + createProvider, + MetamaskProvider, + Provider, + ProviderDetector, + ProviderProxyConstructor, + PROVIDERS, +} from '@distributedlab/w3p' +import { inject, provide, Ref, ref } from 'vue' + +const providerDetector = new ProviderDetector() + +const PROVIDERS_PROXIES: { [key in PROVIDERS]?: ProviderProxyConstructor } = { + [PROVIDERS.Metamask]: MetamaskProvider, +} + +const PROVIDE_NAME = 'web3' + +type Web3State = { + provider: Ref + connect: (providerType: PROVIDERS) => Promise +} + +export const useWeb3Provide = () => { + const provider = ref() + + const connect = async (providerType: PROVIDERS) => { + if (!(providerType in PROVIDERS_PROXIES)) throw new TypeError('Provider not supported') + + const providerProxy = PROVIDERS_PROXIES[providerType] + + if (!providerProxy) throw new TypeError('Provider not supported') + + provider.value?.clearHandlers?.() + + provider.value = await createProvider(providerProxy, { + providerDetector, + listeners: { + onChainChanged: () => { + connect(providerType) + }, + onAccountChanged: () => { + connect(providerType) + }, + }, + }) + + await provider.value.connect() + } + + provide(PROVIDE_NAME, { + provider, + connect, + }) +} + +export const useWeb3Inject = () => { + const web3 = inject(PROVIDE_NAME) + + if (!web3) throw new Error('useWeb3Inject must be used within a Web3Provider') + + return web3 +} diff --git a/packages/w3p/src/provider.ts b/packages/w3p/src/provider.ts index d85dcbe9..aeeb04fc 100644 --- a/packages/w3p/src/provider.ts +++ b/packages/w3p/src/provider.ts @@ -11,6 +11,7 @@ import type { ProviderListeners, ProviderProxy, ProviderProxyConstructor, + RawProvider, TransactionResponse, TxRequestBody, } from './types' @@ -51,7 +52,7 @@ export class Provider implements IProvider { this.proxyConstructor = proxyConstructor } - public get rawProvider() { + public get rawProvider(): RawProvider | undefined { return this.proxy?.rawProvider } From 3534d869cf02ec9e9f078d5ae1740458ff1bade2 Mon Sep 17 00:00:00 2001 From: lukachi Date: Sat, 2 Mar 2024 18:25:55 +0200 Subject: [PATCH 3/4] refactoring upds --- packages/w3p/src/provider-detector.ts | 9 ++++----- packages/w3p/src/providers/wrapped/evm-wallet-connect.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/w3p/src/provider-detector.ts b/packages/w3p/src/provider-detector.ts index 1aadddcd..9ddc6f77 100644 --- a/packages/w3p/src/provider-detector.ts +++ b/packages/w3p/src/provider-detector.ts @@ -110,13 +110,12 @@ export class ProviderDetector> { } async defineProviders(): Promise { - if (this.rawProviders.length) { - this.designateProviders() - } else { + if (!this.rawProviders.length) { await sleep(3000) - await this.detectRawProviders() - this.designateProviders() + this.detectRawProviders() } + + this.designateProviders() } designateProviders(): void { diff --git a/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts b/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts index a0bb2622..e691fc6a 100644 --- a/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts +++ b/packages/w3p/src/providers/wrapped/evm-wallet-connect.ts @@ -83,7 +83,7 @@ export class WalletConnectEvmProvider } get isConnected(): boolean { - return Boolean(this.chainId) || Boolean(this.address) + return Boolean(this.chainId || this.address) } async init(): Promise { From 560af8dcbeac0aeb81a177eca40ce2d4c6b288b4 Mon Sep 17 00:00:00 2001 From: lukachi Date: Sat, 2 Mar 2024 18:32:33 +0200 Subject: [PATCH 4/4] bump v, upd changelog --- CHANGELOG.md | 8 +++++++- packages/fetcher/package.json | 2 +- packages/jac/package.json | 2 +- packages/reactivity/package.json | 2 +- packages/tools/package.json | 2 +- packages/w3p/package.json | 2 +- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5416fc5..b07b4d97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.0-rc.13] - 2024-03-02 +### Changed +- `@distributedlab/w3p` - private properties to be public +- `@distributedlab/tools` - `EventEmitter` properties to be public + ## [1.0.0-rc.12] - 2024-02-28 ### Removed - `all` - Compling output into `.mjs` extension @@ -366,7 +371,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [old repo]: https://github.com/distributed-lab/web-kit-old -[Unreleased]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.12...HEAD +[Unreleased]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.13...HEAD +[1.0.0-rc.13]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.12...1.0.0-rc.13 [1.0.0-rc.12]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.11...1.0.0-rc.12 [1.0.0-rc.11]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.10...1.0.0-rc.11 [1.0.0-rc.10]: https://github.com/distributed-lab/web-kit/compare/1.0.0-rc.9...1.0.0-rc.10 diff --git a/packages/fetcher/package.json b/packages/fetcher/package.json index 4bf2d73a..32d1eb8d 100644 --- a/packages/fetcher/package.json +++ b/packages/fetcher/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/fetcher", - "version": "1.0.0-rc.12", + "version": "1.0.0-rc.13", "description": "Fetch API wrapper with the extended functionality and simple interface", "repository": { "type": "git", diff --git a/packages/jac/package.json b/packages/jac/package.json index 1d72426b..936f2093 100644 --- a/packages/jac/package.json +++ b/packages/jac/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/jac", - "version": "1.0.0-rc.12", + "version": "1.0.0-rc.13", "description": "A library for constructing JSON-API compliant requests and responses", "repository": { "type": "git", diff --git a/packages/reactivity/package.json b/packages/reactivity/package.json index dbc501a2..eb538bc3 100644 --- a/packages/reactivity/package.json +++ b/packages/reactivity/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/reactivity", - "version": "1.0.0-rc.12", + "version": "1.0.0-rc.13", "description": "Implementation of the reactivity connections to propagate changes between objects", "repository": { "type": "git", diff --git a/packages/tools/package.json b/packages/tools/package.json index 053216b7..15725ef1 100644 --- a/packages/tools/package.json +++ b/packages/tools/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/tools", - "version": "1.0.0-rc.12", + "version": "1.0.0-rc.13", "description": "Collection of common utility functions and classes", "repository": { "type": "git", diff --git a/packages/w3p/package.json b/packages/w3p/package.json index 95955713..dbe2d2e6 100644 --- a/packages/w3p/package.json +++ b/packages/w3p/package.json @@ -1,6 +1,6 @@ { "name": "@distributedlab/w3p", - "version": "1.0.0-rc.12", + "version": "1.0.0-rc.13", "description": "Wrapper for Web3 Providers", "repository": { "type": "git",