@usebutr/bitcoin 0.1.0

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.
@@ -0,0 +1,304 @@
1
+ import { ChainBase, PlatformDiscoverer, WalletAdapter, WalletCapabilities } from "@usebutr/core";
2
+ import { StandardConnectFeature, StandardDisconnectFeature, StandardEventsFeature, StandardEventsListener, WalletStandardAppModule, WalletStandardWallet, WalletStandardWallet as WalletStandardWallet$1, WalletStandardWalletAccount, WalletStandardWalletAccount as WalletStandardWalletAccount$1, WalletsApp } from "@usebutr/wallet-standard-shared";
3
+
4
+ //#region src/wallet-standard-types.d.ts
5
+ type BitcoinSignMessageInput = {
6
+ account: WalletStandardWalletAccount$1;
7
+ message: Uint8Array;
8
+ };
9
+ type BitcoinSignMessageOutput = {
10
+ signature: Uint8Array;
11
+ signedMessage: Uint8Array;
12
+ };
13
+ type BitcoinSignMessageFeature = {
14
+ signMessage(input: BitcoinSignMessageInput): Promise<BitcoinSignMessageOutput>;
15
+ };
16
+ type BitcoinSignPsbtInput = {
17
+ account: WalletStandardWalletAccount$1; /** Network chain id (`bip122:…`). */
18
+ chain: string; /** Base64- or hex-encoded PSBT bytes. */
19
+ psbt: Uint8Array;
20
+ /** Optional input indexes to sign; omit to sign every input the wallet
21
+ * controls. */
22
+ signInputs?: ReadonlyArray<number>;
23
+ };
24
+ type BitcoinSignPsbtOutput = {
25
+ /** Signed PSBT bytes (the wallet either fills in signatures only or
26
+ * finalises depending on the input indexes). */
27
+ signedPsbt: Uint8Array;
28
+ };
29
+ type BitcoinSignPsbtFeature = {
30
+ signPsbt(input: BitcoinSignPsbtInput): Promise<BitcoinSignPsbtOutput>;
31
+ };
32
+ type BitcoinSendTransferInput = {
33
+ account: WalletStandardWalletAccount$1;
34
+ amount: bigint;
35
+ chain: string;
36
+ recipient: string;
37
+ };
38
+ type BitcoinSendTransferOutput = {
39
+ /** Broadcast txid. */txid: string;
40
+ };
41
+ type BitcoinSendTransferFeature = {
42
+ sendTransfer(input: BitcoinSendTransferInput): Promise<BitcoinSendTransferOutput>;
43
+ };
44
+ //#endregion
45
+ //#region src/wallet-standard-adapter.d.ts
46
+ declare const slugify: (name: string) => string;
47
+ /**
48
+ * Adapt a Bitcoin Wallet Standard `Wallet` into a butr `WalletAdapter`.
49
+ *
50
+ * Returns `null` if the wallet doesn't advertise any `bip122:` chain or
51
+ * doesn't expose `standard:connect`. Same posture as the SVM/Sui
52
+ * adapters: gate features on what each wallet advertises, return
53
+ * placeholders for RPC reads, forward `subscribe` through
54
+ * `standard:events`.
55
+ *
56
+ * **Known limitations**
57
+ *
58
+ * - `getBalance` returns `{ value: 0n, symbol: "BTC" }`. Bitcoin
59
+ * balance lookups require an Esplora/Electrum/RPC client outside
60
+ * butr's scope.
61
+ * - `getTransactionReceipt` returns `"Pending"` for the same reason.
62
+ * - `sendTx` expects the consumer to pass `{ amount: bigint, recipient: string }`
63
+ * via butr's `unknown` tx parameter — the simplest mental model that
64
+ * maps onto `bitcoin:sendTransfer`. PSBT-shaped flows go through
65
+ * `signTransaction`.
66
+ * - `signTransaction` expects a `Uint8Array` PSBT (raw bytes) — the
67
+ * same shape `bitcoin:signPsbt` accepts. Consumers building with
68
+ * `bitcoinjs-lib` get bytes via `psbt.toBuffer()`.
69
+ * - `switchChain` is local-state-only; the capability flag is `false`
70
+ * when only one chain is advertised. Wallets that ship a real switch
71
+ * primitive (none today, portably) would need their own adapter.
72
+ */
73
+ declare const buildBitcoinAdapter: (wallet: WalletStandardWallet$1,
74
+ /** Optional. Called with a function that pushes a synthetic
75
+ * `disconnected` event to all current subscribers. The discovery
76
+ * layer invokes it on Wallet Standard `unregister`. */
77
+
78
+ registerDisconnector?: (emit: () => void) => void) => WalletAdapter | null;
79
+ //#endregion
80
+ //#region src/wallet-standard.d.ts
81
+ /**
82
+ * Subscribe to Bitcoin Wallet Standard announcements.
83
+ *
84
+ * Phantom (Bitcoin), Magic Eden, OKX Wallet (Bitcoin), and Leather
85
+ * advertise `bitcoin:*` features over the same `getWallets()` bus that
86
+ * SVM and Sui consume. `buildBitcoinAdapter` returns `null` for wallets
87
+ * that don't advertise any `bip122:` chain, so multi-chain wallets
88
+ * (Phantom: EVM + SVM + Sui + Bitcoin) produce one adapter per platform.
89
+ *
90
+ * Requires the **optional peer dependency** `@wallet-standard/app`.
91
+ *
92
+ * The discovery loop (dynamic import, dedupe, register / unregister
93
+ * bridge) lives in `@usebutr/wallet-standard-shared`.
94
+ */
95
+ declare const discoverBitcoinAdapters: (onAdapter: (adapter: WalletAdapter) => void) => (() => void);
96
+ //#endregion
97
+ //#region src/chains.d.ts
98
+ /**
99
+ * CAIP-2 Bitcoin chain references use the first 8 bytes (big-endian)
100
+ * of each network's genesis block hash. These string ids are what
101
+ * Bitcoin Wallet Standard wallets (Phantom, Magic Eden, OKX) advertise
102
+ * in `wallet.chains`; the adapter's `switchChain` rejects anything else.
103
+ *
104
+ * - Mainnet: `bip122:000000000019d6689c085ae165831e93`
105
+ * - Testnet: `bip122:000000000933ea01ad0ee984209779ba`
106
+ * - Signet: `bip122:00000008819873e925422c1ff0f99f7c`
107
+ *
108
+ * Bitcoin has no per-call "switch chain" RPC across the major wallets,
109
+ * so butr's adapter treats chain as a wallet-side configuration —
110
+ * `switchChain` updates local state to influence subsequent calls (same
111
+ * posture as SVM). Bitcoin's `switchChain` capability is `false` by
112
+ * default; consumers building on top can opt in if their wallet exposes
113
+ * a switch primitive.
114
+ */
115
+ declare const BITCOIN_CHAINS: {
116
+ readonly mainnet: {
117
+ readonly id: "bip122:000000000019d6689c085ae165831e93";
118
+ readonly name: "Bitcoin";
119
+ readonly namespace: "bip122";
120
+ readonly reference: "000000000019d6689c085ae165831e93";
121
+ };
122
+ readonly signet: {
123
+ readonly id: "bip122:00000008819873e925422c1ff0f99f7c";
124
+ readonly name: "Bitcoin Signet";
125
+ readonly namespace: "bip122";
126
+ readonly reference: "00000008819873e925422c1ff0f99f7c";
127
+ };
128
+ readonly testnet: {
129
+ readonly id: "bip122:000000000933ea01ad0ee984209779ba";
130
+ readonly name: "Bitcoin Testnet";
131
+ readonly namespace: "bip122";
132
+ readonly reference: "000000000933ea01ad0ee984209779ba";
133
+ };
134
+ };
135
+ declare const BITCOIN_CHAINS_LIST: ReadonlyArray<ChainBase>;
136
+ //#endregion
137
+ //#region src/capabilities.d.ts
138
+ type BitcoinCapabilityInput = {
139
+ chainCount: number;
140
+ features: {
141
+ events: boolean;
142
+ sendTransfer: boolean;
143
+ signMessage: boolean;
144
+ signPsbt: boolean;
145
+ };
146
+ };
147
+ /**
148
+ * Bitcoin capability mapping.
149
+ *
150
+ * - `sendTransaction = bitcoin:sendTransfer present`. The wallet handles
151
+ * UTXO selection, fee estimation, signing, and broadcast.
152
+ * - `signTransaction = bitcoin:signPsbt present`. Sign-only PSBT path
153
+ * for consumers that build their own UTXO-shaped transactions with
154
+ * `bitcoinjs-lib` and broadcast through their own provider.
155
+ * - `signMessage = bitcoin:signMessage present`.
156
+ * - `signIn = false`. No Sign-In-With-Bitcoin standard yet (BIP-322 is
157
+ * message-signing oriented, not auth).
158
+ * - `subscribe = events present`. Most Bitcoin wallets don't emit
159
+ * change events portably; capabilities admits the truth.
160
+ * - `switchChain = false`. No portable per-call switch RPC across
161
+ * Bitcoin wallets — Xverse/Unisat/Phantom each pick their own network.
162
+ */
163
+ declare const resolveBitcoinCapabilities: (input: BitcoinCapabilityInput) => WalletCapabilities;
164
+ //#endregion
165
+ //#region src/injected/icon.d.ts
166
+ /**
167
+ * Generic Bitcoin wallet icon — same purse SVG style as the EVM
168
+ * package, recoloured. Inline so the picker doesn't flash.
169
+ *
170
+ * Lives in its own file because both injected adapters (UniSat-shape
171
+ * and sats-connect) need the same fallback when the wallet doesn't
172
+ * advertise its own icon, and there's no other "shared" thing they
173
+ * both want — a one-line module beats a grab-bag.
174
+ */
175
+ declare const GENERIC_BITCOIN_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iI2Y3OTMxYSIgc3Ryb2tlPSJub25lIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIvPjx0ZXh0IHg9IjEyIiB5PSIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjE0IiBmb250LXdlaWdodD0iYm9sZCIgZmlsbD0iI2ZmZiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+QjwvdGV4dD48L3N2Zz4=";
176
+ //#endregion
177
+ //#region src/injected/sats-connect.d.ts
178
+ /** sats-connect (Xverse) shape — a JSON-RPC-ish `request(method, params)`. */
179
+ type SatsConnectProvider = {
180
+ request(method: string, params?: Record<string, unknown>): Promise<{
181
+ error?: {
182
+ message: string;
183
+ };
184
+ result?: unknown;
185
+ }>;
186
+ };
187
+ /**
188
+ * Wrap an Xverse-style `BitcoinProvider` (sats-connect) into a butr
189
+ * `WalletAdapter`. sats-connect routes everything through a single
190
+ * `request(method, params)` RPC; we shim each butr capability onto the
191
+ * corresponding sats-connect method.
192
+ *
193
+ * Tested against Xverse's `getAccounts`, `signMessage`, `signPsbt`,
194
+ * `sendTransfer` methods.
195
+ */
196
+ //#endregion
197
+ //#region src/injected/unisat.d.ts
198
+ /** UniSat-style provider: a single object on `window.unisat` with the
199
+ * same four methods every UniSat-derivative wallet exposes (UniSat
200
+ * itself, OKX Wallet's Bitcoin path at `window.okxwallet.bitcoin`). */
201
+ type UnisatProvider = {
202
+ getAccounts(): Promise<ReadonlyArray<string>>;
203
+ getNetwork?(): Promise<"livenet" | "mainnet" | "testnet" | "signet">;
204
+ on?(event: "accountsChanged" | "networkChanged", listener: (...args: Array<unknown>) => void): void;
205
+ pushPsbt?(psbtHex: string): Promise<string>;
206
+ removeListener?(event: "accountsChanged" | "networkChanged", listener: (...args: Array<unknown>) => void): void;
207
+ requestAccounts(): Promise<ReadonlyArray<string>>;
208
+ sendBitcoin?(recipient: string, amount: number): Promise<string>;
209
+ signMessage(message: string, type?: "ecdsa" | "bip322-simple"): Promise<string>;
210
+ signPsbt(psbtHex: string, options?: Record<string, unknown>): Promise<string>;
211
+ };
212
+ /**
213
+ * Wrap a UniSat-style provider (`window.unisat`, `window.okxwallet.bitcoin`,
214
+ * `window.btc`) into a butr `WalletAdapter`.
215
+ *
216
+ * The UniSat shape is consistent enough that one adapter handles every
217
+ * derivative. Differences (network names, `sendBitcoin` presence) are
218
+ * gated by feature detection per call.
219
+ */
220
+ //#endregion
221
+ //#region src/injected/index.d.ts
222
+ type InjectedHost = {
223
+ btc?: UnisatProvider;
224
+ okxwallet?: {
225
+ bitcoin?: UnisatProvider;
226
+ };
227
+ unisat?: UnisatProvider;
228
+ XverseProviders?: {
229
+ BitcoinProvider?: SatsConnectProvider;
230
+ };
231
+ };
232
+ type InjectedBitcoinDiscoveryOptions = {
233
+ /** Suppresses emission when Wallet Standard discovery has already
234
+ * registered a Bitcoin adapter for the same browser session. */
235
+ hasAnyWalletStandardAdapter?: () => boolean;
236
+ /** Settle deadline in ms before the fallback fires. Same default and
237
+ * intent as the EVM injected fallback. */
238
+ settleMs?: number; /** Override the global host (tests, iframes). */
239
+ target?: InjectedHost | null;
240
+ };
241
+ /**
242
+ * Last-resort discovery path for Bitcoin wallets that DON'T announce via
243
+ * Wallet Standard. Probes, in order: `window.unisat`,
244
+ * `window.okxwallet.bitcoin`, `window.XverseProviders.BitcoinProvider`,
245
+ * `window.btc`.
246
+ *
247
+ * Wallet Standard wallets (Phantom, Magic Eden, Leather, modern OKX
248
+ * builds) are already handled by `discoverBitcoinAdapters`. This
249
+ * fallback waits `settleMs` (default 150ms), consults
250
+ * `hasAnyWalletStandardAdapter` if provided, and emits adapters for
251
+ * any injected providers that weren't already covered.
252
+ *
253
+ * Each emitted adapter has a stable id prefix (`injected:bitcoin:*`)
254
+ * so consumers can distinguish them in the picker UI.
255
+ */
256
+ declare const discoverInjectedBitcoinAdapter: (onAdapter: (adapter: WalletAdapter) => void, options?: InjectedBitcoinDiscoveryOptions) => (() => void);
257
+ //#endregion
258
+ //#region src/discoverer.d.ts
259
+ /**
260
+ * Bitcoin's `PlatformDiscoverer`: Wallet Standard primary (Phantom,
261
+ * Magic Eden, Leather, OKX); legacy fallback covers sats-connect
262
+ * (Xverse), `window.unisat`, OKX legacy, and `window.btc`. The
263
+ * fallback defers to Wallet Standard via `hasAnyPrimaryAdapter`.
264
+ */
265
+ declare const bitcoinDiscoverer: PlatformDiscoverer;
266
+ //#endregion
267
+ //#region src/signer-augmentation.d.ts
268
+ /**
269
+ * Augment `@usebutr/core`'s `SignerForPlatform` registry with the Bitcoin
270
+ * entry. Bitcoin's signer surface is fragmented — `getSigner()` may
271
+ * return one of three shapes depending on which adapter discovered the
272
+ * wallet:
273
+ *
274
+ * - `WalletStandardWallet` — for Phantom, Magic Eden, Leather, OKX
275
+ * (modern Wallet Standard path).
276
+ * - A UniSat-shaped provider — for Unisat, OKX legacy, `window.btc`
277
+ * (injected path).
278
+ * - A sats-connect `BitcoinProvider` — for Xverse (sats-connect path).
279
+ *
280
+ * The registry surfaces the union honestly so consumers know they need
281
+ * to runtime-narrow.
282
+ */
283
+ type UnisatLike = {
284
+ getAccounts(): Promise<ReadonlyArray<string>>;
285
+ requestAccounts(): Promise<ReadonlyArray<string>>;
286
+ signMessage(message: string, type?: string): Promise<string>;
287
+ signPsbt(psbtHex: string, options?: Record<string, unknown>): Promise<string>;
288
+ };
289
+ type SatsConnectLike = {
290
+ request(method: string, params?: Record<string, unknown>): Promise<{
291
+ error?: {
292
+ message: string;
293
+ };
294
+ result?: unknown;
295
+ }>;
296
+ };
297
+ declare module "@usebutr/core" {
298
+ interface SignerForPlatform {
299
+ bitcoin: SatsConnectLike | UnisatLike | WalletStandardWallet$1;
300
+ }
301
+ }
302
+ //#endregion
303
+ export { BITCOIN_CHAINS, BITCOIN_CHAINS_LIST, type BitcoinCapabilityInput, type BitcoinSendTransferFeature, type BitcoinSendTransferInput, type BitcoinSendTransferOutput, type BitcoinSignMessageFeature, type BitcoinSignMessageInput, type BitcoinSignMessageOutput, type BitcoinSignPsbtFeature, type BitcoinSignPsbtInput, type BitcoinSignPsbtOutput, GENERIC_BITCOIN_ICON, type InjectedBitcoinDiscoveryOptions, type StandardConnectFeature, type StandardDisconnectFeature, type StandardEventsFeature, type StandardEventsListener, type WalletStandardAppModule, type WalletStandardWallet, type WalletStandardWalletAccount, type WalletsApp, bitcoinDiscoverer, buildBitcoinAdapter, discoverBitcoinAdapters, discoverInjectedBitcoinAdapter, resolveBitcoinCapabilities, slugify };
304
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/wallet-standard-types.ts","../src/wallet-standard-adapter.ts","../src/wallet-standard.ts","../src/chains.ts","../src/capabilities.ts","../src/injected/icon.ts","../src/injected/sats-connect.ts","../src/injected/unisat.ts","../src/injected/index.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +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};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@usebutr/bitcoin",
3
+ "version": "0.1.0",
4
+ "description": "Wallet Standard + injected (sats-connect / Unisat / OKX) wallet discovery and adapters for butr (Bitcoin).",
5
+ "license": "MIT",
6
+ "author": "Pedro Filho <pedro@filho.me>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/pedroapfilho/usebutr.git",
10
+ "directory": "packages/bitcoin"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "type": "module",
16
+ "sideEffects": false,
17
+ "types": "dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "dependencies": {
28
+ "@usebutr/core": "0.1.0",
29
+ "@usebutr/wallet-standard-shared": "0.1.0"
30
+ },
31
+ "devDependencies": {
32
+ "@wallet-standard/app": "^1.1.0",
33
+ "typescript": "^6.0.3",
34
+ "vitest": "^4.1.6",
35
+ "@repo/config-vitest": "0.0.0",
36
+ "@repo/typescript-config": "0.0.0"
37
+ },
38
+ "peerDependencies": {
39
+ "@wallet-standard/app": "^1.1.0"
40
+ },
41
+ "peerDependenciesMeta": {
42
+ "@wallet-standard/app": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "scripts": {
47
+ "build": "tsdown",
48
+ "clean": "rm -rf dist",
49
+ "dev": "tsdown --watch",
50
+ "lint": "oxlint src",
51
+ "test": "vitest run --passWithNoTests",
52
+ "test:coverage": "vitest run --coverage --passWithNoTests",
53
+ "typecheck": "tsc -p tsconfig.json --noEmit"
54
+ }
55
+ }