UNPKG

proximity-wallet-connect

Version:

Wallet Connect package for NEAR Wallet Selector (Proximity fork with transaction fixes).

161 lines (140 loc) 4.84 kB
import Client from "@walletconnect/sign-client"; import type { SignClientTypes, EngineTypes, ISignClient, } from "@walletconnect/types"; // eslint-disable-next-line @typescript-eslint/consistent-type-imports let WalletConnectModal: typeof import("@walletconnect/modal").WalletConnectModal; import("@walletconnect/modal").then((module) => { WalletConnectModal = module.WalletConnectModal; }); import type { SessionTypes } from "@walletconnect/types"; import type { EventEmitterService, Subscription, WalletEvents, } from "proximity-dex-core"; class WalletConnectClient { private client: Client; private emitter: EventEmitterService<WalletEvents>; private modal: typeof WalletConnectModal.prototype; async init(opts: SignClientTypes.Options) { this.client = await Client.init(opts); } constructor(emitter: EventEmitterService<WalletEvents>) { this.emitter = emitter; } get session(): ISignClient["session"] { return this.client.session; } on<Event extends SignClientTypes.Event>( event: Event, callback: (args: SignClientTypes.EventArguments[Event]) => void ): Subscription { this.client.on(event, callback); return { remove: () => this.client.removeListener(event, callback), }; } once<Event extends SignClientTypes.Event>( event: Event, callback: (args: SignClientTypes.EventArguments[Event]) => void ) { this.client.once(event, callback); } async connect( params: EngineTypes.ConnectParams, qrCodeModal: boolean, projectId: string, chainId: string ) { if (!this.modal) { this.modal = new WalletConnectModal({ projectId, chains: [chainId], explorerExcludedWalletIds: "ALL", }); } return new Promise<SessionTypes.Struct>((resolve, reject) => { this.client .connect(params) .then(({ uri, approval }) => { if (uri) { if (qrCodeModal) { this.modal.openModal({ uri, standaloneChains: [chainId], }); this.modal.subscribeModal(({ open }) => { if (!open) { reject(new Error("User cancelled pairing")); } }); } else { this.emitter.emit("uriChanged", { uri }); } } approval() .then(resolve) .catch(reject) .finally(() => this.modal.closeModal()); }) .catch(reject); }); } async request<Response>( params: EngineTypes.RequestParams ): Promise<Response> { console.log('🚨 [WC-CLIENT] request() called with:', { topic: params.topic, chainId: params.chainId, method: params.request.method, paramsKeys: Object.keys(params.request.params || {}), timestamp: new Date().toISOString(), }); // Check if the session is still active const session = this.client.session.get(params.topic); console.log('🚨 [WC-CLIENT] Session state:', { exists: !!session, topic: session?.topic, expiry: session ? new Date(session.expiry * 1000).toISOString() : 'N/A', peerName: session?.peer?.metadata?.name, connected: session?.acknowledged, }); // Check active listeners const eventNames = (this.client as any).events?.eventNames?.() || []; console.log('🚨 [WC-CLIENT] Active event listeners:', eventNames); console.log('🚨 [WC-CLIENT] About to call this.client.request()...'); try { // Add a race condition with a detailed timeout const requestPromise = this.client.request<Response>(params); const timeoutPromise = new Promise<never>((_, reject) => { setTimeout(() => { reject(new Error(`WalletConnect request timed out after 120 seconds. Method: ${params.request.method}. This usually means Fireblocks didn't respond.`)); }, 120000); // 2 minutes }); const result = await Promise.race([requestPromise, timeoutPromise]); console.log('🚨 [WC-CLIENT] request() completed successfully:', { method: params.request.method, resultType: typeof result, isArray: Array.isArray(result), timestamp: new Date().toISOString(), }); return result; } catch (error) { console.error('🚨 [WC-CLIENT] request() FAILED:', { method: params.request.method, error: error, errorMessage: error instanceof Error ? error.message : String(error), errorStack: error instanceof Error ? error.stack : undefined, timestamp: new Date().toISOString(), }); throw error; } } async disconnect(params: EngineTypes.DisconnectParams) { return this.client.disconnect(params); } } export default WalletConnectClient;