@usebutr/bitcoin 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{logWarn as e}from"@usebutr/core";import{buildAccount as t,discoverWalletStandard as n,getFeature as r,pickAccountByAddress as i,pickFirstAddress as a,slugify as o}from"@usebutr/wallet-standard-shared";const s=e=>({getBalance:!1,getTransactionReceipt:!1,requestAccounts:!1,sendTransaction:e.features.sendTransfer,signIn:!1,signMessage:e.features.signMessage,signTransaction:e.features.signPsbt,subscribe:e.features.events,switchAccount:!1,switchChain:e.chainCount>1}),c=`bip122:`,l=`bip122:000000000019d6689c085ae165831e93`,u=e=>o(`btc`,e),d=e=>e.chains.find(e=>e===l)||(e.chains.find(e=>e.startsWith(c))??null),f=(e,t)=>({id:e,name:t,namespace:`bip122`,reference:e.slice(7)}),p=(e,n)=>t(e,n),m=(t,n)=>{let o=d(t);if(!o)return null;let m=r(t,`standard:connect`);if(!m)return null;let h=r(t,`standard:disconnect`),g=r(t,`standard:events`),_=r(t,`bitcoin:signMessage`),v=r(t,`bitcoin:signPsbt`),y=r(t,`bitcoin:sendTransfer`),b=o,x=()=>f(b,t.name),S=new Set,C=()=>{if(t.accounts.length===0)return;let e=x(),n=t.accounts.map(t=>p(t.address,e)),r=n[0];if(r)for(let e of S)e({account:r,accounts:n,type:`accountChanged`})};return n?.(()=>{for(let e of S)e({type:`disconnected`})}),{capabilities:s({chainCount:t.chains.filter(e=>e.startsWith(c)).length,features:{events:!!g,sendTransfer:!!y,signMessage:!!_,signPsbt:!!v}}),chainPlatform:`bitcoin`,async connect(e){await m.connect(e?.silent?{silent:!0}:void 0)},async disconnect(){if(h)try{await h.disconnect()}catch(t){e(`[butr] Bitcoin Wallet Standard disconnect threw:`,t)}},getAccount(){let e=a(t.accounts);return e?Promise.resolve(p(e,x())):Promise.resolve(null)},getAccounts(){let e=x();return Promise.resolve(t.accounts.map(t=>p(t.address,e)))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(t)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:t.icon,id:u(t.name),name:t.name,async requestAccounts(){await m.connect()},async sendTx(e,n){if(!y)throw Error(`Wallet ${t.name} does not advertise bitcoin:sendTransfer`);if(!e||typeof e!=`object`||typeof e.amount!=`bigint`||typeof e.recipient!=`string`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — pass the recipient address and an amount in satoshis`);let{amount:r,recipient:a}=e,o=n?i(t.accounts,n.walletAddress):t.accounts[0]??null;if(!o)throw Error(`No connected account`);return(await y.sendTransfer({account:o,amount:r,chain:b,recipient:a})).txid},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e,n)},async signMessage(e,n){if(!_)throw Error(`Wallet ${t.name} does not advertise bitcoin:signMessage`);let r=n?i(t.accounts,n.walletAddress):t.accounts[0]??null;if(!r)throw Error(`No connected account`);let a=await _.signMessage({account:r,message:e});return{signature:a.signature,signedMessage:a.signedMessage}},...v?{async signTransaction(e,n){let r=n?i(t.accounts,n.walletAddress):t.accounts[0]??null;if(!r)throw Error(`No connected account`);if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return(await v.signPsbt({account:r,chain:b,psbt:e})).signedPsbt}}:{},subscribe(e){S.add(e);let t=null;if(g){let n=g.on(`change`,t=>{if(t.chains){let e=t.chains.find(e=>e===l)??t.chains.find(e=>e.startsWith(c));e&&(b=e)}if(t.accounts){if(t.accounts.length===0){e({type:`disconnected`});return}let n=x(),r=t.accounts.map(e=>p(e.address,n)),i=r[0];if(!i)return;e({account:i,accounts:r,type:`accountChanged`});return}t.chains&&C()});t=()=>n()}return()=>{S.delete(e),t?.()}},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);if(!t.chains.includes(e.id))throw Error(`Wallet ${t.name} does not advertise chain "${e.id}". Available: ${t.chains.join(`, `)}`);return b=e.id,C(),Promise.resolve()}}},h=e=>n(e,(e,t)=>m(e,t)),g={mainnet:{id:`bip122:000000000019d6689c085ae165831e93`,name:`Bitcoin`,namespace:`bip122`,reference:`000000000019d6689c085ae165831e93`},signet:{id:`bip122:00000008819873e925422c1ff0f99f7c`,name:`Bitcoin Signet`,namespace:`bip122`,reference:`00000008819873e925422c1ff0f99f7c`},testnet:{id:`bip122:000000000933ea01ad0ee984209779ba`,name:`Bitcoin Testnet`,namespace:`bip122`,reference:`000000000933ea01ad0ee984209779ba`}},_=Object.values(g),v=`data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2Y3OTMxYSIgc3Ryb2tlPSJub25lIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+QjwvdGV4dD48L3N2Zz4=`,y={getBalance:!1,getTransactionReceipt:!1,requestAccounts:!0,sendTransaction:!0,signIn:!1,signMessage:!0,signTransaction:!0,subscribe:!1,switchAccount:!1,switchChain:!1},b=e=>{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.codePointAt(e)??0;return n},x=e=>{let t=``;for(let n of e)t+=String.fromCodePoint(n);return btoa(t)},S=(e,n,r)=>{let i=g.mainnet,a=[],o=async(e,t)=>{let n=await r.request(e,t);if(n.error)throw Error(`[butr/bitcoin] sats-connect ${e} failed: ${n.error.message}`);return n.result},s=async()=>{let e=await o(`getAccounts`,{message:`Connect to butr`,purposes:[`payment`,`ordinals`]});if(!e?.addresses)return[];let t=e.addresses.map(e=>e.address);return a=t,t};return{capabilities:y,chainPlatform:`bitcoin`,async connect(){await s()},disconnect(){return a=[],Promise.resolve()},async getAccount(){let e=a[0];if(e)return t(e,i);let n=(await s())[0];return n?t(n,i):null},async getAccounts(){return(a.length>0?a:await s()).map(e=>t(e,i))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(r)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:v,id:e,name:n,async requestAccounts(){await s()},async sendTx(e){if(!e||typeof e!=`object`||typeof e.recipient!=`string`||typeof e.amount!=`bigint`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis`);let{amount:t,recipient:n}=e;return(await o(`sendTransfer`,{recipients:[{address:n,amount:t.toString()}]})).txid},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e)},async signMessage(e){let t=a[0];if(!t)throw Error(`No connected account`);return{signature:b((await o(`signMessage`,{address:t,message:new TextDecoder().decode(e)})).signature),signedMessage:e}},async signTransaction(e){if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return b((await o(`signPsbt`,{psbt:x(e)})).psbt)},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);return i=e,Promise.resolve()}}},C={getBalance:!1,getTransactionReceipt:!1,requestAccounts:!0,sendTransaction:!0,signIn:!1,signMessage:!0,signTransaction:!0,subscribe:!0,switchAccount:!1,switchChain:!1},w=e=>{let t=``;for(let n of e)t+=n.toString(16).padStart(2,`0`);return t},T=e=>{let t=e.startsWith(`0x`)?e.slice(2):e,n=new Uint8Array(t.length/2);for(let e=0;e<n.length;e+=1)n[e]=Number.parseInt(t.slice(e*2,e*2+2),16);return n},E=e=>{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.codePointAt(e)??0;return n},D=(e,n,r)=>{let i=g.mainnet,a=new Set,o=async()=>{if(typeof r.getNetwork==`function`)try{let e=await r.getNetwork();i=e===`testnet`?g.testnet:e===`signet`?g.signet:g.mainnet}catch{}};return{capabilities:C,chainPlatform:`bitcoin`,async connect(e){if(e?.silent){if((await r.getAccounts()).length===0)throw Error(`No authorized accounts for silent reconnect`);await o();return}await r.requestAccounts(),await o()},disconnect(){return Promise.resolve()},async getAccount(){let e=(await r.getAccounts())[0];return e?(await o(),t(e,i)):null},async getAccounts(){let e=await r.getAccounts();return e.length===0?[]:(await o(),e.map(e=>t(e,i)))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(r)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:v,id:e,name:n,async requestAccounts(){await r.requestAccounts(),await o()},sendTx(e){if(typeof r.sendBitcoin!=`function`)throw TypeError(`Wallet ${n} does not expose sendBitcoin`);if(!e||typeof e!=`object`||typeof e.recipient!=`string`||typeof e.amount!=`bigint`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis`);let{amount:t,recipient:i}=e,a=Number(t);return r.sendBitcoin(i,a)},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e)},async signMessage(e){let t=new TextDecoder().decode(e);return{signature:E(await r.signMessage(t)),signedMessage:e}},async signTransaction(e){if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return T(await r.signPsbt(w(e)))},subscribe(e){a.add(e);let n=(...n)=>{let r=n[0]??[];if(r.length===0){e({type:`disconnected`});return}let a=r.map(e=>t(e,i)),o=a[0];o&&e({account:o,accounts:a,type:`accountChanged`})},s=()=>{o()};return r.on?.(`accountsChanged`,n),r.on?.(`networkChanged`,s),()=>{r.removeListener?.(`accountsChanged`,n),r.removeListener?.(`networkChanged`,s),a.delete(e)}},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);return i=e,o(),Promise.resolve()}}},O=e=>e===void 0?typeof window>`u`?null:window:e,k=e=>{let t=[],n=new Set;e.unisat&&!n.has(e.unisat)&&(n.add(e.unisat),t.push(D(`injected:bitcoin:unisat`,`Unisat`,e.unisat)));let r=e.okxwallet?.bitcoin;r&&!n.has(r)&&(n.add(r),t.push(D(`injected:bitcoin:okx`,`OKX Wallet (Bitcoin)`,r)));let i=e.XverseProviders?.BitcoinProvider;return i&&!n.has(i)&&(n.add(i),t.push(S(`injected:bitcoin:xverse`,`Xverse`,i))),e.btc&&!n.has(e.btc)&&(n.add(e.btc),t.push(D(`injected:bitcoin:legacy`,`Browser Bitcoin wallet`,e.btc))),t},A=(e,t={})=>{let n=t.settleMs??150,r=!1,i=setTimeout(()=>{if(r||t.hasAnyWalletStandardAdapter?.())return;let n=O(t.target);if(!n)return;let i=k(n);for(let t of i)e(t)},n);return()=>{r=!0,clearTimeout(i)}},j={fallback:{subscribe:(e,t)=>A(e,{hasAnyWalletStandardAdapter:t.hasAnyPrimaryAdapter})},platform:`bitcoin`,subscribe:h};export{g as BITCOIN_CHAINS,_ as BITCOIN_CHAINS_LIST,v as GENERIC_BITCOIN_ICON,j as bitcoinDiscoverer,m as buildBitcoinAdapter,h as discoverBitcoinAdapters,A as discoverInjectedBitcoinAdapter,s as resolveBitcoinCapabilities,u as slugify};
|
|
1
|
+
import{logWarn as e,sanitizeIcon as t}from"@usebutr/core";import{buildAccount as n,discoverWalletStandard as r,getFeature as i,pickAccountByAddress as a,pickFirstAddress as o,slugify as s}from"@usebutr/wallet-standard-shared";const c=e=>({getBalance:!1,getTransactionReceipt:!1,requestAccounts:!1,sendTransaction:e.features.sendTransfer,signIn:!1,signMessage:e.features.signMessage,signTransaction:e.features.signPsbt,subscribe:e.features.events,switchAccount:!1,switchChain:e.chainCount>1}),l=`bip122:`,u=`bip122:000000000019d6689c085ae165831e93`,d=e=>s(`btc`,e),f=e=>e.chains.find(e=>e===u)||(e.chains.find(e=>e.startsWith(l))??null),p=(e,t)=>({id:e,name:t,namespace:`bip122`,reference:e.slice(7)}),m=(e,t)=>n(e,t),h=(n,r)=>{let s=f(n);if(!s)return null;let h=i(n,`standard:connect`);if(!h)return null;let g=i(n,`standard:disconnect`),_=i(n,`standard:events`),v=i(n,`bitcoin:signMessage`),y=i(n,`bitcoin:signPsbt`),b=i(n,`bitcoin:sendTransfer`),x=s,S=()=>p(x,n.name),C=new Set,w=()=>{if(n.accounts.length===0)return;let e=S(),t=n.accounts.map(t=>m(t.address,e)),r=t[0];if(r)for(let e of C)e({account:r,accounts:t,type:`accountChanged`})};return r?.(()=>{for(let e of C)e({type:`disconnected`})}),{capabilities:c({chainCount:n.chains.filter(e=>e.startsWith(l)).length,features:{events:!!_,sendTransfer:!!b,signMessage:!!v,signPsbt:!!y}}),chainPlatform:`bitcoin`,async connect(e){await h.connect(e?.silent?{silent:!0}:void 0)},async disconnect(){if(g)try{await g.disconnect()}catch(t){e(`[butr] Bitcoin Wallet Standard disconnect threw:`,t)}},getAccount(){let e=o(n.accounts);return e?Promise.resolve(m(e,S())):Promise.resolve(null)},getAccounts(){let e=S();return Promise.resolve(n.accounts.map(t=>m(t.address,e)))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(n)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:t(n.icon),id:d(n.name),name:n.name,async requestAccounts(){await h.connect()},async sendTx(e,t){if(!b)throw Error(`Wallet ${n.name} does not advertise bitcoin:sendTransfer`);if(!e||typeof e!=`object`||typeof e.amount!=`bigint`||typeof e.recipient!=`string`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — pass the recipient address and an amount in satoshis`);let{amount:r,recipient:i}=e,o=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!o)throw Error(`No connected account`);return(await b.sendTransfer({account:o,amount:r,chain:x,recipient:i})).txid},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e,n)},async signMessage(e,t){if(!v)throw Error(`Wallet ${n.name} does not advertise bitcoin:signMessage`);let r=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!r)throw Error(`No connected account`);let i=await v.signMessage({account:r,message:e});return{signature:i.signature,signedMessage:i.signedMessage}},...y?{async signTransaction(e,t){let r=t?a(n.accounts,t.walletAddress):n.accounts[0]??null;if(!r)throw Error(`No connected account`);if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return(await y.signPsbt({account:r,chain:x,psbt:e})).signedPsbt}}:{},subscribe(e){C.add(e);let t=null;if(_){let n=_.on(`change`,t=>{if(t.chains){let e=t.chains.find(e=>e===u)??t.chains.find(e=>e.startsWith(l));e&&(x=e)}if(t.accounts){if(t.accounts.length===0){e({type:`disconnected`});return}let n=S(),r=t.accounts.map(e=>m(e.address,n)),i=r[0];if(!i)return;e({account:i,accounts:r,type:`accountChanged`});return}t.chains&&w()});t=()=>n()}return()=>{C.delete(e),t?.()}},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);if(!n.chains.includes(e.id))throw Error(`Wallet ${n.name} does not advertise chain "${e.id}". Available: ${n.chains.join(`, `)}`);return x=e.id,w(),Promise.resolve()}}},g=e=>r(e,(e,t)=>h(e,t)),_={mainnet:{id:`bip122:000000000019d6689c085ae165831e93`,name:`Bitcoin`,namespace:`bip122`,reference:`000000000019d6689c085ae165831e93`},signet:{id:`bip122:00000008819873e925422c1ff0f99f7c`,name:`Bitcoin Signet`,namespace:`bip122`,reference:`00000008819873e925422c1ff0f99f7c`},testnet:{id:`bip122:000000000933ea01ad0ee984209779ba`,name:`Bitcoin Testnet`,namespace:`bip122`,reference:`000000000933ea01ad0ee984209779ba`}},v=Object.values(_),y=`data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2Y3OTMxYSIgc3Ryb2tlPSJub25lIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+QjwvdGV4dD48L3N2Zz4=`,b={getBalance:!1,getTransactionReceipt:!1,requestAccounts:!0,sendTransaction:!0,signIn:!1,signMessage:!0,signTransaction:!0,subscribe:!1,switchAccount:!1,switchChain:!1},x=e=>{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.codePointAt(e)??0;return n},S=e=>{let t=``;for(let n of e)t+=String.fromCodePoint(n);return btoa(t)},C=(e,t,r)=>{let i=_.mainnet,a=[],o=async(e,t)=>{let n=await r.request(e,t);if(n.error)throw Error(`[butr/bitcoin] sats-connect ${e} failed: ${n.error.message}`);return n.result},s=async()=>{let e=await o(`getAccounts`,{message:`Connect to butr`,purposes:[`payment`,`ordinals`]});if(!e?.addresses)return[];let t=e.addresses.map(e=>e.address);return a=t,t};return{capabilities:b,chainPlatform:`bitcoin`,async connect(){await s()},disconnect(){return a=[],Promise.resolve()},async getAccount(){let e=a[0];if(e)return n(e,i);let t=(await s())[0];return t?n(t,i):null},async getAccounts(){return(a.length>0?a:await s()).map(e=>n(e,i))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(r)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:y,id:e,name:t,async requestAccounts(){await s()},async sendTx(e){if(!e||typeof e!=`object`||typeof e.recipient!=`string`||typeof e.amount!=`bigint`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis`);let{amount:t,recipient:n}=e;return(await o(`sendTransfer`,{recipients:[{address:n,amount:t.toString()}]})).txid},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e)},async signMessage(e){let t=a[0];if(!t)throw Error(`No connected account`);return{signature:x((await o(`signMessage`,{address:t,message:new TextDecoder().decode(e)})).signature),signedMessage:e}},async signTransaction(e){if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return x((await o(`signPsbt`,{psbt:S(e)})).psbt)},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);return i=e,Promise.resolve()}}},w={getBalance:!1,getTransactionReceipt:!1,requestAccounts:!0,sendTransaction:!0,signIn:!1,signMessage:!0,signTransaction:!0,subscribe:!0,switchAccount:!1,switchChain:!1},T=e=>{let t=``;for(let n of e)t+=n.toString(16).padStart(2,`0`);return t},E=e=>{let t=e.startsWith(`0x`)?e.slice(2):e,n=new Uint8Array(t.length/2);for(let e=0;e<n.length;e+=1)n[e]=Number.parseInt(t.slice(e*2,e*2+2),16);return n},D=e=>{let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e+=1)n[e]=t.codePointAt(e)??0;return n},O=(e,t,r)=>{let i=_.mainnet,a=new Set,o=async()=>{if(typeof r.getNetwork==`function`)try{let e=await r.getNetwork();i=e===`testnet`?_.testnet:e===`signet`?_.signet:_.mainnet}catch{}};return{capabilities:w,chainPlatform:`bitcoin`,async connect(e){if(e?.silent){if((await r.getAccounts()).length===0)throw Error(`No authorized accounts for silent reconnect`);await o();return}await r.requestAccounts(),await o()},disconnect(){return Promise.resolve()},async getAccount(){let e=(await r.getAccounts())[0];return e?(await o(),n(e,i)):null},async getAccounts(){let e=await r.getAccounts();return e.length===0?[]:(await o(),e.map(e=>n(e,i)))},getBalance(){return Promise.resolve({decimals:8,formatted:`0`,symbol:`BTC`,value:0n})},getSigner(){return Promise.resolve(r)},getTransactionReceipt(){return Promise.resolve({status:`Pending`})},icon:y,id:e,name:t,async requestAccounts(){await r.requestAccounts(),await o()},sendTx(e){if(typeof r.sendBitcoin!=`function`)throw TypeError(`Wallet ${t} does not expose sendBitcoin`);if(!e||typeof e!=`object`||typeof e.recipient!=`string`||typeof e.amount!=`bigint`)throw TypeError(`Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis`);let{amount:n,recipient:i}=e,a=Number(n);return r.sendBitcoin(i,a)},sendTxToChain(e,t,n,r){return r?.(),this.sendTx(e)},async signMessage(e){let t=new TextDecoder().decode(e);return{signature:D(await r.signMessage(t)),signedMessage:e}},async signTransaction(e){if(!(e instanceof Uint8Array))throw TypeError(`Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())`);return E(await r.signPsbt(T(e)))},subscribe(e){a.add(e);let t=(...t)=>{let r=t[0]??[];if(r.length===0){e({type:`disconnected`});return}let a=r.map(e=>n(e,i)),o=a[0];o&&e({account:o,accounts:a,type:`accountChanged`})},s=()=>{o()};return r.on?.(`accountsChanged`,t),r.on?.(`networkChanged`,s),()=>{r.removeListener?.(`accountsChanged`,t),r.removeListener?.(`networkChanged`,s),a.delete(e)}},switchChain(e){if(e.namespace!==`bip122`)throw Error(`Bitcoin adapter received non-Bitcoin chain "${e.id}". Pass a chain with namespace "bip122".`);return i=e,o(),Promise.resolve()}}},k=e=>e===void 0?typeof window>`u`?null:window:e,A=e=>{let t=[],n=new Set;e.unisat&&!n.has(e.unisat)&&(n.add(e.unisat),t.push(O(`injected:bitcoin:unisat`,`Unisat`,e.unisat)));let r=e.okxwallet?.bitcoin;r&&!n.has(r)&&(n.add(r),t.push(O(`injected:bitcoin:okx`,`OKX Wallet (Bitcoin)`,r)));let i=e.XverseProviders?.BitcoinProvider;return i&&!n.has(i)&&(n.add(i),t.push(C(`injected:bitcoin:xverse`,`Xverse`,i))),e.btc&&!n.has(e.btc)&&(n.add(e.btc),t.push(O(`injected:bitcoin:legacy`,`Browser Bitcoin wallet`,e.btc))),t},j=(e,t={})=>{let n=t.settleMs??150,r=!1,i=setTimeout(()=>{if(r||t.hasAnyWalletStandardAdapter?.())return;let n=k(t.target);if(!n)return;let i=A(n);for(let t of i)e(t)},n);return()=>{r=!0,clearTimeout(i)}},M={fallback:{subscribe:(e,t)=>j(e,{hasAnyWalletStandardAdapter:t.hasAnyPrimaryAdapter})},platform:`bitcoin`,subscribe:g};export{_ as BITCOIN_CHAINS,v as BITCOIN_CHAINS_LIST,y as GENERIC_BITCOIN_ICON,M as bitcoinDiscoverer,h as buildBitcoinAdapter,g as discoverBitcoinAdapters,j as discoverInjectedBitcoinAdapter,c as resolveBitcoinCapabilities,d as slugify};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["kitSlugify","base64ToBytes"],"sources":["../src/capabilities.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/injected/icon.ts","../src/injected/sats-connect.ts","../src/injected/unisat.ts","../src/injected/index.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\ntype BitcoinCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n sendTransfer: boolean;\n signMessage: boolean;\n signPsbt: boolean;\n };\n};\n\n/**\n * Bitcoin capability mapping.\n *\n * - `sendTransaction = bitcoin:sendTransfer present`. The wallet handles\n * UTXO selection, fee estimation, signing, and broadcast.\n * - `signTransaction = bitcoin:signPsbt present`. Sign-only PSBT path\n * for consumers that build their own UTXO-shaped transactions with\n * `bitcoinjs-lib` and broadcast through their own provider.\n * - `signMessage = bitcoin:signMessage present`.\n * - `signIn = false`. No Sign-In-With-Bitcoin standard yet (BIP-322 is\n * message-signing oriented, not auth).\n * - `subscribe = events present`. Most Bitcoin wallets don't emit\n * change events portably; capabilities admits the truth.\n * - `switchChain = false`. No portable per-call switch RPC across\n * Bitcoin wallets — Xverse/Unisat/Phantom each pick their own network.\n */\nconst resolveBitcoinCapabilities = (input: BitcoinCapabilityInput): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: input.features.sendTransfer,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: input.features.signPsbt,\n subscribe: input.features.events,\n switchAccount: false,\n switchChain: input.chainCount > 1,\n});\n\nexport type { BitcoinCapabilityInput };\nexport { resolveBitcoinCapabilities };\n","import type { Account, ChainBase, ConnectorEvent, WalletAdapter } from \"@usebutr/core\";\nimport { logWarn } from \"@usebutr/core\";\nimport {\n buildAccount,\n getFeature,\n pickAccountByAddress,\n pickFirstAddress,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type {\n StandardConnectFeature,\n StandardDisconnectFeature,\n StandardEventsFeature,\n WalletStandardWallet,\n} from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveBitcoinCapabilities } from \"./capabilities\";\nimport type {\n BitcoinSendTransferFeature,\n BitcoinSignMessageFeature,\n BitcoinSignPsbtFeature,\n} from \"./wallet-standard-types\";\n\nconst BITCOIN_PREFIX = \"bip122:\";\nconst BITCOIN_DECIMALS = 8;\nconst BITCOIN_MAINNET_ID = \"bip122:000000000019d6689c085ae165831e93\";\n\nconst slugify = (name: string): string => kitSlugify(\"btc\", name);\n\nconst pickBitcoinChain = (wallet: WalletStandardWallet): string | null => {\n const mainnet = wallet.chains.find((c) => c === BITCOIN_MAINNET_ID);\n if (mainnet) {\n return mainnet;\n }\n return wallet.chains.find((c) => c.startsWith(BITCOIN_PREFIX)) ?? null;\n};\n\nconst buildBitcoinChain = (chainId: string, walletName: string): ChainBase => ({\n id: chainId,\n // Same posture as EVM/SVM/Sui: butr ships no chain-id → name table.\n name: walletName,\n namespace: \"bip122\",\n reference: chainId.slice(BITCOIN_PREFIX.length),\n});\n\nconst buildBitcoinAccount = (address: string, chain: ChainBase): Account =>\n buildAccount(address, chain);\n\n/**\n * Adapt a Bitcoin Wallet Standard `Wallet` into a butr `WalletAdapter`.\n *\n * Returns `null` if the wallet doesn't advertise any `bip122:` chain or\n * doesn't expose `standard:connect`. Same posture as the SVM/Sui\n * adapters: gate features on what each wallet advertises, return\n * placeholders for RPC reads, forward `subscribe` through\n * `standard:events`.\n *\n * **Known limitations**\n *\n * - `getBalance` returns `{ value: 0n, symbol: \"BTC\" }`. Bitcoin\n * balance lookups require an Esplora/Electrum/RPC client outside\n * butr's scope.\n * - `getTransactionReceipt` returns `\"Pending\"` for the same reason.\n * - `sendTx` expects the consumer to pass `{ amount: bigint, recipient: string }`\n * via butr's `unknown` tx parameter — the simplest mental model that\n * maps onto `bitcoin:sendTransfer`. PSBT-shaped flows go through\n * `signTransaction`.\n * - `signTransaction` expects a `Uint8Array` PSBT (raw bytes) — the\n * same shape `bitcoin:signPsbt` accepts. Consumers building with\n * `bitcoinjs-lib` get bytes via `psbt.toBuffer()`.\n * - `switchChain` is local-state-only; the capability flag is `false`\n * when only one chain is advertised. Wallets that ship a real switch\n * primitive (none today, portably) would need their own adapter.\n */\nconst buildBitcoinAdapter = (\n wallet: WalletStandardWallet,\n /** Optional. Called with a function that pushes a synthetic\n * `disconnected` event to all current subscribers. The discovery\n * layer invokes it on Wallet Standard `unregister`. */\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const bitcoinChainId = pickBitcoinChain(wallet);\n if (!bitcoinChainId) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\n return null;\n }\n\n const disconnect = getFeature<StandardDisconnectFeature>(wallet, \"standard:disconnect\");\n const events = getFeature<StandardEventsFeature>(wallet, \"standard:events\");\n const signMessage = getFeature<BitcoinSignMessageFeature>(wallet, \"bitcoin:signMessage\");\n const signPsbt = getFeature<BitcoinSignPsbtFeature>(wallet, \"bitcoin:signPsbt\");\n const sendTransfer = getFeature<BitcoinSendTransferFeature>(wallet, \"bitcoin:sendTransfer\");\n\n let currentChainId = bitcoinChainId;\n const currentChain = (): ChainBase => buildBitcoinChain(currentChainId, wallet.name);\n\n const listeners = new Set<(event: ConnectorEvent) => void>();\n const notifyAccountChanged = () => {\n if (wallet.accounts.length === 0) {\n return;\n }\n const chain = currentChain();\n const built = wallet.accounts.map((a) => buildBitcoinAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n for (const listener of listeners) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n };\n\n registerDisconnector?.(() => {\n for (const listener of listeners) {\n listener({ type: \"disconnected\" });\n }\n });\n\n return {\n capabilities: resolveBitcoinCapabilities({\n chainCount: wallet.chains.filter((c) => c.startsWith(BITCOIN_PREFIX)).length,\n features: {\n events: Boolean(events),\n sendTransfer: Boolean(sendTransfer),\n signMessage: Boolean(signMessage),\n signPsbt: Boolean(signPsbt),\n },\n }),\n chainPlatform: \"bitcoin\",\n\n async connect(opts) {\n await connect.connect(opts?.silent ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\n try {\n await disconnect.disconnect();\n } catch (error) {\n logWarn(\"[butr] Bitcoin Wallet Standard disconnect threw:\", error);\n }\n }\n },\n\n getAccount() {\n const address = pickFirstAddress(wallet.accounts);\n if (!address) {\n return Promise.resolve(null);\n }\n return Promise.resolve(buildBitcoinAccount(address, currentChain()));\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildBitcoinAccount(a.address, chain)));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: BITCOIN_DECIMALS,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n // Consumers cast to whatever Bitcoin signing wrapper they use\n // (bitcoinjs-lib's Signer, scure-btc-signer's HDWallet, etc.) or\n // call butr's adapter directly for PSBT / send-transfer.\n return Promise.resolve(wallet);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: wallet.icon,\n id: slugify(wallet.name),\n name: wallet.name,\n\n async requestAccounts() {\n await connect.connect();\n },\n\n async sendTx(tx, account) {\n if (!sendTransfer) {\n throw new Error(`Wallet ${wallet.name} does not advertise bitcoin:sendTransfer`);\n }\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — pass the recipient address and an amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await sendTransfer.sendTransfer({\n account: wsAccount,\n amount,\n chain: currentChainId,\n recipient,\n });\n return output.txid;\n },\n\n sendTxToChain(tx, _targetChainId, account, cb) {\n cb?.();\n return this.sendTx(tx, account);\n },\n\n async signMessage(msg, account) {\n if (!signMessage) {\n throw new Error(`Wallet ${wallet.name} does not advertise bitcoin:signMessage`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await signMessage.signMessage({ account: wsAccount, message: msg });\n return { signature: output.signature, signedMessage: output.signedMessage };\n },\n\n ...(signPsbt\n ? {\n async signTransaction(tx, account) {\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n const output = await signPsbt.signPsbt({\n account: wsAccount,\n chain: currentChainId,\n psbt: tx,\n });\n return output.signedPsbt;\n },\n }\n : {}),\n\n subscribe(listener) {\n listeners.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (events) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.chains) {\n const next =\n changes.chains.find((c) => c === BITCOIN_MAINNET_ID) ??\n changes.chains.find((c) => c.startsWith(BITCOIN_PREFIX));\n if (next) {\n currentChainId = next;\n }\n }\n\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildBitcoinAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n return;\n }\n\n if (changes.chains) {\n notifyAccountChanged();\n }\n });\n unsubWallet = () => unsub();\n }\n return () => {\n listeners.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain(chain) {\n if (chain.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${chain.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n if (!wallet.chains.includes(chain.id)) {\n throw new Error(\n `Wallet ${wallet.name} does not advertise chain \"${chain.id}\". Available: ${wallet.chains.join(\", \")}`,\n );\n }\n currentChainId = chain.id;\n notifyAccountChanged();\n return Promise.resolve();\n },\n };\n};\n\nexport { buildBitcoinAdapter, slugify };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport { discoverWalletStandard } from \"@usebutr/wallet-standard-shared\";\n\nimport { buildBitcoinAdapter } from \"./wallet-standard-adapter\";\n\n/**\n * Subscribe to Bitcoin Wallet Standard announcements.\n *\n * Phantom (Bitcoin), Magic Eden, OKX Wallet (Bitcoin), and Leather\n * advertise `bitcoin:*` features over the same `getWallets()` bus that\n * SVM and Sui consume. `buildBitcoinAdapter` returns `null` for wallets\n * that don't advertise any `bip122:` chain, so multi-chain wallets\n * (Phantom: EVM + SVM + Sui + Bitcoin) produce one adapter per platform.\n *\n * Requires the **optional peer dependency** `@wallet-standard/app`.\n *\n * The discovery loop (dynamic import, dedupe, register / unregister\n * bridge) lives in `@usebutr/wallet-standard-shared`.\n */\nconst discoverBitcoinAdapters = (onAdapter: (adapter: WalletAdapter) => void): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildBitcoinAdapter(wallet, registerDisconnector),\n );\n\nexport { discoverBitcoinAdapters };\n","import type { ChainBase } from \"@usebutr/core\";\n\n/**\n * CAIP-2 Bitcoin chain references use the first 8 bytes (big-endian)\n * of each network's genesis block hash. These string ids are what\n * Bitcoin Wallet Standard wallets (Phantom, Magic Eden, OKX) advertise\n * in `wallet.chains`; the adapter's `switchChain` rejects anything else.\n *\n * - Mainnet: `bip122:000000000019d6689c085ae165831e93`\n * - Testnet: `bip122:000000000933ea01ad0ee984209779ba`\n * - Signet: `bip122:00000008819873e925422c1ff0f99f7c`\n *\n * Bitcoin has no per-call \"switch chain\" RPC across the major wallets,\n * so butr's adapter treats chain as a wallet-side configuration —\n * `switchChain` updates local state to influence subsequent calls (same\n * posture as SVM). Bitcoin's `switchChain` capability is `false` by\n * default; consumers building on top can opt in if their wallet exposes\n * a switch primitive.\n */\nconst BITCOIN_CHAINS = {\n mainnet: {\n id: \"bip122:000000000019d6689c085ae165831e93\",\n name: \"Bitcoin\",\n namespace: \"bip122\",\n reference: \"000000000019d6689c085ae165831e93\",\n },\n signet: {\n id: \"bip122:00000008819873e925422c1ff0f99f7c\",\n name: \"Bitcoin Signet\",\n namespace: \"bip122\",\n reference: \"00000008819873e925422c1ff0f99f7c\",\n },\n testnet: {\n id: \"bip122:000000000933ea01ad0ee984209779ba\",\n name: \"Bitcoin Testnet\",\n namespace: \"bip122\",\n reference: \"000000000933ea01ad0ee984209779ba\",\n },\n} as const satisfies Record<string, ChainBase>;\n\nconst BITCOIN_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(BITCOIN_CHAINS);\n\nexport { BITCOIN_CHAINS, BITCOIN_CHAINS_LIST };\n","/**\n * Generic Bitcoin wallet icon — same purse SVG style as the EVM\n * package, recoloured. Inline so the picker doesn't flash.\n *\n * Lives in its own file because both injected adapters (UniSat-shape\n * and sats-connect) need the same fallback when the wallet doesn't\n * advertise its own icon, and there's no other \"shared\" thing they\n * both want — a one-line module beats a grab-bag.\n */\nconst GENERIC_BITCOIN_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2Y3OTMxYSIgc3Ryb2tlPSJub25lIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+QjwvdGV4dD48L3N2Zz4=\";\n\nexport { GENERIC_BITCOIN_ICON };\n","import type { ChainBase, WalletAdapter, WalletCapabilities } from \"@usebutr/core\";\nimport { buildAccount } from \"@usebutr/wallet-standard-shared\";\n\nimport { BITCOIN_CHAINS } from \"../chains\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\n\n/** sats-connect (Xverse) shape — a JSON-RPC-ish `request(method, params)`. */\ntype SatsConnectProvider = {\n request(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<{ error?: { message: string }; result?: unknown }>;\n};\n\nconst CAPS_SATS_CONNECT: WalletCapabilities = {\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: true,\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: true,\n subscribe: false,\n switchAccount: false,\n switchChain: false,\n};\n\n// Encoding helpers — small enough to live next to their caller rather\n// than in a cross-cutting \"shared\" file.\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCodePoint(byte);\n }\n return btoa(binary);\n};\n\n/**\n * Wrap an Xverse-style `BitcoinProvider` (sats-connect) into a butr\n * `WalletAdapter`. sats-connect routes everything through a single\n * `request(method, params)` RPC; we shim each butr capability onto the\n * corresponding sats-connect method.\n *\n * Tested against Xverse's `getAccounts`, `signMessage`, `signPsbt`,\n * `sendTransfer` methods.\n */\nconst buildSatsConnectAdapter = (\n id: string,\n name: string,\n provider: SatsConnectProvider,\n): WalletAdapter => {\n let chain: ChainBase = BITCOIN_CHAINS.mainnet;\n let cachedAccounts: ReadonlyArray<string> = [];\n\n const callRequest = async <T>(method: string, params?: Record<string, unknown>): Promise<T> => {\n const response = await provider.request(method, params);\n if (response.error) {\n throw new Error(`[butr/bitcoin] sats-connect ${method} failed: ${response.error.message}`);\n }\n return response.result as T;\n };\n\n const loadAccounts = async (): Promise<ReadonlyArray<string>> => {\n const result = await callRequest<{\n addresses?: ReadonlyArray<{ address: string; purpose?: string }>;\n }>(\"getAccounts\", {\n message: \"Connect to butr\",\n purposes: [\"payment\", \"ordinals\"],\n });\n if (!result?.addresses) {\n return [];\n }\n const addresses = result.addresses.map((a) => a.address);\n cachedAccounts = addresses;\n return addresses;\n };\n\n return {\n capabilities: CAPS_SATS_CONNECT,\n chainPlatform: \"bitcoin\",\n\n async connect() {\n await loadAccounts();\n },\n\n disconnect() {\n cachedAccounts = [];\n return Promise.resolve();\n },\n\n async getAccount() {\n const first = cachedAccounts[0];\n if (first) {\n return buildAccount(first, chain);\n }\n const accounts = await loadAccounts();\n const firstFresh = accounts[0];\n return firstFresh ? buildAccount(firstFresh, chain) : null;\n },\n\n async getAccounts() {\n const accounts = cachedAccounts.length > 0 ? cachedAccounts : await loadAccounts();\n return accounts.map((a) => buildAccount(a, chain));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: 8,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(provider);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: GENERIC_BITCOIN_ICON,\n id,\n name,\n\n async requestAccounts() {\n await loadAccounts();\n },\n\n async sendTx(tx) {\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n const result = await callRequest<{ txid: string }>(\"sendTransfer\", {\n recipients: [{ address: recipient, amount: amount.toString() }],\n });\n return result.txid;\n },\n\n sendTxToChain(tx, _targetChainId, _account, cb) {\n cb?.();\n return this.sendTx(tx);\n },\n\n async signMessage(msg) {\n const address = cachedAccounts[0];\n if (!address) {\n throw new Error(\"No connected account\");\n }\n const result = await callRequest<{ messageHash?: string; signature: string }>(\"signMessage\", {\n address,\n message: new TextDecoder().decode(msg),\n });\n return { signature: base64ToBytes(result.signature), signedMessage: msg };\n },\n\n async signTransaction(tx) {\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n // sats-connect's signPsbt takes a base64 PSBT; encode our bytes\n // and decode the response back to bytes.\n const result = await callRequest<{ psbt: string }>(\"signPsbt\", {\n psbt: bytesToBase64(tx),\n });\n return base64ToBytes(result.psbt);\n },\n\n switchChain(target) {\n if (target.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${target.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n chain = target;\n return Promise.resolve();\n },\n };\n};\n\nexport type { SatsConnectProvider };\nexport { buildSatsConnectAdapter };\n","import type { ChainBase, ConnectorEvent, WalletAdapter, WalletCapabilities } from \"@usebutr/core\";\nimport { buildAccount } from \"@usebutr/wallet-standard-shared\";\n\nimport { BITCOIN_CHAINS } from \"../chains\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\n\n/** UniSat-style provider: a single object on `window.unisat` with the\n * same four methods every UniSat-derivative wallet exposes (UniSat\n * itself, OKX Wallet's Bitcoin path at `window.okxwallet.bitcoin`). */\ntype UnisatProvider = {\n getAccounts(): Promise<ReadonlyArray<string>>;\n getNetwork?(): Promise<\"livenet\" | \"mainnet\" | \"testnet\" | \"signet\">;\n on?(\n event: \"accountsChanged\" | \"networkChanged\",\n listener: (...args: Array<unknown>) => void,\n ): void;\n pushPsbt?(psbtHex: string): Promise<string>;\n removeListener?(\n event: \"accountsChanged\" | \"networkChanged\",\n listener: (...args: Array<unknown>) => void,\n ): void;\n requestAccounts(): Promise<ReadonlyArray<string>>;\n sendBitcoin?(recipient: string, amount: number): Promise<string>;\n signMessage(message: string, type?: \"ecdsa\" | \"bip322-simple\"): Promise<string>;\n signPsbt(psbtHex: string, options?: Record<string, unknown>): Promise<string>;\n};\n\nconst CAPS_UNISAT: WalletCapabilities = {\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: true,\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: true,\n subscribe: true,\n switchAccount: false,\n switchChain: false,\n};\n\n// Encoding helpers — small enough to live next to their caller rather\n// than in a cross-cutting \"shared\" file.\nconst bytesToHex = (bytes: Uint8Array): string => {\n let hex = \"\";\n for (const byte of bytes) {\n hex += byte.toString(16).padStart(2, \"0\");\n }\n return hex;\n};\n\nconst hexToBytes = (hex: string): Uint8Array => {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i += 1) {\n out[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n};\n\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\n/**\n * Wrap a UniSat-style provider (`window.unisat`, `window.okxwallet.bitcoin`,\n * `window.btc`) into a butr `WalletAdapter`.\n *\n * The UniSat shape is consistent enough that one adapter handles every\n * derivative. Differences (network names, `sendBitcoin` presence) are\n * gated by feature detection per call.\n */\nconst buildUnisatAdapter = (id: string, name: string, provider: UnisatProvider): WalletAdapter => {\n let chain: ChainBase = BITCOIN_CHAINS.mainnet;\n const listenersSet = new Set<(event: ConnectorEvent) => void>();\n\n const refreshChain = async () => {\n if (typeof provider.getNetwork !== \"function\") {\n return;\n }\n try {\n const network = await provider.getNetwork();\n if (network === \"testnet\") {\n chain = BITCOIN_CHAINS.testnet;\n } else if (network === \"signet\") {\n chain = BITCOIN_CHAINS.signet;\n } else {\n chain = BITCOIN_CHAINS.mainnet;\n }\n } catch {\n // Network probe failed — keep the current chain. The next call\n // will retry through whichever path next invokes refreshChain.\n }\n };\n\n return {\n capabilities: CAPS_UNISAT,\n chainPlatform: \"bitcoin\",\n\n async connect(opts) {\n if (opts?.silent) {\n const accounts = await provider.getAccounts();\n if (accounts.length === 0) {\n throw new Error(\"No authorized accounts for silent reconnect\");\n }\n await refreshChain();\n return;\n }\n await provider.requestAccounts();\n await refreshChain();\n },\n\n disconnect() {\n // No portable disconnect across UniSat-shaped wallets. butr's\n // reducer marks the wallet disconnected on its side regardless.\n return Promise.resolve();\n },\n\n async getAccount() {\n const accounts = await provider.getAccounts();\n const first = accounts[0];\n if (!first) {\n return null;\n }\n await refreshChain();\n return buildAccount(first, chain);\n },\n\n async getAccounts() {\n const accounts = await provider.getAccounts();\n if (accounts.length === 0) {\n return [];\n }\n await refreshChain();\n return accounts.map((a) => buildAccount(a, chain));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: 8,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(provider);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: GENERIC_BITCOIN_ICON,\n id,\n name,\n\n async requestAccounts() {\n await provider.requestAccounts();\n await refreshChain();\n },\n\n sendTx(tx) {\n if (typeof provider.sendBitcoin !== \"function\") {\n throw new TypeError(`Wallet ${name} does not expose sendBitcoin`);\n }\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n // UniSat's sendBitcoin takes a JS number for satoshis. Values\n // above 2^53 aren't representable; that's 90+ million BTC, which\n // would never appear in practice.\n const sats = Number(amount);\n return provider.sendBitcoin(recipient, sats);\n },\n\n sendTxToChain(tx, _targetChainIdDecimal, _account, cb) {\n cb?.();\n return this.sendTx(tx);\n },\n\n async signMessage(msg) {\n // UniSat takes a UTF-8 message and returns a base64 signature.\n // We return the raw signature bytes (decoded from base64) and the\n // bytes the wallet signed (pass-through of the input). UniSat\n // doesn't expose a \"pre-image\" so the input itself is the signed\n // message from butr's perspective.\n const text = new TextDecoder().decode(msg);\n const signatureB64 = await provider.signMessage(text);\n return { signature: base64ToBytes(signatureB64), signedMessage: msg };\n },\n\n async signTransaction(tx) {\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n const signedHex = await provider.signPsbt(bytesToHex(tx));\n return hexToBytes(signedHex);\n },\n\n subscribe(listener) {\n listenersSet.add(listener);\n const onAccountsChanged = (...args: ReadonlyArray<unknown>) => {\n const accounts = (args[0] as ReadonlyArray<string> | undefined) ?? [];\n if (accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const built = accounts.map((a) => buildAccount(a, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n };\n const onNetworkChanged = () => {\n void refreshChain();\n };\n provider.on?.(\"accountsChanged\", onAccountsChanged);\n provider.on?.(\"networkChanged\", onNetworkChanged);\n return () => {\n provider.removeListener?.(\"accountsChanged\", onAccountsChanged);\n provider.removeListener?.(\"networkChanged\", onNetworkChanged);\n listenersSet.delete(listener);\n };\n },\n\n switchChain(target) {\n if (target.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${target.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n // UniSat-shaped wallets pick their network via the user's\n // extension UI; we update local state so consumers see it, but\n // the wallet itself doesn't switch.\n chain = target;\n void refreshChain();\n return Promise.resolve();\n },\n };\n};\n\nexport type { UnisatProvider };\nexport { buildUnisatAdapter };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\nimport type { SatsConnectProvider } from \"./sats-connect\";\nimport { buildSatsConnectAdapter } from \"./sats-connect\";\nimport type { UnisatProvider } from \"./unisat\";\nimport { buildUnisatAdapter } from \"./unisat\";\n\nconst DEFAULT_SETTLE_MS = 150;\n\ntype InjectedHost = {\n btc?: UnisatProvider;\n okxwallet?: { bitcoin?: UnisatProvider };\n unisat?: UnisatProvider;\n XverseProviders?: { BitcoinProvider?: SatsConnectProvider };\n};\n\ntype InjectedBitcoinDiscoveryOptions = {\n /** Suppresses emission when Wallet Standard discovery has already\n * registered a Bitcoin adapter for the same browser session. */\n hasAnyWalletStandardAdapter?: () => boolean;\n /** Settle deadline in ms before the fallback fires. Same default and\n * intent as the EVM injected fallback. */\n settleMs?: number;\n /** Override the global host (tests, iframes). */\n target?: InjectedHost | null;\n};\n\nconst readHost = (target: InjectedBitcoinDiscoveryOptions[\"target\"]): InjectedHost | null => {\n const globalWindow = typeof window === \"undefined\" ? null : (window as unknown as InjectedHost);\n return target === undefined ? globalWindow : target;\n};\n\nconst probeProviders = (host: InjectedHost): Array<WalletAdapter> => {\n const adapters: Array<WalletAdapter> = [];\n const seen = new Set<UnisatProvider | SatsConnectProvider>();\n\n if (host.unisat && !seen.has(host.unisat)) {\n seen.add(host.unisat);\n adapters.push(buildUnisatAdapter(\"injected:bitcoin:unisat\", \"Unisat\", host.unisat));\n }\n\n const okxBitcoin = host.okxwallet?.bitcoin;\n if (okxBitcoin && !seen.has(okxBitcoin)) {\n seen.add(okxBitcoin);\n adapters.push(buildUnisatAdapter(\"injected:bitcoin:okx\", \"OKX Wallet (Bitcoin)\", okxBitcoin));\n }\n\n const xverse = host.XverseProviders?.BitcoinProvider;\n if (xverse && !seen.has(xverse)) {\n seen.add(xverse);\n adapters.push(buildSatsConnectAdapter(\"injected:bitcoin:xverse\", \"Xverse\", xverse));\n }\n\n if (host.btc && !seen.has(host.btc)) {\n seen.add(host.btc);\n adapters.push(\n buildUnisatAdapter(\"injected:bitcoin:legacy\", \"Browser Bitcoin wallet\", host.btc),\n );\n }\n\n return adapters;\n};\n\n/**\n * Last-resort discovery path for Bitcoin wallets that DON'T announce via\n * Wallet Standard. Probes, in order: `window.unisat`,\n * `window.okxwallet.bitcoin`, `window.XverseProviders.BitcoinProvider`,\n * `window.btc`.\n *\n * Wallet Standard wallets (Phantom, Magic Eden, Leather, modern OKX\n * builds) are already handled by `discoverBitcoinAdapters`. This\n * fallback waits `settleMs` (default 150ms), consults\n * `hasAnyWalletStandardAdapter` if provided, and emits adapters for\n * any injected providers that weren't already covered.\n *\n * Each emitted adapter has a stable id prefix (`injected:bitcoin:*`)\n * so consumers can distinguish them in the picker UI.\n */\nconst discoverInjectedBitcoinAdapter = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedBitcoinDiscoveryOptions = {},\n): (() => void) => {\n const settleMs = options.settleMs ?? DEFAULT_SETTLE_MS;\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) {\n return;\n }\n if (options.hasAnyWalletStandardAdapter?.()) {\n return;\n }\n const host = readHost(options.target);\n if (!host) {\n return;\n }\n const adapters = probeProviders(host);\n for (const adapter of adapters) {\n onAdapter(adapter);\n }\n }, settleMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n};\n\nexport type { InjectedBitcoinDiscoveryOptions };\nexport { GENERIC_BITCOIN_ICON, discoverInjectedBitcoinAdapter };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverInjectedBitcoinAdapter } from \"./injected\";\nimport { discoverBitcoinAdapters } from \"./wallet-standard\";\n\n/**\n * Bitcoin's `PlatformDiscoverer`: Wallet Standard primary (Phantom,\n * Magic Eden, Leather, OKX); legacy fallback covers sats-connect\n * (Xverse), `window.unisat`, OKX legacy, and `window.btc`. The\n * fallback defers to Wallet Standard via `hasAnyPrimaryAdapter`.\n */\nconst bitcoinDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) =>\n discoverInjectedBitcoinAdapter(onAdapter, {\n hasAnyWalletStandardAdapter: opts.hasAnyPrimaryAdapter,\n }),\n },\n platform: \"bitcoin\",\n subscribe: discoverBitcoinAdapters,\n};\n\nexport { bitcoinDiscoverer };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["kitSlugify","base64ToBytes"],"sources":["../src/capabilities.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/injected/icon.ts","../src/injected/sats-connect.ts","../src/injected/unisat.ts","../src/injected/index.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\ntype BitcoinCapabilityInput = {\n chainCount: number;\n features: {\n events: boolean;\n sendTransfer: boolean;\n signMessage: boolean;\n signPsbt: boolean;\n };\n};\n\n/**\n * Bitcoin capability mapping.\n *\n * - `sendTransaction = bitcoin:sendTransfer present`. The wallet handles\n * UTXO selection, fee estimation, signing, and broadcast.\n * - `signTransaction = bitcoin:signPsbt present`. Sign-only PSBT path\n * for consumers that build their own UTXO-shaped transactions with\n * `bitcoinjs-lib` and broadcast through their own provider.\n * - `signMessage = bitcoin:signMessage present`.\n * - `signIn = false`. No Sign-In-With-Bitcoin standard yet (BIP-322 is\n * message-signing oriented, not auth).\n * - `subscribe = events present`. Most Bitcoin wallets don't emit\n * change events portably; capabilities admits the truth.\n * - `switchChain = false`. No portable per-call switch RPC across\n * Bitcoin wallets — Xverse/Unisat/Phantom each pick their own network.\n */\nconst resolveBitcoinCapabilities = (input: BitcoinCapabilityInput): WalletCapabilities => ({\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: false,\n sendTransaction: input.features.sendTransfer,\n signIn: false,\n signMessage: input.features.signMessage,\n signTransaction: input.features.signPsbt,\n subscribe: input.features.events,\n switchAccount: false,\n switchChain: input.chainCount > 1,\n});\n\nexport type { BitcoinCapabilityInput };\nexport { resolveBitcoinCapabilities };\n","import type { Account, ChainBase, ConnectorEvent, WalletAdapter } from \"@usebutr/core\";\nimport { logWarn, sanitizeIcon } from \"@usebutr/core\";\nimport {\n buildAccount,\n getFeature,\n pickAccountByAddress,\n pickFirstAddress,\n slugify as kitSlugify,\n} from \"@usebutr/wallet-standard-shared\";\nimport type {\n StandardConnectFeature,\n StandardDisconnectFeature,\n StandardEventsFeature,\n WalletStandardWallet,\n} from \"@usebutr/wallet-standard-shared\";\n\nimport { resolveBitcoinCapabilities } from \"./capabilities\";\nimport type {\n BitcoinSendTransferFeature,\n BitcoinSignMessageFeature,\n BitcoinSignPsbtFeature,\n} from \"./wallet-standard-types\";\n\nconst BITCOIN_PREFIX = \"bip122:\";\nconst BITCOIN_DECIMALS = 8;\nconst BITCOIN_MAINNET_ID = \"bip122:000000000019d6689c085ae165831e93\";\n\nconst slugify = (name: string): string => kitSlugify(\"btc\", name);\n\nconst pickBitcoinChain = (wallet: WalletStandardWallet): string | null => {\n const mainnet = wallet.chains.find((c) => c === BITCOIN_MAINNET_ID);\n if (mainnet) {\n return mainnet;\n }\n return wallet.chains.find((c) => c.startsWith(BITCOIN_PREFIX)) ?? null;\n};\n\nconst buildBitcoinChain = (chainId: string, walletName: string): ChainBase => ({\n id: chainId,\n // Same posture as EVM/SVM/Sui: butr ships no chain-id → name table.\n name: walletName,\n namespace: \"bip122\",\n reference: chainId.slice(BITCOIN_PREFIX.length),\n});\n\nconst buildBitcoinAccount = (address: string, chain: ChainBase): Account =>\n buildAccount(address, chain);\n\n/**\n * Adapt a Bitcoin Wallet Standard `Wallet` into a butr `WalletAdapter`.\n *\n * Returns `null` if the wallet doesn't advertise any `bip122:` chain or\n * doesn't expose `standard:connect`. Same posture as the SVM/Sui\n * adapters: gate features on what each wallet advertises, return\n * placeholders for RPC reads, forward `subscribe` through\n * `standard:events`.\n *\n * **Known limitations**\n *\n * - `getBalance` returns `{ value: 0n, symbol: \"BTC\" }`. Bitcoin\n * balance lookups require an Esplora/Electrum/RPC client outside\n * butr's scope.\n * - `getTransactionReceipt` returns `\"Pending\"` for the same reason.\n * - `sendTx` expects the consumer to pass `{ amount: bigint, recipient: string }`\n * via butr's `unknown` tx parameter — the simplest mental model that\n * maps onto `bitcoin:sendTransfer`. PSBT-shaped flows go through\n * `signTransaction`.\n * - `signTransaction` expects a `Uint8Array` PSBT (raw bytes) — the\n * same shape `bitcoin:signPsbt` accepts. Consumers building with\n * `bitcoinjs-lib` get bytes via `psbt.toBuffer()`.\n * - `switchChain` is local-state-only; the capability flag is `false`\n * when only one chain is advertised. Wallets that ship a real switch\n * primitive (none today, portably) would need their own adapter.\n */\nconst buildBitcoinAdapter = (\n wallet: WalletStandardWallet,\n /** Optional. Called with a function that pushes a synthetic\n * `disconnected` event to all current subscribers. The discovery\n * layer invokes it on Wallet Standard `unregister`. */\n registerDisconnector?: (emit: () => void) => void,\n): WalletAdapter | null => {\n const bitcoinChainId = pickBitcoinChain(wallet);\n if (!bitcoinChainId) {\n return null;\n }\n const connect = getFeature<StandardConnectFeature>(wallet, \"standard:connect\");\n if (!connect) {\n return null;\n }\n\n const disconnect = getFeature<StandardDisconnectFeature>(wallet, \"standard:disconnect\");\n const events = getFeature<StandardEventsFeature>(wallet, \"standard:events\");\n const signMessage = getFeature<BitcoinSignMessageFeature>(wallet, \"bitcoin:signMessage\");\n const signPsbt = getFeature<BitcoinSignPsbtFeature>(wallet, \"bitcoin:signPsbt\");\n const sendTransfer = getFeature<BitcoinSendTransferFeature>(wallet, \"bitcoin:sendTransfer\");\n\n let currentChainId = bitcoinChainId;\n const currentChain = (): ChainBase => buildBitcoinChain(currentChainId, wallet.name);\n\n const listeners = new Set<(event: ConnectorEvent) => void>();\n const notifyAccountChanged = () => {\n if (wallet.accounts.length === 0) {\n return;\n }\n const chain = currentChain();\n const built = wallet.accounts.map((a) => buildBitcoinAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n for (const listener of listeners) {\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n }\n };\n\n registerDisconnector?.(() => {\n for (const listener of listeners) {\n listener({ type: \"disconnected\" });\n }\n });\n\n return {\n capabilities: resolveBitcoinCapabilities({\n chainCount: wallet.chains.filter((c) => c.startsWith(BITCOIN_PREFIX)).length,\n features: {\n events: Boolean(events),\n sendTransfer: Boolean(sendTransfer),\n signMessage: Boolean(signMessage),\n signPsbt: Boolean(signPsbt),\n },\n }),\n chainPlatform: \"bitcoin\",\n\n async connect(opts) {\n await connect.connect(opts?.silent ? { silent: true } : undefined);\n },\n\n async disconnect() {\n if (disconnect) {\n try {\n await disconnect.disconnect();\n } catch (error) {\n logWarn(\"[butr] Bitcoin Wallet Standard disconnect threw:\", error);\n }\n }\n },\n\n getAccount() {\n const address = pickFirstAddress(wallet.accounts);\n if (!address) {\n return Promise.resolve(null);\n }\n return Promise.resolve(buildBitcoinAccount(address, currentChain()));\n },\n\n getAccounts() {\n const chain = currentChain();\n return Promise.resolve(wallet.accounts.map((a) => buildBitcoinAccount(a.address, chain)));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: BITCOIN_DECIMALS,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n // Consumers cast to whatever Bitcoin signing wrapper they use\n // (bitcoinjs-lib's Signer, scure-btc-signer's HDWallet, etc.) or\n // call butr's adapter directly for PSBT / send-transfer.\n return Promise.resolve(wallet);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: sanitizeIcon(wallet.icon),\n id: slugify(wallet.name),\n name: wallet.name,\n\n async requestAccounts() {\n await connect.connect();\n },\n\n async sendTx(tx, account) {\n if (!sendTransfer) {\n throw new Error(`Wallet ${wallet.name} does not advertise bitcoin:sendTransfer`);\n }\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — pass the recipient address and an amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await sendTransfer.sendTransfer({\n account: wsAccount,\n amount,\n chain: currentChainId,\n recipient,\n });\n return output.txid;\n },\n\n sendTxToChain(tx, _targetChainId, account, cb) {\n cb?.();\n return this.sendTx(tx, account);\n },\n\n async signMessage(msg, account) {\n if (!signMessage) {\n throw new Error(`Wallet ${wallet.name} does not advertise bitcoin:signMessage`);\n }\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n const output = await signMessage.signMessage({ account: wsAccount, message: msg });\n return { signature: output.signature, signedMessage: output.signedMessage };\n },\n\n ...(signPsbt\n ? {\n async signTransaction(tx, account) {\n const wsAccount = account\n ? pickAccountByAddress(wallet.accounts, account.walletAddress)\n : (wallet.accounts[0] ?? null);\n if (!wsAccount) {\n throw new Error(\"No connected account\");\n }\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n const output = await signPsbt.signPsbt({\n account: wsAccount,\n chain: currentChainId,\n psbt: tx,\n });\n return output.signedPsbt;\n },\n }\n : {}),\n\n subscribe(listener) {\n listeners.add(listener);\n let unsubWallet: (() => void) | null = null;\n if (events) {\n const unsub = events.on(\"change\", (changes) => {\n if (changes.chains) {\n const next =\n changes.chains.find((c) => c === BITCOIN_MAINNET_ID) ??\n changes.chains.find((c) => c.startsWith(BITCOIN_PREFIX));\n if (next) {\n currentChainId = next;\n }\n }\n\n if (changes.accounts) {\n if (changes.accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const chain = currentChain();\n const built = changes.accounts.map((a) => buildBitcoinAccount(a.address, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n return;\n }\n\n if (changes.chains) {\n notifyAccountChanged();\n }\n });\n unsubWallet = () => unsub();\n }\n return () => {\n listeners.delete(listener);\n unsubWallet?.();\n };\n },\n\n switchChain(chain) {\n if (chain.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${chain.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n if (!wallet.chains.includes(chain.id)) {\n throw new Error(\n `Wallet ${wallet.name} does not advertise chain \"${chain.id}\". Available: ${wallet.chains.join(\", \")}`,\n );\n }\n currentChainId = chain.id;\n notifyAccountChanged();\n return Promise.resolve();\n },\n };\n};\n\nexport { buildBitcoinAdapter, slugify };\n","import type { WalletAdapter } from \"@usebutr/core\";\nimport { discoverWalletStandard } from \"@usebutr/wallet-standard-shared\";\n\nimport { buildBitcoinAdapter } from \"./wallet-standard-adapter\";\n\n/**\n * Subscribe to Bitcoin Wallet Standard announcements.\n *\n * Phantom (Bitcoin), Magic Eden, OKX Wallet (Bitcoin), and Leather\n * advertise `bitcoin:*` features over the same `getWallets()` bus that\n * SVM and Sui consume. `buildBitcoinAdapter` returns `null` for wallets\n * that don't advertise any `bip122:` chain, so multi-chain wallets\n * (Phantom: EVM + SVM + Sui + Bitcoin) produce one adapter per platform.\n *\n * Requires the **optional peer dependency** `@wallet-standard/app`.\n *\n * The discovery loop (dynamic import, dedupe, register / unregister\n * bridge) lives in `@usebutr/wallet-standard-shared`.\n */\nconst discoverBitcoinAdapters = (onAdapter: (adapter: WalletAdapter) => void): (() => void) =>\n discoverWalletStandard(onAdapter, (wallet, registerDisconnector) =>\n buildBitcoinAdapter(wallet, registerDisconnector),\n );\n\nexport { discoverBitcoinAdapters };\n","import type { ChainBase } from \"@usebutr/core\";\n\n/**\n * CAIP-2 Bitcoin chain references use the first 8 bytes (big-endian)\n * of each network's genesis block hash. These string ids are what\n * Bitcoin Wallet Standard wallets (Phantom, Magic Eden, OKX) advertise\n * in `wallet.chains`; the adapter's `switchChain` rejects anything else.\n *\n * - Mainnet: `bip122:000000000019d6689c085ae165831e93`\n * - Testnet: `bip122:000000000933ea01ad0ee984209779ba`\n * - Signet: `bip122:00000008819873e925422c1ff0f99f7c`\n *\n * Bitcoin has no per-call \"switch chain\" RPC across the major wallets,\n * so butr's adapter treats chain as a wallet-side configuration —\n * `switchChain` updates local state to influence subsequent calls (same\n * posture as SVM). Bitcoin's `switchChain` capability is `false` by\n * default; consumers building on top can opt in if their wallet exposes\n * a switch primitive.\n */\nconst BITCOIN_CHAINS = {\n mainnet: {\n id: \"bip122:000000000019d6689c085ae165831e93\",\n name: \"Bitcoin\",\n namespace: \"bip122\",\n reference: \"000000000019d6689c085ae165831e93\",\n },\n signet: {\n id: \"bip122:00000008819873e925422c1ff0f99f7c\",\n name: \"Bitcoin Signet\",\n namespace: \"bip122\",\n reference: \"00000008819873e925422c1ff0f99f7c\",\n },\n testnet: {\n id: \"bip122:000000000933ea01ad0ee984209779ba\",\n name: \"Bitcoin Testnet\",\n namespace: \"bip122\",\n reference: \"000000000933ea01ad0ee984209779ba\",\n },\n} as const satisfies Record<string, ChainBase>;\n\nconst BITCOIN_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(BITCOIN_CHAINS);\n\nexport { BITCOIN_CHAINS, BITCOIN_CHAINS_LIST };\n","/**\n * Generic Bitcoin wallet icon — same purse SVG style as the EVM\n * package, recoloured. Inline so the picker doesn't flash.\n *\n * Lives in its own file because both injected adapters (UniSat-shape\n * and sats-connect) need the same fallback when the wallet doesn't\n * advertise its own icon, and there's no other \"shared\" thing they\n * both want — a one-line module beats a grab-bag.\n */\nconst GENERIC_BITCOIN_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2Y3OTMxYSIgc3Ryb2tlPSJub25lIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+QjwvdGV4dD48L3N2Zz4=\";\n\nexport { GENERIC_BITCOIN_ICON };\n","import type { ChainBase, WalletAdapter, WalletCapabilities } from \"@usebutr/core\";\nimport { buildAccount } from \"@usebutr/wallet-standard-shared\";\n\nimport { BITCOIN_CHAINS } from \"../chains\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\n\n/** sats-connect (Xverse) shape — a JSON-RPC-ish `request(method, params)`. */\ntype SatsConnectProvider = {\n request(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<{ error?: { message: string }; result?: unknown }>;\n};\n\nconst CAPS_SATS_CONNECT: WalletCapabilities = {\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: true,\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: true,\n subscribe: false,\n switchAccount: false,\n switchChain: false,\n};\n\n// Encoding helpers — small enough to live next to their caller rather\n// than in a cross-cutting \"shared\" file.\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\nconst bytesToBase64 = (bytes: Uint8Array): string => {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCodePoint(byte);\n }\n return btoa(binary);\n};\n\n/**\n * Wrap an Xverse-style `BitcoinProvider` (sats-connect) into a butr\n * `WalletAdapter`. sats-connect routes everything through a single\n * `request(method, params)` RPC; we shim each butr capability onto the\n * corresponding sats-connect method.\n *\n * Tested against Xverse's `getAccounts`, `signMessage`, `signPsbt`,\n * `sendTransfer` methods.\n */\nconst buildSatsConnectAdapter = (\n id: string,\n name: string,\n provider: SatsConnectProvider,\n): WalletAdapter => {\n let chain: ChainBase = BITCOIN_CHAINS.mainnet;\n let cachedAccounts: ReadonlyArray<string> = [];\n\n const callRequest = async <T>(method: string, params?: Record<string, unknown>): Promise<T> => {\n const response = await provider.request(method, params);\n if (response.error) {\n throw new Error(`[butr/bitcoin] sats-connect ${method} failed: ${response.error.message}`);\n }\n return response.result as T;\n };\n\n const loadAccounts = async (): Promise<ReadonlyArray<string>> => {\n const result = await callRequest<{\n addresses?: ReadonlyArray<{ address: string; purpose?: string }>;\n }>(\"getAccounts\", {\n message: \"Connect to butr\",\n purposes: [\"payment\", \"ordinals\"],\n });\n if (!result?.addresses) {\n return [];\n }\n const addresses = result.addresses.map((a) => a.address);\n cachedAccounts = addresses;\n return addresses;\n };\n\n return {\n capabilities: CAPS_SATS_CONNECT,\n chainPlatform: \"bitcoin\",\n\n async connect() {\n await loadAccounts();\n },\n\n disconnect() {\n cachedAccounts = [];\n return Promise.resolve();\n },\n\n async getAccount() {\n const first = cachedAccounts[0];\n if (first) {\n return buildAccount(first, chain);\n }\n const accounts = await loadAccounts();\n const firstFresh = accounts[0];\n return firstFresh ? buildAccount(firstFresh, chain) : null;\n },\n\n async getAccounts() {\n const accounts = cachedAccounts.length > 0 ? cachedAccounts : await loadAccounts();\n return accounts.map((a) => buildAccount(a, chain));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: 8,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(provider);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: GENERIC_BITCOIN_ICON,\n id,\n name,\n\n async requestAccounts() {\n await loadAccounts();\n },\n\n async sendTx(tx) {\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n const result = await callRequest<{ txid: string }>(\"sendTransfer\", {\n recipients: [{ address: recipient, amount: amount.toString() }],\n });\n return result.txid;\n },\n\n sendTxToChain(tx, _targetChainId, _account, cb) {\n cb?.();\n return this.sendTx(tx);\n },\n\n async signMessage(msg) {\n const address = cachedAccounts[0];\n if (!address) {\n throw new Error(\"No connected account\");\n }\n const result = await callRequest<{ messageHash?: string; signature: string }>(\"signMessage\", {\n address,\n message: new TextDecoder().decode(msg),\n });\n return { signature: base64ToBytes(result.signature), signedMessage: msg };\n },\n\n async signTransaction(tx) {\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n // sats-connect's signPsbt takes a base64 PSBT; encode our bytes\n // and decode the response back to bytes.\n const result = await callRequest<{ psbt: string }>(\"signPsbt\", {\n psbt: bytesToBase64(tx),\n });\n return base64ToBytes(result.psbt);\n },\n\n switchChain(target) {\n if (target.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${target.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n chain = target;\n return Promise.resolve();\n },\n };\n};\n\nexport type { SatsConnectProvider };\nexport { buildSatsConnectAdapter };\n","import type { ChainBase, ConnectorEvent, WalletAdapter, WalletCapabilities } from \"@usebutr/core\";\nimport { buildAccount } from \"@usebutr/wallet-standard-shared\";\n\nimport { BITCOIN_CHAINS } from \"../chains\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\n\n/** UniSat-style provider: a single object on `window.unisat` with the\n * same four methods every UniSat-derivative wallet exposes (UniSat\n * itself, OKX Wallet's Bitcoin path at `window.okxwallet.bitcoin`). */\ntype UnisatProvider = {\n getAccounts(): Promise<ReadonlyArray<string>>;\n getNetwork?(): Promise<\"livenet\" | \"mainnet\" | \"testnet\" | \"signet\">;\n on?(\n event: \"accountsChanged\" | \"networkChanged\",\n listener: (...args: Array<unknown>) => void,\n ): void;\n pushPsbt?(psbtHex: string): Promise<string>;\n removeListener?(\n event: \"accountsChanged\" | \"networkChanged\",\n listener: (...args: Array<unknown>) => void,\n ): void;\n requestAccounts(): Promise<ReadonlyArray<string>>;\n sendBitcoin?(recipient: string, amount: number): Promise<string>;\n signMessage(message: string, type?: \"ecdsa\" | \"bip322-simple\"): Promise<string>;\n signPsbt(psbtHex: string, options?: Record<string, unknown>): Promise<string>;\n};\n\nconst CAPS_UNISAT: WalletCapabilities = {\n getBalance: false,\n getTransactionReceipt: false,\n requestAccounts: true,\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: true,\n subscribe: true,\n switchAccount: false,\n switchChain: false,\n};\n\n// Encoding helpers — small enough to live next to their caller rather\n// than in a cross-cutting \"shared\" file.\nconst bytesToHex = (bytes: Uint8Array): string => {\n let hex = \"\";\n for (const byte of bytes) {\n hex += byte.toString(16).padStart(2, \"0\");\n }\n return hex;\n};\n\nconst hexToBytes = (hex: string): Uint8Array => {\n const clean = hex.startsWith(\"0x\") ? hex.slice(2) : hex;\n const out = new Uint8Array(clean.length / 2);\n for (let i = 0; i < out.length; i += 1) {\n out[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n};\n\nconst base64ToBytes = (b64: string): Uint8Array => {\n const binary = atob(b64);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) {\n out[i] = binary.codePointAt(i) ?? 0;\n }\n return out;\n};\n\n/**\n * Wrap a UniSat-style provider (`window.unisat`, `window.okxwallet.bitcoin`,\n * `window.btc`) into a butr `WalletAdapter`.\n *\n * The UniSat shape is consistent enough that one adapter handles every\n * derivative. Differences (network names, `sendBitcoin` presence) are\n * gated by feature detection per call.\n */\nconst buildUnisatAdapter = (id: string, name: string, provider: UnisatProvider): WalletAdapter => {\n let chain: ChainBase = BITCOIN_CHAINS.mainnet;\n const listenersSet = new Set<(event: ConnectorEvent) => void>();\n\n const refreshChain = async () => {\n if (typeof provider.getNetwork !== \"function\") {\n return;\n }\n try {\n const network = await provider.getNetwork();\n if (network === \"testnet\") {\n chain = BITCOIN_CHAINS.testnet;\n } else if (network === \"signet\") {\n chain = BITCOIN_CHAINS.signet;\n } else {\n chain = BITCOIN_CHAINS.mainnet;\n }\n } catch {\n // Network probe failed — keep the current chain. The next call\n // will retry through whichever path next invokes refreshChain.\n }\n };\n\n return {\n capabilities: CAPS_UNISAT,\n chainPlatform: \"bitcoin\",\n\n async connect(opts) {\n if (opts?.silent) {\n const accounts = await provider.getAccounts();\n if (accounts.length === 0) {\n throw new Error(\"No authorized accounts for silent reconnect\");\n }\n await refreshChain();\n return;\n }\n await provider.requestAccounts();\n await refreshChain();\n },\n\n disconnect() {\n // No portable disconnect across UniSat-shaped wallets. butr's\n // reducer marks the wallet disconnected on its side regardless.\n return Promise.resolve();\n },\n\n async getAccount() {\n const accounts = await provider.getAccounts();\n const first = accounts[0];\n if (!first) {\n return null;\n }\n await refreshChain();\n return buildAccount(first, chain);\n },\n\n async getAccounts() {\n const accounts = await provider.getAccounts();\n if (accounts.length === 0) {\n return [];\n }\n await refreshChain();\n return accounts.map((a) => buildAccount(a, chain));\n },\n\n getBalance() {\n return Promise.resolve({\n decimals: 8,\n formatted: \"0\",\n symbol: \"BTC\",\n value: 0n,\n });\n },\n\n getSigner() {\n return Promise.resolve(provider);\n },\n\n getTransactionReceipt() {\n return Promise.resolve({ status: \"Pending\" as const });\n },\n\n icon: GENERIC_BITCOIN_ICON,\n id,\n name,\n\n async requestAccounts() {\n await provider.requestAccounts();\n await refreshChain();\n },\n\n sendTx(tx) {\n if (typeof provider.sendBitcoin !== \"function\") {\n throw new TypeError(`Wallet ${name} does not expose sendBitcoin`);\n }\n if (\n !tx ||\n typeof tx !== \"object\" ||\n typeof (tx as { recipient?: unknown }).recipient !== \"string\" ||\n typeof (tx as { amount?: unknown }).amount !== \"bigint\"\n ) {\n throw new TypeError(\n \"Bitcoin sendTx expects { amount: bigint, recipient: string } — amount in satoshis\",\n );\n }\n const { amount, recipient } = tx as { amount: bigint; recipient: string };\n // UniSat's sendBitcoin takes a JS number for satoshis. Values\n // above 2^53 aren't representable; that's 90+ million BTC, which\n // would never appear in practice.\n const sats = Number(amount);\n return provider.sendBitcoin(recipient, sats);\n },\n\n sendTxToChain(tx, _targetChainIdDecimal, _account, cb) {\n cb?.();\n return this.sendTx(tx);\n },\n\n async signMessage(msg) {\n // UniSat takes a UTF-8 message and returns a base64 signature.\n // We return the raw signature bytes (decoded from base64) and the\n // bytes the wallet signed (pass-through of the input). UniSat\n // doesn't expose a \"pre-image\" so the input itself is the signed\n // message from butr's perspective.\n const text = new TextDecoder().decode(msg);\n const signatureB64 = await provider.signMessage(text);\n return { signature: base64ToBytes(signatureB64), signedMessage: msg };\n },\n\n async signTransaction(tx) {\n if (!(tx instanceof Uint8Array)) {\n throw new TypeError(\n \"Bitcoin signTransaction expects a PSBT as Uint8Array (e.g. psbt.toBuffer())\",\n );\n }\n const signedHex = await provider.signPsbt(bytesToHex(tx));\n return hexToBytes(signedHex);\n },\n\n subscribe(listener) {\n listenersSet.add(listener);\n const onAccountsChanged = (...args: ReadonlyArray<unknown>) => {\n const accounts = (args[0] as ReadonlyArray<string> | undefined) ?? [];\n if (accounts.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n const built = accounts.map((a) => buildAccount(a, chain));\n const first = built[0];\n if (!first) {\n return;\n }\n listener({ account: first, accounts: built, type: \"accountChanged\" });\n };\n const onNetworkChanged = () => {\n void refreshChain();\n };\n provider.on?.(\"accountsChanged\", onAccountsChanged);\n provider.on?.(\"networkChanged\", onNetworkChanged);\n return () => {\n provider.removeListener?.(\"accountsChanged\", onAccountsChanged);\n provider.removeListener?.(\"networkChanged\", onNetworkChanged);\n listenersSet.delete(listener);\n };\n },\n\n switchChain(target) {\n if (target.namespace !== \"bip122\") {\n throw new Error(\n `Bitcoin adapter received non-Bitcoin chain \"${target.id}\". Pass a chain with namespace \"bip122\".`,\n );\n }\n // UniSat-shaped wallets pick their network via the user's\n // extension UI; we update local state so consumers see it, but\n // the wallet itself doesn't switch.\n chain = target;\n void refreshChain();\n return Promise.resolve();\n },\n };\n};\n\nexport type { UnisatProvider };\nexport { buildUnisatAdapter };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport { GENERIC_BITCOIN_ICON } from \"./icon\";\nimport type { SatsConnectProvider } from \"./sats-connect\";\nimport { buildSatsConnectAdapter } from \"./sats-connect\";\nimport type { UnisatProvider } from \"./unisat\";\nimport { buildUnisatAdapter } from \"./unisat\";\n\nconst DEFAULT_SETTLE_MS = 150;\n\ntype InjectedHost = {\n btc?: UnisatProvider;\n okxwallet?: { bitcoin?: UnisatProvider };\n unisat?: UnisatProvider;\n XverseProviders?: { BitcoinProvider?: SatsConnectProvider };\n};\n\ntype InjectedBitcoinDiscoveryOptions = {\n /** Suppresses emission when Wallet Standard discovery has already\n * registered a Bitcoin adapter for the same browser session. */\n hasAnyWalletStandardAdapter?: () => boolean;\n /** Settle deadline in ms before the fallback fires. Same default and\n * intent as the EVM injected fallback. */\n settleMs?: number;\n /** Override the global host (tests, iframes). */\n target?: InjectedHost | null;\n};\n\nconst readHost = (target: InjectedBitcoinDiscoveryOptions[\"target\"]): InjectedHost | null => {\n const globalWindow = typeof window === \"undefined\" ? null : (window as unknown as InjectedHost);\n return target === undefined ? globalWindow : target;\n};\n\nconst probeProviders = (host: InjectedHost): Array<WalletAdapter> => {\n const adapters: Array<WalletAdapter> = [];\n const seen = new Set<UnisatProvider | SatsConnectProvider>();\n\n if (host.unisat && !seen.has(host.unisat)) {\n seen.add(host.unisat);\n adapters.push(buildUnisatAdapter(\"injected:bitcoin:unisat\", \"Unisat\", host.unisat));\n }\n\n const okxBitcoin = host.okxwallet?.bitcoin;\n if (okxBitcoin && !seen.has(okxBitcoin)) {\n seen.add(okxBitcoin);\n adapters.push(buildUnisatAdapter(\"injected:bitcoin:okx\", \"OKX Wallet (Bitcoin)\", okxBitcoin));\n }\n\n const xverse = host.XverseProviders?.BitcoinProvider;\n if (xverse && !seen.has(xverse)) {\n seen.add(xverse);\n adapters.push(buildSatsConnectAdapter(\"injected:bitcoin:xverse\", \"Xverse\", xverse));\n }\n\n if (host.btc && !seen.has(host.btc)) {\n seen.add(host.btc);\n adapters.push(\n buildUnisatAdapter(\"injected:bitcoin:legacy\", \"Browser Bitcoin wallet\", host.btc),\n );\n }\n\n return adapters;\n};\n\n/**\n * Last-resort discovery path for Bitcoin wallets that DON'T announce via\n * Wallet Standard. Probes, in order: `window.unisat`,\n * `window.okxwallet.bitcoin`, `window.XverseProviders.BitcoinProvider`,\n * `window.btc`.\n *\n * Wallet Standard wallets (Phantom, Magic Eden, Leather, modern OKX\n * builds) are already handled by `discoverBitcoinAdapters`. This\n * fallback waits `settleMs` (default 150ms), consults\n * `hasAnyWalletStandardAdapter` if provided, and emits adapters for\n * any injected providers that weren't already covered.\n *\n * Each emitted adapter has a stable id prefix (`injected:bitcoin:*`)\n * so consumers can distinguish them in the picker UI.\n */\nconst discoverInjectedBitcoinAdapter = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedBitcoinDiscoveryOptions = {},\n): (() => void) => {\n const settleMs = options.settleMs ?? DEFAULT_SETTLE_MS;\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) {\n return;\n }\n if (options.hasAnyWalletStandardAdapter?.()) {\n return;\n }\n const host = readHost(options.target);\n if (!host) {\n return;\n }\n const adapters = probeProviders(host);\n for (const adapter of adapters) {\n onAdapter(adapter);\n }\n }, settleMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n};\n\nexport type { InjectedBitcoinDiscoveryOptions };\nexport { GENERIC_BITCOIN_ICON, discoverInjectedBitcoinAdapter };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverInjectedBitcoinAdapter } from \"./injected\";\nimport { discoverBitcoinAdapters } from \"./wallet-standard\";\n\n/**\n * Bitcoin's `PlatformDiscoverer`: Wallet Standard primary (Phantom,\n * Magic Eden, Leather, OKX); legacy fallback covers sats-connect\n * (Xverse), `window.unisat`, OKX legacy, and `window.btc`. The\n * fallback defers to Wallet Standard via `hasAnyPrimaryAdapter`.\n */\nconst bitcoinDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) =>\n discoverInjectedBitcoinAdapter(onAdapter, {\n hasAnyWalletStandardAdapter: opts.hasAnyPrimaryAdapter,\n }),\n },\n platform: \"bitcoin\",\n subscribe: discoverBitcoinAdapters,\n};\n\nexport { bitcoinDiscoverer };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebutr/bitcoin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Wallet Standard + injected (sats-connect / Unisat / OKX) wallet discovery and adapters for butr (Bitcoin).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pedro Filho <pedro@filho.me>",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@usebutr/core": "0.2.
|
|
29
|
-
"@usebutr/wallet-standard-shared": "0.2.
|
|
28
|
+
"@usebutr/core": "0.2.1",
|
|
29
|
+
"@usebutr/wallet-standard-shared": "0.2.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@wallet-standard/app": "^1.1.0",
|