import EventEmitter from 'eventemitter3'; import { PublicKey, Transaction } from '@solana/web3.js'; import { notify } from '../../utils/notifications'; import { WalletAdapter } from '@solana/wallet-base'; type PhantomEvent = 'disconnect' | 'connect'; type PhantomRequestMethod = | 'connect' | 'disconnect' | 'signTransaction' | 'signAllTransactions'; interface PhantomProvider { publicKey?: PublicKey; isConnected?: boolean; autoApprove?: boolean; signTransaction: (transaction: Transaction) => Promise; signAllTransactions: (transactions: Transaction[]) => Promise; connect: () => Promise; disconnect: () => Promise; on: (event: PhantomEvent, handler: (args: any) => void) => void; request: (method: PhantomRequestMethod, params: any) => Promise; } export class PhantomWalletAdapter extends EventEmitter implements WalletAdapter { _provider: PhantomProvider | undefined; _cachedCorrectKey?: PublicKey; constructor() { super(); this.connect = this.connect.bind(this); } get connected() { return this._provider?.isConnected || false; } get autoApprove() { return this._provider?.autoApprove || false; } async signAllTransactions( transactions: Transaction[], ): Promise { if (!this._provider) { return transactions; } return this._provider.signAllTransactions(transactions); } get publicKey() { // Due to weird phantom bug where their public key isnt quite like ours if (!this._cachedCorrectKey && this._provider?.publicKey) this._cachedCorrectKey = new PublicKey( this._provider.publicKey.toBase58(), ); return this._cachedCorrectKey || null; } async signTransaction(transaction: Transaction) { if (!this._provider) { return transaction; } return this._provider.signTransaction(transaction); } connect = async () => { if (this._provider) { return; } let provider: PhantomProvider; if ((window as any)?.solana?.isPhantom) { provider = (window as any).solana; } else { window.open('https://phantom.app/', '_blank'); notify({ message: 'Phantom Error', description: 'Please install Phantom wallet from Chrome ', }); return; } provider.on('connect', () => { this._provider = provider; this.emit('connect'); }); if (!provider.isConnected) { await provider.connect(); } this._provider = provider; this.emit('connect'); }; disconnect() { if (this._provider) { this._provider.disconnect(); this._provider = undefined; this.emit('disconnect'); } } }