import { Adapter , BaseMessageSignerWalletAdapter , EventEmitter , scopePollingDetectionStrategy , SendTransactionOptions , WalletAccountError , WalletConnectionError , WalletDisconnectedError , WalletDisconnectionError , WalletError , WalletName , WalletNotConnectedError , WalletNotReadyError , WalletPublicKeyError , WalletReadyState , WalletSignTransactionError , WalletWindowClosedError , } from '@solana/wallet-adapter-base' ; import { Connection , PublicKey , SendOptions , Transaction , TransactionSignature } from '@solana/web3.js' ; interface PhantomWalletEvents { connect ( ... args ) : unknown ; disconnect ( ... args ) : unknown ; } interface PhantomWallet extends EventEmitter < PhantomWalletEvents > { isPhantom ? : boolean ; publicKey ? : { toBytes ( ) : Uint8Array ; } ; isConnected : boolean ; signTransaction ( transaction ) : Promise < Transaction > ; signAllTransactions ( transactions ) : Promise < Transaction [ ] > ; signAndSendTransaction ( transaction , options ? ) : Promise < { signature : TransactionSignature ; } > ; signMessage ( message ) : Promise < { signature : Uint8Array ; } > ; connect ( ) : Promise < void > ; disconnect ( ) : Promise < void > ; _handleDisconnect ( ... args ) : unknown ; } interface PhantomWindow extends Window { solana ? : PhantomWallet ; } declare const window ; export interface PhantomWalletAdapterConfig { } export const PhantomWalletName = 'Phantom' as WalletName ; export class PhantomWalletAdapter extends BaseMessageSignerWalletAdapter { name = PhantomWalletName ; url = 'https://phantom.app' ; icon = 'data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiBoZWlnaHQ9IjM0IiB3aWR0aD0iMzQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4MT0iLjUiIHgyPSIuNSIgeTE9IjAiIHkyPSIxIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1MzRiYjEiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM1NTFiZjkiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9Ii41IiB4Mj0iLjUiIHkxPSIwIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmZmIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii44MiIvPjwvbGluZWFyR3JhZGllbnQ+PGNpcmNsZSBjeD0iMTciIGN5PSIxNyIgZmlsbD0idXJsKCNhKSIgcj0iMTciLz48cGF0aCBkPSJtMjkuMTcwMiAxNy4yMDcxaC0yLjk5NjljMC02LjEwNzQtNC45NjgzLTExLjA1ODE3LTExLjA5NzUtMTEuMDU4MTctNi4wNTMyNSAwLTEwLjk3NDYzIDQuODI5NTctMTEuMDk1MDggMTAuODMyMzctLjEyNDYxIDYuMjA1IDUuNzE3NTIgMTEuNTkzMiAxMS45NDUzOCAxMS41OTMyaC43ODM0YzUuNDkwNiAwIDEyLjg0OTctNC4yODI5IDEzLjk5OTUtOS41MDEzLjIxMjMtLjk2MTktLjU1MDItMS44NjYxLTEuNTM4OC0xLjg2NjF6bS0xOC41NDc5LjI3MjFjMCAuODE2Ny0uNjcwMzggMS40ODQ3LTEuNDkwMDEgMS40ODQ3LS44MTk2NCAwLTEuNDg5OTgtLjY2ODMtMS40ODk5OC0xLjQ4NDd2LTIuNDAxOWMwLS44MTY3LjY3MDM0LTEuNDg0NyAxLjQ4OTk4LTEuNDg0Ny44MTk2MyAwIDEuNDkwMDEuNjY4IDEuNDkwMDEgMS40ODQ3em01LjE3MzggMGMwIC44MTY3LS42NzAzIDEuNDg0Ny0xLjQ4OTkgMS40ODQ3LS44MTk3IDAtMS40OS0uNjY4My0xLjQ5LTEuNDg0N3YtMi40MDE5YzAtLjgxNjcuNjcwNi0xLjQ4NDcgMS40OS0xLjQ4NDcuODE5NiAwIDEuNDg5OS42NjggMS40ODk5IDEuNDg0N3oiIGZpbGw9InVybCgjYikiLz48L3N2Zz4K' ; private _connecting : boolean ; private _wallet : PhantomWallet | null ; private _publicKey : PublicKey | null ; private _readyState : WalletReadyState = typeof window === 'undefined' || typeof document === 'undefined' ? WalletReadyState . Unsupported : WalletReadyState . NotDetected ; constructor ( config = { } ) { super ( ) ; this . _connecting = false ; this . _wallet = null ; this . _publicKey = null ; if ( this . _readyState !== WalletReadyState . Unsupported ) { scopePollingDetectionStrategy ( ( ) => { if ( window . solana ?. isPhantom ) { this . _readyState = WalletReadyState . Installed ; this . emit ( 'readyStateChange' , this . _readyState ) ; return true ; } return false ; } ) ; } } get publicKey ( ) : PublicKey | null { return this . _publicKey ; } get connecting ( ) : boolean { return this . _connecting ; } get connected ( ) : boolean { return ! ! this . _wallet ?. isConnected ; } get readyState ( ) : WalletReadyState { return this . _readyState ; } async connect ( ) { try { if ( this . connected || this . connecting ) return ; if ( this . _readyState !== WalletReadyState . Installed ) throw new WalletNotReadyError ( ) ; this . _connecting = true ; const wallet = window ! . solana ! ; if ( ! wallet . isConnected ) { const handleDisconnect = wallet . _handleDisconnect ; try { await new Promise < void > ( ( resolve , reject ) => { const connect = ( ) => { wallet . off ( 'connect' , connect ) ; resolve ( ) ; } ; wallet . _handleDisconnect = ( ... args ) => { wallet . off ( 'connect' , connect ) ; reject ( new WalletWindowClosedError ( ) ) ; return handleDisconnect . apply ( wallet , args ) ; } ; wallet . on ( 'connect' , connect ) ; wallet . connect ( ) . catch ( ( reason ) => { wallet . off ( 'connect' , connect ) ; reject ( reason ) ; } ) ; } ) ; } catch ( error ) { if ( error instanceof WalletError ) throw error ; throw new WalletConnectionError ( error ?. message , error ) ; } finally { wallet . _handleDisconnect = handleDisconnect ; } } if ( ! wallet . publicKey ) throw new WalletAccountError ( ) ; let publicKey ; try { publicKey = new PublicKey ( wallet . publicKey . toBytes ( ) ) ; } catch ( error ) { throw new WalletPublicKeyError ( error ?. message , error ) ; } wallet . on ( 'disconnect' , this . _disconnected ) ; this . _wallet = wallet ; this . _publicKey = publicKey ; this . emit ( 'connect' , publicKey ) ; } catch ( error ) { this . emit ( 'error' , error ) ; throw error ; } finally { this . _connecting = false ; } } async disconnect ( ) { const wallet = this . _wallet ; if ( wallet ) { wallet . off ( 'disconnect' , this . _disconnected ) ; this . _wallet = null ; this . _publicKey = null ; try { await wallet . disconnect ( ) ; } catch ( error ) { this . emit ( 'error' , new WalletDisconnectionError ( error ?. message , error ) ) ; } } this . emit ( 'disconnect' ) ; } async sendTransaction ( transaction , connection , options ? ) { try { const wallet = this . _wallet ; if ( wallet && 'signAndSendTransaction' in wallet && ! options ?. signers ) { transaction . feePayer = transaction . feePayer || this . publicKey || undefined ; transaction . recentBlockhash = transaction . recentBlockhash || ( await connection . getRecentBlockhash ( 'finalized' ) ) . blockhash ; const { signature } = await wallet . signAndSendTransaction ( transaction , options ) ; return signature ; } } catch ( error ) { this . emit ( 'error' , error ) ; throw error ; } return await super . sendTransaction ( transaction , connection , options ) ; } async signTransaction ( transaction ) { try { const wallet = this . _wallet ; if ( ! wallet ) throw new WalletNotConnectedError ( ) ; try { return ( await wallet . signTransaction ( transaction ) ) || transaction ; } catch ( error ) { throw new WalletSignTransactionError ( error ?. message , error ) ; } } catch ( error ) { this . emit ( 'error' , error ) ; throw error ; } } async signAllTransactions ( transactions ) { try { const wallet = this . _wallet ; if ( ! wallet ) throw new WalletNotConnectedError ( ) ; try { return ( await wallet . signAllTransactions ( transactions ) ) || transactions ; } catch ( error ) { throw new WalletSignTransactionError ( error ?. message , error ) ; } } catch ( error ) { this . emit ( 'error' , error ) ; throw error ; } } async signMessage ( message ) { try { const wallet = this . _wallet ; if ( ! wallet ) throw new WalletNotConnectedError ( ) ; try { const { signature } = await wallet . signMessage ( message ) ; return signature ; } catch ( error ) { throw new WalletSignTransactionError ( error ?. message , error ) ; } } catch ( error ) { this . emit ( 'error' , error ) ; throw error ; } } private _disconnected = ( ) => { const wallet = this . _wallet ; if ( wallet ) { wallet . off ( 'disconnect' , this . _disconnected ) ; this . _wallet = null ; this . _publicKey = null ; this . emit ( 'error' , new WalletDisconnectedError ( ) ) ; this . emit ( 'disconnect' ) ; } } ; }