// Both the studio and the example dapp use the same wallet selection rules. const ids = new WeakMap(); let nextId = 0; const chain = 'solana:devnet'; export function walletChoices(registry, capability, host = globalThis.window) { if (!host) return []; const choices = []; const feature = 'solana:' + capability; for (const wallet of registry.get()) { if (!wallet.chains.includes(chain) || !wallet.features['standard:connect'] || !wallet.features[feature]) continue; if (capability === 'signTransaction' && !wallet.features[feature].supportedTransactionVersions?.includes('legacy')) continue; if (!ids.has(wallet)) ids.set(wallet, 'standard-' + ++nextId); choices.push({id:ids.get(wallet),name:wallet.name,available:true,standard:wallet}); } for (const [id,name,provider] of [ ['phantom','Phantom',host.phantom?.solana ?? (host.solana?.isPhantom ? host.solana : null)], ['solflare','Solflare',host.solflare?.isSolflare ? host.solflare : null], ]) { if (!choices.some(choice=>choice.name.toLowerCase()===id)) choices.push({id,name,provider,available:typeof provider?.[capability]==='function'}); } return choices; } export async function openWallet(choice, capability) { if (!choice?.available) throw Error('Enable your wallet extension or open this page in its wallet browser.'); if (!choice.standard) { const p=choice.provider; await p.connect(); return { get address(){return p.publicKey?.toBase58();}, disconnect:()=>p.disconnect?.(), signMessage:async bytes=>{const signed=await p.signMessage(bytes,'utf8');return signed.signature ?? signed;}, signTransaction:tx=>p.signTransaction(tx), watch:fn=>{ p.on?.('accountChanged',fn);p.on?.('disconnect',fn); return ()=>{p.removeListener?.('accountChanged',fn);p.removeListener?.('disconnect',fn);}; }, }; } const w=choice.standard, feature='solana:'+capability; const {accounts}=await w.features['standard:connect'].connect(); const selected=accounts.find(a=>a.chains.includes(chain) && a.features.includes(feature)); if (!selected) throw Error('Choose an account that supports this action on Solana devnet.'); const account=()=>{ const current=w.accounts.find(a=>a.address===selected.address && a.chains.includes(chain) && a.features.includes(feature)); if (!current) throw Error('Wallet account changed. Reconnect to continue.'); return current; }; return { get address(){return w.accounts.find(a=>a.address===selected.address)?.address;}, disconnect:()=>w.features['standard:disconnect']?.disconnect(), watch:fn=>w.features['standard:events']?.on('change',event=>{if(event.accounts && !event.accounts.some(a=>a.address===selected.address)) fn();}) ?? (()=>{}), signMessage:async bytes=>{ const [result]=await w.features['solana:signMessage'].signMessage({account:account(),message:bytes}); if (result.signedMessage.length!==bytes.length || !bytes.every((v,i)=>result.signedMessage[i]===v)) throw Error('The signed message changed.'); return result.signature; }, signTransaction:async tx=>{ const [result]=await w.features['solana:signTransaction'].signTransaction({account:account(),chain, transaction:tx.serialize({requireAllSignatures:false,verifySignatures:false})}); return tx.constructor.from(result.signedTransaction); }, }; }