bitcoin-wallet-connector 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.
- package/README.md +208 -0
- package/lib/BitcoinConnectionProvider.d.ts +23 -0
- package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs +123 -0
- package/lib/BitcoinWalletAdapterConnector-Bq835yj0.mjs.map +1 -0
- package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js +2 -0
- package/lib/BitcoinWalletAdapterConnector-DMef0iHV.js.map +1 -0
- package/lib/BitcoinWalletAdapterConnector.d.ts +30 -0
- package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs +10 -0
- package/lib/BitgetWalletAdapter.impl-C_HLO7Oi.mjs.map +1 -0
- package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js +2 -0
- package/lib/BitgetWalletAdapter.impl-CxnKMf7U.js.map +1 -0
- package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js +2 -0
- package/lib/LeatherWalletAdapter.impl-B2QgX_tO.js.map +1 -0
- package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs +184 -0
- package/lib/LeatherWalletAdapter.impl-RUYx555r.mjs.map +1 -0
- package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs +235 -0
- package/lib/MagicEdenWalletAdapter.impl-CrA6SGvG.mjs.map +1 -0
- package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js +2 -0
- package/lib/MagicEdenWalletAdapter.impl-Di3Nu2S5.js.map +1 -0
- package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs +67 -0
- package/lib/OkxWalletAdapter.impl-BepoUL1B.mjs.map +1 -0
- package/lib/OkxWalletAdapter.impl-C8kesjGu.js +2 -0
- package/lib/OkxWalletAdapter.impl-C8kesjGu.js.map +1 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js +2 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js.map +1 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs +137 -0
- package/lib/UnisatCompatibleWalletAdapterImpl-M38FqkZI.mjs.map +1 -0
- package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs +14 -0
- package/lib/UnisatWalletAdapter.impl-CJB22se8.mjs.map +1 -0
- package/lib/UnisatWalletAdapter.impl-EISvxdpc.js +2 -0
- package/lib/UnisatWalletAdapter.impl-EISvxdpc.js.map +1 -0
- package/lib/WalletAdapters.types-CnvOqHFH.mjs +32 -0
- package/lib/WalletAdapters.types-CnvOqHFH.mjs.map +1 -0
- package/lib/WalletAdapters.types-De_x1lzr.js +2 -0
- package/lib/WalletAdapters.types-De_x1lzr.js.map +1 -0
- package/lib/WalletAdapters.types.d.ts +110 -0
- package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js +2 -0
- package/lib/XverseCompatibleWalletAdapterImpl-Bf-BK5VK.js.map +1 -0
- package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs +151 -0
- package/lib/XverseCompatibleWalletAdapterImpl-DXKnO_-V.mjs.map +1 -0
- package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs +105 -0
- package/lib/XverseWalletAdapter.impl-CZO0RQva.mjs.map +1 -0
- package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js +2 -0
- package/lib/XverseWalletAdapter.impl-lJwMi-Iv.js.map +1 -0
- package/lib/adapters/BitgetWalletAdapter.d.ts +2 -0
- package/lib/adapters/BitgetWalletAdapter.impl.d.ts +8 -0
- package/lib/adapters/LeatherWalletAdapter.d.ts +2 -0
- package/lib/adapters/LeatherWalletAdapter.impl.d.ts +41 -0
- package/lib/adapters/MagicEdenWalletAdapter.d.ts +11 -0
- package/lib/adapters/MagicEdenWalletAdapter.impl.d.ts +22 -0
- package/lib/adapters/MockAddressWalletAdapter.d.ts +33 -0
- package/lib/adapters/OkxWalletAdapter.d.ts +2 -0
- package/lib/adapters/OkxWalletAdapter.impl.d.ts +51 -0
- package/lib/adapters/UnisatWalletAdapter.d.ts +2 -0
- package/lib/adapters/UnisatWalletAdapter.impl.d.ts +14 -0
- package/lib/adapters/XverseWalletAdapter.d.ts +3 -0
- package/lib/adapters/XverseWalletAdapter.impl.d.ts +14 -0
- package/lib/adapters/index.d.ts +7 -0
- package/lib/adapters.js +2 -0
- package/lib/adapters.js.map +1 -0
- package/lib/adapters.mjs +11 -0
- package/lib/adapters.mjs.map +1 -0
- package/lib/bitget-C7oB4Ffq.mjs +5 -0
- package/lib/bitget-C7oB4Ffq.mjs.map +1 -0
- package/lib/bitget-DXnsxx_y.js +2 -0
- package/lib/bitget-DXnsxx_y.js.map +1 -0
- package/lib/index-CaV3F1Nm.js +424 -0
- package/lib/index-CaV3F1Nm.js.map +1 -0
- package/lib/index-CcQUdePc.mjs +12224 -0
- package/lib/index-CcQUdePc.mjs.map +1 -0
- package/lib/index-D7YwhNAG.mjs +3946 -0
- package/lib/index-D7YwhNAG.mjs.map +1 -0
- package/lib/index-Zx0KcpYx.js +2 -0
- package/lib/index-Zx0KcpYx.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +20 -0
- package/lib/index.mjs.map +1 -0
- package/lib/leather-BoQG_CPn.mjs +5 -0
- package/lib/leather-BoQG_CPn.mjs.map +1 -0
- package/lib/leather-DJ8nWmM8.js +2 -0
- package/lib/leather-DJ8nWmM8.js.map +1 -0
- package/lib/magiceden-B36CEQa6.js +2 -0
- package/lib/magiceden-B36CEQa6.js.map +1 -0
- package/lib/magiceden-Cg7d3agI.mjs +5 -0
- package/lib/magiceden-Cg7d3agI.mjs.map +1 -0
- package/lib/misc-B5EWO_dn.mjs +10 -0
- package/lib/misc-B5EWO_dn.mjs.map +1 -0
- package/lib/misc-CigR0RqC.js +2 -0
- package/lib/misc-CigR0RqC.js.map +1 -0
- package/lib/okx-ChwzM0dK.js +2 -0
- package/lib/okx-ChwzM0dK.js.map +1 -0
- package/lib/okx-DWbHwazu.mjs +5 -0
- package/lib/okx-DWbHwazu.mjs.map +1 -0
- package/lib/react.d.ts +2 -0
- package/lib/react.js +2 -0
- package/lib/react.js.map +1 -0
- package/lib/react.mjs +128 -0
- package/lib/react.mjs.map +1 -0
- package/lib/transaction-CiLOYSE_.mjs +1063 -0
- package/lib/transaction-CiLOYSE_.mjs.map +1 -0
- package/lib/transaction-CzdnbXSo.js +2 -0
- package/lib/transaction-CzdnbXSo.js.map +1 -0
- package/lib/unisat-BvZW5h0U.js +2 -0
- package/lib/unisat-BvZW5h0U.js.map +1 -0
- package/lib/unisat-pLgab4nG.mjs +5 -0
- package/lib/unisat-pLgab4nG.mjs.map +1 -0
- package/lib/utils/StateChannel.d.ts +14 -0
- package/lib/utils/UnisatCompatibleWalletAdapterImpl.d.ts +99 -0
- package/lib/utils/XverseCompatibleWalletAdapterImpl.d.ts +80 -0
- package/lib/utils/XverseCompatibleWalletAdapterImpl_legacy.d.ts +44 -0
- package/lib/utils/bitcoinAddressHelpers.d.ts +14 -0
- package/lib/utils/bitcoinNetworkHelpers.d.ts +4 -0
- package/lib/utils/createAdapterAvailability.d.ts +15 -0
- package/lib/utils/error.d.ts +6 -0
- package/lib/utils/misc.d.ts +3 -0
- package/lib/xverse-IKOHyGi-.js +2 -0
- package/lib/xverse-IKOHyGi-.js.map +1 -0
- package/lib/xverse-iHLNanCB.mjs +5 -0
- package/lib/xverse-iHLNanCB.mjs.map +1 -0
- package/package.json +86 -0
- package/src/BitcoinConnectionProvider.stories.tsx +329 -0
- package/src/BitcoinConnectionProvider.tsx +234 -0
- package/src/BitcoinWalletAdapterConnector.ts +166 -0
- package/src/WalletAdapters.types.ts +154 -0
- package/src/_/bitget.png +0 -0
- package/src/_/leather.svg +4 -0
- package/src/_/magiceden.png +0 -0
- package/src/_/okx.png +0 -0
- package/src/_/unisat.svg +31 -0
- package/src/_/xverse.png +0 -0
- package/src/adapters/BitgetWalletAdapter.impl.ts +22 -0
- package/src/adapters/BitgetWalletAdapter.ts +44 -0
- package/src/adapters/LeatherWalletAdapter.impl.ts +324 -0
- package/src/adapters/LeatherWalletAdapter.ts +35 -0
- package/src/adapters/MagicEdenWalletAdapter.impl.ts +139 -0
- package/src/adapters/MagicEdenWalletAdapter.ts +51 -0
- package/src/adapters/MockAddressWalletAdapter.ts +199 -0
- package/src/adapters/OkxWalletAdapter.impl.ts +168 -0
- package/src/adapters/OkxWalletAdapter.ts +37 -0
- package/src/adapters/UnisatWalletAdapter.impl.ts +32 -0
- package/src/adapters/UnisatWalletAdapter.ts +50 -0
- package/src/adapters/XverseWalletAdapter.impl.ts +150 -0
- package/src/adapters/XverseWalletAdapter.ts +37 -0
- package/src/adapters/index.ts +7 -0
- package/src/env.d.ts +9 -0
- package/src/index.ts +3 -0
- package/src/react.ts +9 -0
- package/src/utils/StateChannel.ts +39 -0
- package/src/utils/UnisatCompatibleWalletAdapterImpl.ts +342 -0
- package/src/utils/XverseCompatibleWalletAdapterImpl.ts +288 -0
- package/src/utils/XverseCompatibleWalletAdapterImpl_legacy.ts +278 -0
- package/src/utils/bitcoinAddressHelpers.ts +132 -0
- package/src/utils/bitcoinNetworkHelpers.ts +17 -0
- package/src/utils/createAdapterAvailability.ts +92 -0
- package/src/utils/error.ts +13 -0
- package/src/utils/misc.ts +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# @c4/bitcoin-wallet-adapters
|
|
2
|
+
|
|
3
|
+
A unified interface for interacting with multiple Bitcoin wallet browser extensions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This library is carefully designed with a focus on **API compatibility** and **dependency security**.
|
|
8
|
+
|
|
9
|
+
### Unified API
|
|
10
|
+
|
|
11
|
+
- **Normalizes wallet differences** - Each Bitcoin wallet has its own unique API. This library provides a consistent interface across all supported wallets, so you can write your code once and support multiple wallets.
|
|
12
|
+
- **Auto-discovery** - Automatically detects which wallet extensions are installed in the user's browser and makes them available for connection.
|
|
13
|
+
|
|
14
|
+
### Security-First Design
|
|
15
|
+
|
|
16
|
+
- **Minimal dependencies** - All dependencies are declared as peer dependencies, not bundled. This means you install them directly in your project and have full control over their versions. If a security vulnerability is discovered, you can upgrade immediately without waiting for this library to release an update.
|
|
17
|
+
- **Optional wallet SDKs** - Wallet SDKs (like `sats-connect` or `@leather.io/rpc`) are optional peer dependencies. You only need to install them if you use the corresponding adapter.
|
|
18
|
+
- **Lazy loading via dynamic imports** - Wallet SDKs are loaded via `dynamic import()` only when the user attempts to connect to that specific wallet. Even if a supply chain attack compromises an optional SDK, it won't be loaded unless the user explicitly tries to connect to that wallet.
|
|
19
|
+
|
|
20
|
+
## Supported Wallets
|
|
21
|
+
|
|
22
|
+
| Wallet | Adapter | Optional Dependency |
|
|
23
|
+
| ------------------------------------------ | ------------------------------- | ------------------- |
|
|
24
|
+
| [Unisat](https://unisat.io/) | `UnisatWalletAdapter` | - |
|
|
25
|
+
| [Xverse](https://www.xverse.app/) | `XverseWalletAdapter` | `sats-connect` |
|
|
26
|
+
| [OKX](https://www.okx.com/web3) | `OkxWalletAdapter` | - |
|
|
27
|
+
| [Leather](https://leather.io/) | `LeatherWalletAdapter` | `@leather.io/rpc` |
|
|
28
|
+
| [Bitget](https://web3.bitget.com/) | `BitgetWalletAdapter` | - |
|
|
29
|
+
| [Magic Eden](https://wallet.magiceden.io/) | `MagicEdenWalletAdapterFactory` | `sats-connect` |
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add @c4/bitcoin-wallet-adapters @scure/base @scure/btc-signer
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Optional Dependencies
|
|
38
|
+
|
|
39
|
+
Install based on which wallets you need to support:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# For Xverse / Magic Eden wallet support
|
|
43
|
+
pnpm add sats-connect
|
|
44
|
+
|
|
45
|
+
# For Leather wallet support
|
|
46
|
+
pnpm add @leather.io/rpc
|
|
47
|
+
|
|
48
|
+
# For React integration
|
|
49
|
+
pnpm add react
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
### Basic Usage (Vanilla JS/TS)
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import {
|
|
58
|
+
BitcoinWalletAdapterConnector,
|
|
59
|
+
UnisatWalletAdapter,
|
|
60
|
+
XverseWalletAdapter,
|
|
61
|
+
} from "@c4/bitcoin-wallet-adapters"
|
|
62
|
+
|
|
63
|
+
const connector = new BitcoinWalletAdapterConnector([
|
|
64
|
+
UnisatWalletAdapter,
|
|
65
|
+
XverseWalletAdapter,
|
|
66
|
+
])
|
|
67
|
+
|
|
68
|
+
// Get available wallets
|
|
69
|
+
const availableAdapters = connector.getAvailableAdapters()
|
|
70
|
+
// => [['unisat', adapter], ['xverse', adapter], ...]
|
|
71
|
+
|
|
72
|
+
// Connect to a wallet
|
|
73
|
+
const [adapterId, adapter] = availableAdapters[0]
|
|
74
|
+
await connector.connect(adapterId, adapter)
|
|
75
|
+
|
|
76
|
+
// Get addresses
|
|
77
|
+
const addresses = await adapter.getAddresses()
|
|
78
|
+
|
|
79
|
+
// Sign a message
|
|
80
|
+
const result = await adapter.signMessage(addresses[0].address, "Hello Bitcoin!")
|
|
81
|
+
|
|
82
|
+
// Disconnect
|
|
83
|
+
await connector.disconnect()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### React Integration
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import {
|
|
90
|
+
BitcoinConnectionProvider,
|
|
91
|
+
useBitcoinConnectionContext,
|
|
92
|
+
} from "@c4/bitcoin-wallet-adapters/react"
|
|
93
|
+
import {
|
|
94
|
+
UnisatWalletAdapter,
|
|
95
|
+
XverseWalletAdapter,
|
|
96
|
+
} from "@c4/bitcoin-wallet-adapters/adapters"
|
|
97
|
+
|
|
98
|
+
const adapterFactories = [UnisatWalletAdapter, XverseWalletAdapter]
|
|
99
|
+
|
|
100
|
+
function App() {
|
|
101
|
+
return (
|
|
102
|
+
<BitcoinConnectionProvider
|
|
103
|
+
adapterFactories={adapterFactories}
|
|
104
|
+
onWalletConnected={session => console.log("Connected:", session)}
|
|
105
|
+
onWalletDisconnected={() => console.log("Disconnected")}
|
|
106
|
+
>
|
|
107
|
+
<WalletUI />
|
|
108
|
+
</BitcoinConnectionProvider>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function WalletUI() {
|
|
113
|
+
const {
|
|
114
|
+
walletSession,
|
|
115
|
+
isConnectionInitializing,
|
|
116
|
+
availableAdapters,
|
|
117
|
+
connect,
|
|
118
|
+
disconnect,
|
|
119
|
+
} = useBitcoinConnectionContext()
|
|
120
|
+
|
|
121
|
+
if (walletSession) {
|
|
122
|
+
return (
|
|
123
|
+
<div>
|
|
124
|
+
<p>Connected: {walletSession.adapterId}</p>
|
|
125
|
+
<button onClick={() => disconnect()}>Disconnect</button>
|
|
126
|
+
</div>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<div>
|
|
132
|
+
{availableAdapters.map(([adapterId, adapter]) => (
|
|
133
|
+
<button
|
|
134
|
+
key={adapterId}
|
|
135
|
+
onClick={() => connect(adapterId, adapter)}
|
|
136
|
+
disabled={isConnectionInitializing}
|
|
137
|
+
>
|
|
138
|
+
Connect {adapterId}
|
|
139
|
+
</button>
|
|
140
|
+
))}
|
|
141
|
+
</div>
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## API
|
|
147
|
+
|
|
148
|
+
### WalletAdapter Interface
|
|
149
|
+
|
|
150
|
+
All adapters implement the following interface:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
interface WalletAdapter {
|
|
154
|
+
connect(): Promise<void>
|
|
155
|
+
disconnect(): Promise<void>
|
|
156
|
+
getAddresses(): Promise<WalletAdapterAddress[]>
|
|
157
|
+
onAddressesChanged(callback): { unsubscribe: () => void }
|
|
158
|
+
signMessage(address: string, message: string): Promise<SignMessageResult>
|
|
159
|
+
sendBitcoin(
|
|
160
|
+
fromAddress: string,
|
|
161
|
+
receiverAddress: string,
|
|
162
|
+
satoshiAmount: bigint,
|
|
163
|
+
options?: { feeRate?: number },
|
|
164
|
+
): Promise<{ txid: string }>
|
|
165
|
+
signAndFinalizePsbt(
|
|
166
|
+
psbtHex: string,
|
|
167
|
+
signIndices: [address: string, signIndex: number][],
|
|
168
|
+
): Promise<{ signedPsbtHex: string }>
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Address Types
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
enum WalletAdapterAddressType {
|
|
176
|
+
P2SH_P2WPKH = "p2sh-p2wpkh", // Nested SegWit
|
|
177
|
+
P2WPKH = "p2wpkh", // Native SegWit
|
|
178
|
+
P2TR = "p2tr", // Taproot
|
|
179
|
+
P2PKH = "p2pkh", // Legacy
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
enum WalletAdapterAddressPurpose {
|
|
183
|
+
Bitcoin = "bitcoin",
|
|
184
|
+
Ordinals = "ordinals",
|
|
185
|
+
BRC20 = "brc20",
|
|
186
|
+
Runes = "runes",
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Development
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Install dependencies
|
|
194
|
+
pnpm install
|
|
195
|
+
|
|
196
|
+
# Build
|
|
197
|
+
pnpm build
|
|
198
|
+
|
|
199
|
+
# Run Storybook
|
|
200
|
+
pnpm storybook
|
|
201
|
+
|
|
202
|
+
# Run tests
|
|
203
|
+
pnpm test
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { WalletAdapter, WalletAdapterAddress, WalletAdapterStatic } from './WalletAdapters.types';
|
|
3
|
+
export interface WalletSession {
|
|
4
|
+
adapterId: string;
|
|
5
|
+
adapter: WalletAdapter;
|
|
6
|
+
addresses: WalletAdapterAddress[];
|
|
7
|
+
}
|
|
8
|
+
export interface BitcoinConnectionContextValue {
|
|
9
|
+
walletSession: null | WalletSession;
|
|
10
|
+
isConnectionInitializing: boolean;
|
|
11
|
+
connect: (adapterId: string, adapter: WalletAdapter) => Promise<void>;
|
|
12
|
+
disconnect: () => Promise<void>;
|
|
13
|
+
adapterFactories: WalletAdapterStatic<WalletAdapter>[];
|
|
14
|
+
availableAdapters: (readonly [adapterId: string, adapter: WalletAdapter])[];
|
|
15
|
+
}
|
|
16
|
+
export declare const BitcoinConnectionProvider: FC<{
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
adapterFactories: WalletAdapterStatic<WalletAdapter>[];
|
|
19
|
+
onWalletConnected?: (session: WalletSession) => void;
|
|
20
|
+
onWalletAddressesChanged?: (addresses: WalletAdapterAddress[]) => void;
|
|
21
|
+
onWalletDisconnected?: () => void;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function useBitcoinConnectionContext(): BitcoinConnectionContextValue;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { B as u, d } from "./WalletAdapters.types-CnvOqHFH.mjs";
|
|
2
|
+
class i {
|
|
3
|
+
constructor(t) {
|
|
4
|
+
this.value = t;
|
|
5
|
+
}
|
|
6
|
+
listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
getValue() {
|
|
8
|
+
return this.value;
|
|
9
|
+
}
|
|
10
|
+
setValue(t) {
|
|
11
|
+
this.value = t, this.emit();
|
|
12
|
+
}
|
|
13
|
+
update(t) {
|
|
14
|
+
this.setValue(t(this.value));
|
|
15
|
+
}
|
|
16
|
+
subscribe(t) {
|
|
17
|
+
return this.listeners.add(t), t(this.value), {
|
|
18
|
+
unsubscribe: () => {
|
|
19
|
+
this.listeners.delete(t);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
emit() {
|
|
24
|
+
for (const t of this.listeners)
|
|
25
|
+
t(this.value);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const r = "app:BitcoinWalletAdapterConnector:previousConnectWallet";
|
|
29
|
+
class h {
|
|
30
|
+
constructor(t) {
|
|
31
|
+
this.Adapters = t, this.adapterOrder = new Map(
|
|
32
|
+
t.map((e, a) => [e.adapterId, a])
|
|
33
|
+
), this.initializeAdapterAvailability();
|
|
34
|
+
}
|
|
35
|
+
availableAdaptersState = new i([]);
|
|
36
|
+
connectedInfoState = new i(null);
|
|
37
|
+
autoConnectRunning = !1;
|
|
38
|
+
availabilitySubscriptions = [];
|
|
39
|
+
adapterOrder = /* @__PURE__ */ new Map();
|
|
40
|
+
dispose() {
|
|
41
|
+
this.availabilitySubscriptions.forEach((t) => t.unsubscribe()), this.availabilitySubscriptions = [], this.availableAdaptersState = new i([]), this.connectedInfoState = new i(null);
|
|
42
|
+
}
|
|
43
|
+
subscribeAvailableAdapters(t) {
|
|
44
|
+
return this.availableAdaptersState.subscribe(t);
|
|
45
|
+
}
|
|
46
|
+
getAvailableAdapters() {
|
|
47
|
+
return this.availableAdaptersState.getValue();
|
|
48
|
+
}
|
|
49
|
+
subscribeConnectedInfo(t) {
|
|
50
|
+
return this.connectedInfoState.subscribe(t);
|
|
51
|
+
}
|
|
52
|
+
getConnectedInfo() {
|
|
53
|
+
return this.connectedInfoState.getValue();
|
|
54
|
+
}
|
|
55
|
+
initializeAdapterAvailability() {
|
|
56
|
+
this.availabilitySubscriptions = this.Adapters.map((t) => t.getAdapter().subscribe((e) => {
|
|
57
|
+
this.addOrUpdateAvailableAdapter(t.adapterId, e);
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
addOrUpdateAvailableAdapter(t, e) {
|
|
61
|
+
this.availableAdaptersState.update((a) => {
|
|
62
|
+
const n = [...a], o = a.findIndex(([s]) => s === t);
|
|
63
|
+
return o === -1 ? n.push([t, e]) : n[o] = [t, e], n.sort(
|
|
64
|
+
(s, c) => (this.adapterOrder.get(s[0]) ?? Number.MAX_SAFE_INTEGER) - (this.adapterOrder.get(c[0]) ?? Number.MAX_SAFE_INTEGER)
|
|
65
|
+
), n;
|
|
66
|
+
}), this.autoConnect();
|
|
67
|
+
}
|
|
68
|
+
async connect(t, e) {
|
|
69
|
+
const a = e;
|
|
70
|
+
await a.connect().catch((n) => {
|
|
71
|
+
if (n instanceof u) {
|
|
72
|
+
alert(n.message);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
throw n;
|
|
76
|
+
}), localStorage.setItem(
|
|
77
|
+
r,
|
|
78
|
+
t
|
|
79
|
+
), this.connectedInfoState.setValue({ adapterId: t, adapter: a });
|
|
80
|
+
}
|
|
81
|
+
async disconnect() {
|
|
82
|
+
const t = this.connectedInfoState.getValue();
|
|
83
|
+
t != null && (await this.disconnectAdapter(t.adapter), this.connectedInfoState.setValue(null));
|
|
84
|
+
}
|
|
85
|
+
async disconnectAdapter(t) {
|
|
86
|
+
await t.disconnect(), localStorage.removeItem(r);
|
|
87
|
+
}
|
|
88
|
+
async autoConnect() {
|
|
89
|
+
if (this.isConnected || this.autoConnectRunning) return;
|
|
90
|
+
const t = this.previousConnectedWallet;
|
|
91
|
+
if (t == null) return;
|
|
92
|
+
const e = this.availableAdaptersState.getValue().find((a) => a[0] === t)?.[1];
|
|
93
|
+
if (e != null) {
|
|
94
|
+
this.autoConnectRunning = !0;
|
|
95
|
+
try {
|
|
96
|
+
await e.getAddresses();
|
|
97
|
+
} catch (a) {
|
|
98
|
+
if (a instanceof d) {
|
|
99
|
+
this.autoConnectRunning = !1;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
throw this.autoConnectRunning = !1, a;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
await this.connect(t, e);
|
|
106
|
+
} finally {
|
|
107
|
+
this.autoConnectRunning = !1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
get previousConnectedWallet() {
|
|
112
|
+
const t = localStorage.getItem(r) || void 0;
|
|
113
|
+
if (this.Adapters.some((e) => e.adapterId === t))
|
|
114
|
+
return t;
|
|
115
|
+
}
|
|
116
|
+
get isConnected() {
|
|
117
|
+
return this.connectedInfoState.getValue() != null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
h as B
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=BitcoinWalletAdapterConnector-Bq835yj0.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitcoinWalletAdapterConnector-Bq835yj0.mjs","sources":["../src/utils/StateChannel.ts","../src/BitcoinWalletAdapterConnector.ts"],"sourcesContent":["export type StateChannelListener<T> = (value: T) => void\n\nexport interface StateChannelSubscription {\n unsubscribe: () => void\n}\n\nexport class StateChannel<T> {\n private listeners = new Set<StateChannelListener<T>>()\n constructor(private value: T) {}\n\n getValue(): T {\n return this.value\n }\n\n setValue(value: T): void {\n this.value = value\n this.emit()\n }\n\n update(updater: (current: T) => T): void {\n this.setValue(updater(this.value))\n }\n\n subscribe(listener: StateChannelListener<T>): StateChannelSubscription {\n this.listeners.add(listener)\n listener(this.value)\n return {\n unsubscribe: () => {\n this.listeners.delete(listener)\n },\n }\n }\n\n private emit(): void {\n for (const listener of this.listeners) {\n listener(this.value)\n }\n }\n}\n","import { AvailabilitySubscription } from \"./utils/createAdapterAvailability\"\nimport { BitcoinWalletAdapterError } from \"./utils/error\"\nimport { StateChannel, StateChannelListener } from \"./utils/StateChannel\"\nimport {\n WalletAdapter,\n WalletAdapterNotConnectedError,\n WalletAdapterStatic,\n} from \"./WalletAdapters.types\"\n\nconst previousConnectWalletAdapterIdLocalStorageKey =\n \"app:BitcoinWalletAdapterConnector:previousConnectWallet\"\n\nexport interface ConnectInfo {\n adapterId: string\n adapter: WalletAdapter\n}\n\nexport type AdapterEntry = readonly [string, WalletAdapter]\n\nexport class BitcoinWalletAdapterConnector {\n private availableAdaptersState = new StateChannel<AdapterEntry[]>([])\n private connectedInfoState = new StateChannel<null | ConnectInfo>(null)\n private autoConnectRunning = false\n private availabilitySubscriptions: AvailabilitySubscription[] = []\n private adapterOrder = new Map<string, number>()\n\n constructor(private Adapters: WalletAdapterStatic<WalletAdapter>[]) {\n this.adapterOrder = new Map(\n Adapters.map((adapter, index) => [adapter.adapterId, index]),\n )\n this.initializeAdapterAvailability()\n }\n\n dispose(): void {\n this.availabilitySubscriptions.forEach(s => s.unsubscribe())\n this.availabilitySubscriptions = []\n this.availableAdaptersState = new StateChannel<AdapterEntry[]>([])\n this.connectedInfoState = new StateChannel<null | ConnectInfo>(null)\n }\n\n subscribeAvailableAdapters(\n listener: StateChannelListener<AdapterEntry[]>,\n ): AvailabilitySubscription {\n return this.availableAdaptersState.subscribe(listener)\n }\n getAvailableAdapters(): AdapterEntry[] {\n return this.availableAdaptersState.getValue()\n }\n\n subscribeConnectedInfo(\n listener: StateChannelListener<null | ConnectInfo>,\n ): AvailabilitySubscription {\n return this.connectedInfoState.subscribe(listener)\n }\n getConnectedInfo(): null | ConnectInfo {\n return this.connectedInfoState.getValue()\n }\n\n private initializeAdapterAvailability(): void {\n this.availabilitySubscriptions = this.Adapters.map(Adapter => {\n return Adapter.getAdapter().subscribe(adapter => {\n this.addOrUpdateAvailableAdapter(Adapter.adapterId, adapter)\n })\n })\n }\n\n private addOrUpdateAvailableAdapter(\n adapterId: string,\n adapter: WalletAdapter,\n ): void {\n this.availableAdaptersState.update(current => {\n const next = [...current]\n const existingIndex = current.findIndex(([id]) => id === adapterId)\n if (existingIndex === -1) {\n next.push([adapterId, adapter] as const)\n } else {\n next[existingIndex] = [adapterId, adapter] as const\n }\n\n next.sort(\n (a, b) =>\n (this.adapterOrder.get(a[0]) ?? Number.MAX_SAFE_INTEGER) -\n (this.adapterOrder.get(b[0]) ?? Number.MAX_SAFE_INTEGER),\n )\n return next\n })\n\n void this.autoConnect()\n }\n\n async connect(adapterId: string, adapter: WalletAdapter): Promise<void> {\n const finalAdapter = adapter\n\n await finalAdapter.connect().catch(err => {\n if (err instanceof BitcoinWalletAdapterError) {\n alert(err.message)\n return\n }\n throw err\n })\n\n localStorage.setItem(\n previousConnectWalletAdapterIdLocalStorageKey,\n adapterId,\n )\n\n this.connectedInfoState.setValue({ adapterId, adapter: finalAdapter })\n }\n\n async disconnect(): Promise<void> {\n const info = this.connectedInfoState.getValue()\n if (info == null) return\n await this.disconnectAdapter(info.adapter)\n this.connectedInfoState.setValue(null)\n }\n private async disconnectAdapter(adapter: WalletAdapter): Promise<void> {\n await adapter.disconnect()\n localStorage.removeItem(previousConnectWalletAdapterIdLocalStorageKey)\n }\n\n private async autoConnect(): Promise<void> {\n if (this.isConnected || this.autoConnectRunning) return\n\n const previousAdapterId = this.previousConnectedWallet\n if (previousAdapterId == null) return\n\n const adapter = this.availableAdaptersState\n .getValue()\n .find(a => a[0] === previousAdapterId)?.[1]\n if (adapter == null) return\n\n this.autoConnectRunning = true\n try {\n await adapter.getAddresses()\n } catch (err: unknown) {\n if (err instanceof WalletAdapterNotConnectedError) {\n this.autoConnectRunning = false\n return\n }\n\n this.autoConnectRunning = false\n throw err\n }\n\n try {\n await this.connect(previousAdapterId, adapter)\n } finally {\n this.autoConnectRunning = false\n }\n }\n\n private get previousConnectedWallet(): string | undefined {\n const adapterId =\n localStorage.getItem(previousConnectWalletAdapterIdLocalStorageKey) ||\n undefined\n\n if (this.Adapters.some(adapter => adapter.adapterId === adapterId)) {\n return adapterId\n }\n return undefined\n }\n\n private get isConnected(): boolean {\n return this.connectedInfoState.getValue() != null\n }\n}\n"],"names":["StateChannel","value","updater","listener","previousConnectWalletAdapterIdLocalStorageKey","BitcoinWalletAdapterConnector","Adapters","adapter","index","s","Adapter","adapterId","current","next","existingIndex","id","a","b","finalAdapter","err","BitcoinWalletAdapterError","info","previousAdapterId","WalletAdapterNotConnectedError"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const l=require("./WalletAdapters.types-De_x1lzr.js");class i{constructor(t){this.value=t}listeners=new Set;getValue(){return this.value}setValue(t){this.value=t,this.emit()}update(t){this.setValue(t(this.value))}subscribe(t){return this.listeners.add(t),t(this.value),{unsubscribe:()=>{this.listeners.delete(t)}}}emit(){for(const t of this.listeners)t(this.value)}}const r="app:BitcoinWalletAdapterConnector:previousConnectWallet";class d{constructor(t){this.Adapters=t,this.adapterOrder=new Map(t.map((e,a)=>[e.adapterId,a])),this.initializeAdapterAvailability()}availableAdaptersState=new i([]);connectedInfoState=new i(null);autoConnectRunning=!1;availabilitySubscriptions=[];adapterOrder=new Map;dispose(){this.availabilitySubscriptions.forEach(t=>t.unsubscribe()),this.availabilitySubscriptions=[],this.availableAdaptersState=new i([]),this.connectedInfoState=new i(null)}subscribeAvailableAdapters(t){return this.availableAdaptersState.subscribe(t)}getAvailableAdapters(){return this.availableAdaptersState.getValue()}subscribeConnectedInfo(t){return this.connectedInfoState.subscribe(t)}getConnectedInfo(){return this.connectedInfoState.getValue()}initializeAdapterAvailability(){this.availabilitySubscriptions=this.Adapters.map(t=>t.getAdapter().subscribe(e=>{this.addOrUpdateAvailableAdapter(t.adapterId,e)}))}addOrUpdateAvailableAdapter(t,e){this.availableAdaptersState.update(a=>{const n=[...a],o=a.findIndex(([s])=>s===t);return o===-1?n.push([t,e]):n[o]=[t,e],n.sort((s,u)=>(this.adapterOrder.get(s[0])??Number.MAX_SAFE_INTEGER)-(this.adapterOrder.get(u[0])??Number.MAX_SAFE_INTEGER)),n}),this.autoConnect()}async connect(t,e){const a=e;await a.connect().catch(n=>{if(n instanceof l.BitcoinWalletAdapterError){alert(n.message);return}throw n}),localStorage.setItem(r,t),this.connectedInfoState.setValue({adapterId:t,adapter:a})}async disconnect(){const t=this.connectedInfoState.getValue();t!=null&&(await this.disconnectAdapter(t.adapter),this.connectedInfoState.setValue(null))}async disconnectAdapter(t){await t.disconnect(),localStorage.removeItem(r)}async autoConnect(){if(this.isConnected||this.autoConnectRunning)return;const t=this.previousConnectedWallet;if(t==null)return;const e=this.availableAdaptersState.getValue().find(a=>a[0]===t)?.[1];if(e!=null){this.autoConnectRunning=!0;try{await e.getAddresses()}catch(a){if(a instanceof l.WalletAdapterNotConnectedError){this.autoConnectRunning=!1;return}throw this.autoConnectRunning=!1,a}try{await this.connect(t,e)}finally{this.autoConnectRunning=!1}}}get previousConnectedWallet(){const t=localStorage.getItem(r)||void 0;if(this.Adapters.some(e=>e.adapterId===t))return t}get isConnected(){return this.connectedInfoState.getValue()!=null}}exports.BitcoinWalletAdapterConnector=d;
|
|
2
|
+
//# sourceMappingURL=BitcoinWalletAdapterConnector-DMef0iHV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitcoinWalletAdapterConnector-DMef0iHV.js","sources":["../src/utils/StateChannel.ts","../src/BitcoinWalletAdapterConnector.ts"],"sourcesContent":["export type StateChannelListener<T> = (value: T) => void\n\nexport interface StateChannelSubscription {\n unsubscribe: () => void\n}\n\nexport class StateChannel<T> {\n private listeners = new Set<StateChannelListener<T>>()\n constructor(private value: T) {}\n\n getValue(): T {\n return this.value\n }\n\n setValue(value: T): void {\n this.value = value\n this.emit()\n }\n\n update(updater: (current: T) => T): void {\n this.setValue(updater(this.value))\n }\n\n subscribe(listener: StateChannelListener<T>): StateChannelSubscription {\n this.listeners.add(listener)\n listener(this.value)\n return {\n unsubscribe: () => {\n this.listeners.delete(listener)\n },\n }\n }\n\n private emit(): void {\n for (const listener of this.listeners) {\n listener(this.value)\n }\n }\n}\n","import { AvailabilitySubscription } from \"./utils/createAdapterAvailability\"\nimport { BitcoinWalletAdapterError } from \"./utils/error\"\nimport { StateChannel, StateChannelListener } from \"./utils/StateChannel\"\nimport {\n WalletAdapter,\n WalletAdapterNotConnectedError,\n WalletAdapterStatic,\n} from \"./WalletAdapters.types\"\n\nconst previousConnectWalletAdapterIdLocalStorageKey =\n \"app:BitcoinWalletAdapterConnector:previousConnectWallet\"\n\nexport interface ConnectInfo {\n adapterId: string\n adapter: WalletAdapter\n}\n\nexport type AdapterEntry = readonly [string, WalletAdapter]\n\nexport class BitcoinWalletAdapterConnector {\n private availableAdaptersState = new StateChannel<AdapterEntry[]>([])\n private connectedInfoState = new StateChannel<null | ConnectInfo>(null)\n private autoConnectRunning = false\n private availabilitySubscriptions: AvailabilitySubscription[] = []\n private adapterOrder = new Map<string, number>()\n\n constructor(private Adapters: WalletAdapterStatic<WalletAdapter>[]) {\n this.adapterOrder = new Map(\n Adapters.map((adapter, index) => [adapter.adapterId, index]),\n )\n this.initializeAdapterAvailability()\n }\n\n dispose(): void {\n this.availabilitySubscriptions.forEach(s => s.unsubscribe())\n this.availabilitySubscriptions = []\n this.availableAdaptersState = new StateChannel<AdapterEntry[]>([])\n this.connectedInfoState = new StateChannel<null | ConnectInfo>(null)\n }\n\n subscribeAvailableAdapters(\n listener: StateChannelListener<AdapterEntry[]>,\n ): AvailabilitySubscription {\n return this.availableAdaptersState.subscribe(listener)\n }\n getAvailableAdapters(): AdapterEntry[] {\n return this.availableAdaptersState.getValue()\n }\n\n subscribeConnectedInfo(\n listener: StateChannelListener<null | ConnectInfo>,\n ): AvailabilitySubscription {\n return this.connectedInfoState.subscribe(listener)\n }\n getConnectedInfo(): null | ConnectInfo {\n return this.connectedInfoState.getValue()\n }\n\n private initializeAdapterAvailability(): void {\n this.availabilitySubscriptions = this.Adapters.map(Adapter => {\n return Adapter.getAdapter().subscribe(adapter => {\n this.addOrUpdateAvailableAdapter(Adapter.adapterId, adapter)\n })\n })\n }\n\n private addOrUpdateAvailableAdapter(\n adapterId: string,\n adapter: WalletAdapter,\n ): void {\n this.availableAdaptersState.update(current => {\n const next = [...current]\n const existingIndex = current.findIndex(([id]) => id === adapterId)\n if (existingIndex === -1) {\n next.push([adapterId, adapter] as const)\n } else {\n next[existingIndex] = [adapterId, adapter] as const\n }\n\n next.sort(\n (a, b) =>\n (this.adapterOrder.get(a[0]) ?? Number.MAX_SAFE_INTEGER) -\n (this.adapterOrder.get(b[0]) ?? Number.MAX_SAFE_INTEGER),\n )\n return next\n })\n\n void this.autoConnect()\n }\n\n async connect(adapterId: string, adapter: WalletAdapter): Promise<void> {\n const finalAdapter = adapter\n\n await finalAdapter.connect().catch(err => {\n if (err instanceof BitcoinWalletAdapterError) {\n alert(err.message)\n return\n }\n throw err\n })\n\n localStorage.setItem(\n previousConnectWalletAdapterIdLocalStorageKey,\n adapterId,\n )\n\n this.connectedInfoState.setValue({ adapterId, adapter: finalAdapter })\n }\n\n async disconnect(): Promise<void> {\n const info = this.connectedInfoState.getValue()\n if (info == null) return\n await this.disconnectAdapter(info.adapter)\n this.connectedInfoState.setValue(null)\n }\n private async disconnectAdapter(adapter: WalletAdapter): Promise<void> {\n await adapter.disconnect()\n localStorage.removeItem(previousConnectWalletAdapterIdLocalStorageKey)\n }\n\n private async autoConnect(): Promise<void> {\n if (this.isConnected || this.autoConnectRunning) return\n\n const previousAdapterId = this.previousConnectedWallet\n if (previousAdapterId == null) return\n\n const adapter = this.availableAdaptersState\n .getValue()\n .find(a => a[0] === previousAdapterId)?.[1]\n if (adapter == null) return\n\n this.autoConnectRunning = true\n try {\n await adapter.getAddresses()\n } catch (err: unknown) {\n if (err instanceof WalletAdapterNotConnectedError) {\n this.autoConnectRunning = false\n return\n }\n\n this.autoConnectRunning = false\n throw err\n }\n\n try {\n await this.connect(previousAdapterId, adapter)\n } finally {\n this.autoConnectRunning = false\n }\n }\n\n private get previousConnectedWallet(): string | undefined {\n const adapterId =\n localStorage.getItem(previousConnectWalletAdapterIdLocalStorageKey) ||\n undefined\n\n if (this.Adapters.some(adapter => adapter.adapterId === adapterId)) {\n return adapterId\n }\n return undefined\n }\n\n private get isConnected(): boolean {\n return this.connectedInfoState.getValue() != null\n }\n}\n"],"names":["StateChannel","value","updater","listener","previousConnectWalletAdapterIdLocalStorageKey","BitcoinWalletAdapterConnector","Adapters","adapter","index","s","Adapter","adapterId","current","next","existingIndex","id","a","b","finalAdapter","err","BitcoinWalletAdapterError","info","previousAdapterId","WalletAdapterNotConnectedError"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AvailabilitySubscription } from './utils/createAdapterAvailability';
|
|
2
|
+
import { StateChannelListener } from './utils/StateChannel';
|
|
3
|
+
import { WalletAdapter, WalletAdapterStatic } from './WalletAdapters.types';
|
|
4
|
+
export interface ConnectInfo {
|
|
5
|
+
adapterId: string;
|
|
6
|
+
adapter: WalletAdapter;
|
|
7
|
+
}
|
|
8
|
+
export type AdapterEntry = readonly [string, WalletAdapter];
|
|
9
|
+
export declare class BitcoinWalletAdapterConnector {
|
|
10
|
+
private Adapters;
|
|
11
|
+
private availableAdaptersState;
|
|
12
|
+
private connectedInfoState;
|
|
13
|
+
private autoConnectRunning;
|
|
14
|
+
private availabilitySubscriptions;
|
|
15
|
+
private adapterOrder;
|
|
16
|
+
constructor(Adapters: WalletAdapterStatic<WalletAdapter>[]);
|
|
17
|
+
dispose(): void;
|
|
18
|
+
subscribeAvailableAdapters(listener: StateChannelListener<AdapterEntry[]>): AvailabilitySubscription;
|
|
19
|
+
getAvailableAdapters(): AdapterEntry[];
|
|
20
|
+
subscribeConnectedInfo(listener: StateChannelListener<null | ConnectInfo>): AvailabilitySubscription;
|
|
21
|
+
getConnectedInfo(): null | ConnectInfo;
|
|
22
|
+
private initializeAdapterAvailability;
|
|
23
|
+
private addOrUpdateAvailableAdapter;
|
|
24
|
+
connect(adapterId: string, adapter: WalletAdapter): Promise<void>;
|
|
25
|
+
disconnect(): Promise<void>;
|
|
26
|
+
private disconnectAdapter;
|
|
27
|
+
private autoConnect;
|
|
28
|
+
private get previousConnectedWallet();
|
|
29
|
+
private get isConnected();
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitgetWalletAdapter.impl-C_HLO7Oi.mjs","sources":["../src/adapters/BitgetWalletAdapter.impl.ts"],"sourcesContent":["import {\n UnisatCompatibleProviderAPI,\n UnisatCompatibleWalletAdapterImpl,\n} from \"../utils/UnisatCompatibleWalletAdapterImpl\"\nimport { WalletAdapter } from \"../WalletAdapters.types\"\n\n/**\n * Derivation path (BIP-44): m/44'/0'/0'/0/ address_index\n */\nexport class BitgetWalletAdapterImpl\n extends UnisatCompatibleWalletAdapterImpl\n implements WalletAdapter\n{\n constructor(provider: UnisatCompatibleProviderAPI) {\n /**\n * Bitget Provider API:\n *\n * https://web3.bitget.com/zh-CN/docs/provider-api/btc.html\n */\n super(provider, \"Bitget\")\n }\n}\n"],"names":["BitgetWalletAdapterImpl","UnisatCompatibleWalletAdapterImpl","provider"],"mappings":";AASO,MAAMA,UACHC,EAEV;AAAA,EACE,YAAYC,GAAuC;AAMjD,UAAMA,GAAU,QAAQ;AAAA,EAC1B;AACF;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./UnisatCompatibleWalletAdapterImpl-Cq2Oqk1b.js");class l extends e.UnisatCompatibleWalletAdapterImpl{constructor(t){super(t,"Bitget")}}exports.BitgetWalletAdapterImpl=l;
|
|
2
|
+
//# sourceMappingURL=BitgetWalletAdapter.impl-CxnKMf7U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitgetWalletAdapter.impl-CxnKMf7U.js","sources":["../src/adapters/BitgetWalletAdapter.impl.ts"],"sourcesContent":["import {\n UnisatCompatibleProviderAPI,\n UnisatCompatibleWalletAdapterImpl,\n} from \"../utils/UnisatCompatibleWalletAdapterImpl\"\nimport { WalletAdapter } from \"../WalletAdapters.types\"\n\n/**\n * Derivation path (BIP-44): m/44'/0'/0'/0/ address_index\n */\nexport class BitgetWalletAdapterImpl\n extends UnisatCompatibleWalletAdapterImpl\n implements WalletAdapter\n{\n constructor(provider: UnisatCompatibleProviderAPI) {\n /**\n * Bitget Provider API:\n *\n * https://web3.bitget.com/zh-CN/docs/provider-api/btc.html\n */\n super(provider, \"Bitget\")\n }\n}\n"],"names":["BitgetWalletAdapterImpl","UnisatCompatibleWalletAdapterImpl","provider"],"mappings":"mJASO,MAAMA,UACHC,EAAAA,iCAEV,CACE,YAAYC,EAAuC,CAMjD,MAAMA,EAAU,QAAQ,CAC1B,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-Zx0KcpYx.js"),r=require("./WalletAdapters.types-De_x1lzr.js"),y="LeatherProvider.BitcoinProvider",l=`app:${y}:`;class A{constructor(e){this.request=e}walletDisplayName="Leather";retrieveConnectedAddress(){let e;const s=localStorage.getItem(l)||void 0;if(s!=null)try{if(e=JSON.parse(s),e==null||!("addresses"in e)||!Array.isArray(e.addresses))throw new Error("Invalid stored addresses")}catch{localStorage.removeItem(l)}return e}async connect(){if(this.retrieveConnectedAddress()==null){const e=await o(this.request("getAddresses"));localStorage.setItem(l,JSON.stringify(e))}}async disconnect(){return localStorage.removeItem(l),Promise.resolve()}async getAddresses(){const e=this.retrieveConnectedAddress();if(e==null)throw new r.WalletAdapterNotConnectedError(this.walletDisplayName);const s=e.addresses.filter(t=>t.symbol==="BTC"&&t.type),a=s.filter(t=>t.type==="p2tr")[0].address.startsWith("bc");return s.map(t=>({network:a?r.WalletAdapterBitcoinNetwork.MAINNET:r.WalletAdapterBitcoinNetwork.TESTNET,purposes:t.type==="p2tr"?[r.WalletAdapterAddressPurpose.Ordinals,r.WalletAdapterAddressPurpose.BRC20,r.WalletAdapterAddressPurpose.Runes]:[r.WalletAdapterAddressPurpose.Bitcoin],addressType:t.type==="p2tr"?r.WalletAdapterAddressType.P2TR:r.WalletAdapterAddressType.P2WPKH,address:t.address,scriptPubKey:i.hex.encode(i.addressToScriptPubKey(i.getBitcoinNetwork(a?"mainnet":"testnet"),t.address)),publicKey:t.publicKey,tapInternalKey:t.type==="p2tr"?i.hex.encode(i.getTapInternalKeyOf_P2TR_publicKey(i.getBitcoinNetwork(a?"mainnet":"testnet"),i.hex.decode(t.publicKey))):void 0}))}async signMessage(e,s){const t=(await this.getAddresses()).find(p=>p.address===e)?.addressType,d=t===r.WalletAdapterAddressType.P2WPKH?"p2wpkh":t===r.WalletAdapterAddressType.P2TR?"p2tr":void 0;if(d==null)throw new r.BitcoinWalletAdapterError("Address is not supported");const n=await o(this.request("signMessage",{message:s,paymentType:d}));return{algorithm:n.algorithm==="ecdsa"?r.SignMessageAlgorithm.ECDSA:r.SignMessageAlgorithm.BIP322,result:n.signature,address:e,publicKey:n.publicKey}}sendBitcoinFeeRateCapability="required";async sendBitcoin(e,s,a,t){return{txid:(await o(this.request("sendBitcoin",{origin:e,destination:s,amount:a,feeRate:t?.feeRate}))).txid}}sendInscriptionFeeRateCapability="available";async sendInscription(e,s,a,t){const{txid:d}=await o(this.request("sendOrdinals",{ordinals:[{destination:s,id:a}],paymentType:"p2wpkh",sender:e,feeRate:t?.feeRate}));return{txid:d}}async signAndFinalizePsbt(e,s){const t=(await this.getAddresses()).find(n=>n.address===s[0]?.[0]);if(t==null)throw new r.WalletAdapterNotConnectedError(this.walletDisplayName);return{signedPsbtHex:(await o(this.request("signAndFinalizePsbt",{hex:e,inputsToSign:s.map(([n,p])=>({address:n,signingIndexes:[p],signatureHash:void 0,disableTweakSigner:void 0})),paymentType:t.addressType===r.WalletAdapterAddressType.P2TR?"p2tr":"p2wpkh"}))).hex}}onAddressesChanged(e){let s=!1;const a=async()=>{if(!s)try{const t=await this.getAddresses();e({addresses:t})}catch(t){if(t instanceof r.WalletAdapterNotConnectedError){s=!0;return}console.warn("[Leather] Failed to get addresses on change:",t)}finally{s||setTimeout(a,1e3)}};return setTimeout(a,1e3),{unsubscribe:()=>{s=!0}}}}class u extends r.BitcoinWalletAdapterError{constructor(e){super("Leather wallet error: "+e.error.message,{cause:e})}}const o=async c=>{try{return await c}catch(e){throw e instanceof r.UserRejectError?e:e.error?.code===4001?new r.UserRejectError:new u(e)}};exports.LeatherWalletAdapterError=u;exports.LeatherWalletAdapterImpl=A;
|
|
2
|
+
//# sourceMappingURL=LeatherWalletAdapter.impl-B2QgX_tO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LeatherWalletAdapter.impl-B2QgX_tO.js","sources":["../src/adapters/LeatherWalletAdapter.impl.ts"],"sourcesContent":["import type { RequestFn, RpcErrorBody, RpcErrorResponse } from \"@leather.io/rpc\"\nimport { hex } from \"@scure/base\"\nimport {\n addressToScriptPubKey,\n getTapInternalKeyOf_P2TR_publicKey,\n} from \"../utils/bitcoinAddressHelpers\"\nimport { getBitcoinNetwork } from \"../utils/bitcoinNetworkHelpers\"\nimport { UserRejectError, BitcoinWalletAdapterError } from \"../utils/error\"\nimport {\n SignMessageAlgorithm,\n SignMessageResult,\n WalletAdapter,\n WalletAdapter_onAddressesChanged_callback,\n WalletAdapterAddress,\n WalletAdapterAddressPurpose,\n WalletAdapterAddressType,\n WalletAdapterBitcoinNetwork,\n WalletAdapterNotConnectedError,\n} from \"../WalletAdapters.types\"\n\ntype GetAddressesResponseData = any\n\n/**\n * https://github.com/leather-io/mono/blob/a664e64040fed1c25abef1f8864a1c7fae5444c1/packages/rpc/src/rpc/schemas.ts#L64-L78\n */\nenum RpcErrorCode {\n // Spec defined server errors\n PARSE_ERROR = -32700,\n INVALID_REQUEST = -32600,\n METHOD_NOT_FOUND = -32601,\n INVALID_PARAMS = -32602,\n INTERNAL_ERROR = -32603,\n SERVER_ERROR = -32000,\n // Client defined errors\n USER_REJECTION = 4001,\n METHOD_NOT_SUPPORTED = 4002,\n // gRPC spec borrowed\n PERMISSION_DENIED = 7,\n UNAUTHENTICATED = 16,\n}\n\ntype Addresses = (WalletAdapterAddress & { publicKey: string })[]\n\nconst LEATHER_PROVIDER_ID = \"LeatherProvider.BitcoinProvider\"\n\nconst localStorageKey = `app:${LEATHER_PROVIDER_ID}:`\n\n/**\n * Derivation path (BIP-84): m/84'/0'/ account_index '/0/0\n */\nexport class LeatherWalletAdapterImpl implements WalletAdapter {\n constructor(private request: RequestFn) {}\n\n private readonly walletDisplayName = \"Leather\"\n\n private retrieveConnectedAddress(): GetAddressesResponseData | undefined {\n let resp: GetAddressesResponseData | undefined\n const stored = localStorage.getItem(localStorageKey) || undefined\n if (stored != null) {\n try {\n resp = JSON.parse(stored)\n if (\n resp == null ||\n !(\"addresses\" in resp) ||\n !Array.isArray(resp.addresses)\n ) {\n throw new Error(\"Invalid stored addresses\")\n }\n } catch {\n localStorage.removeItem(localStorageKey)\n }\n }\n return resp\n }\n\n async connect(): Promise<void> {\n if (this.retrieveConnectedAddress() == null) {\n const resp = await handleRpcError(\n /**\n * https://leather.gitbook.io/developers/bitcoin/connect-users/get-addresses\n */\n this.request(\"getAddresses\"),\n )\n localStorage.setItem(localStorageKey, JSON.stringify(resp))\n }\n }\n\n async disconnect(): Promise<void> {\n localStorage.removeItem(localStorageKey)\n return Promise.resolve()\n }\n\n async getAddresses(): Promise<Addresses> {\n const resp = this.retrieveConnectedAddress()\n\n if (resp == null) {\n throw new WalletAdapterNotConnectedError(this.walletDisplayName)\n }\n\n const addresses = resp.addresses.filter(\n (a: any) => (a as any).symbol === \"BTC\" && a.type,\n )\n\n const isMainnet = addresses\n .filter((a: any) => a.type === \"p2tr\")[0]\n .address.startsWith(\"bc\")\n\n return addresses.map((a: any) => ({\n network: isMainnet\n ? WalletAdapterBitcoinNetwork.MAINNET\n : WalletAdapterBitcoinNetwork.TESTNET,\n purposes:\n a.type === \"p2tr\"\n ? [\n WalletAdapterAddressPurpose.Ordinals,\n WalletAdapterAddressPurpose.BRC20,\n WalletAdapterAddressPurpose.Runes,\n ]\n : [WalletAdapterAddressPurpose.Bitcoin],\n addressType:\n a.type === \"p2tr\"\n ? WalletAdapterAddressType.P2TR\n : WalletAdapterAddressType.P2WPKH,\n address: a.address,\n scriptPubKey: hex.encode(\n addressToScriptPubKey(\n getBitcoinNetwork(isMainnet ? \"mainnet\" : \"testnet\"),\n a.address,\n ),\n ),\n publicKey: a.publicKey!,\n tapInternalKey:\n a.type === \"p2tr\"\n ? hex.encode(\n getTapInternalKeyOf_P2TR_publicKey(\n getBitcoinNetwork(isMainnet ? \"mainnet\" : \"testnet\"),\n hex.decode(a.publicKey!),\n ),\n )\n : undefined,\n }))\n }\n\n async signMessage(\n address: string,\n message: string,\n ): Promise<SignMessageResult> {\n const accounts = await this.getAddresses()\n\n const addressType = accounts.find(a => a.address === address)?.addressType\n\n // prettier-ignore\n const paymentType =\n addressType === WalletAdapterAddressType.P2WPKH ? 'p2wpkh' as const :\n addressType === WalletAdapterAddressType.P2TR ? 'p2tr' as const :\n undefined\n if (paymentType == null) {\n throw new BitcoinWalletAdapterError(\"Address is not supported\")\n }\n\n const resp: any = await handleRpcError(\n /**\n * https://leather.gitbook.io/developers/bitcoin-methods/signmessage\n */\n this.request(\"signMessage\", {\n message,\n paymentType,\n }),\n )\n\n return {\n algorithm:\n resp.algorithm === \"ecdsa\"\n ? SignMessageAlgorithm.ECDSA\n : SignMessageAlgorithm.BIP322,\n result: resp.signature,\n address,\n publicKey: resp.publicKey,\n }\n }\n\n sendBitcoinFeeRateCapability = \"required\" as const\n async sendBitcoin(\n fromAddress: string,\n receiverAddress: string,\n satoshiAmount: bigint,\n options?: { feeRate?: number },\n ): Promise<{ txid: string }> {\n const resp: any = await handleRpcError(\n /**\n * https://leather.gitbook.io/developers/bitcoin-methods/sendbitcoin\n */\n (this.request as any)(\"sendBitcoin\", {\n origin: fromAddress,\n destination: receiverAddress,\n amount: satoshiAmount,\n feeRate: options?.feeRate,\n }),\n )\n return { txid: resp.txid }\n }\n\n sendInscriptionFeeRateCapability = \"available\" as const\n\n async sendInscription(\n fromAddress: string,\n receiverAddress: string,\n inscriptionId: string,\n options?: { feeRate?: number },\n ): Promise<{ txid: string }> {\n const { txid }: any = await handleRpcError(\n /**\n * https://leather.gitbook.io/developers/ordinals/send-ordinals\n */\n (this.request as any)(\"sendOrdinals\", {\n ordinals: [\n {\n destination: receiverAddress,\n id: inscriptionId,\n },\n ],\n paymentType: \"p2wpkh\",\n sender: fromAddress,\n feeRate: options?.feeRate,\n }),\n )\n return { txid }\n }\n\n async signAndFinalizePsbt(\n psbtHex: string,\n signIndices: [address: string, signIndex: number][],\n ): Promise<{\n signedPsbtHex: string\n }> {\n const accounts = await this.getAddresses()\n const signingAccount = accounts.find(\n account => account.address === signIndices[0]?.[0],\n )\n if (signingAccount == null) {\n throw new WalletAdapterNotConnectedError(this.walletDisplayName)\n }\n\n const resp: any = await handleRpcError(\n /**\n * https://leather.gitbook.io/developers/bitcoin-methods/signandfinalizepsbt\n */\n (this.request as any)(\"signAndFinalizePsbt\", {\n hex: psbtHex,\n inputsToSign: signIndices.map(([address, signIndex]) => ({\n address,\n signingIndexes: [signIndex],\n signatureHash: undefined,\n disableTweakSigner: undefined,\n })),\n paymentType:\n signingAccount.addressType === WalletAdapterAddressType.P2TR\n ? \"p2tr\"\n : \"p2wpkh\",\n }),\n )\n\n return { signedPsbtHex: resp.hex }\n }\n\n onAddressesChanged(callback: WalletAdapter_onAddressesChanged_callback): {\n unsubscribe: () => void\n } {\n // Leather doesn't provide event, fallback to polling\n let stopped = false\n\n const tick = async (): Promise<void> => {\n if (stopped) return\n try {\n const addresses = await this.getAddresses()\n callback({ addresses })\n } catch (error) {\n if (error instanceof WalletAdapterNotConnectedError) {\n stopped = true\n return\n }\n console.warn(\"[Leather] Failed to get addresses on change:\", error)\n } finally {\n if (!stopped) {\n setTimeout(tick, 1000)\n }\n }\n }\n\n setTimeout(tick, 1000)\n\n return {\n unsubscribe: () => {\n stopped = true\n },\n }\n }\n}\n\nexport class LeatherWalletAdapterError extends BitcoinWalletAdapterError {\n constructor(rpcError: RpcErrorResponse<RpcErrorBody>) {\n super(\"Leather wallet error: \" + rpcError.error.message, {\n cause: rpcError,\n })\n }\n}\n\nconst handleRpcError = async <T>(\n promise: Promise<T>,\n): Promise<NonNullable<T>> => {\n try {\n return (await promise) as NonNullable<T>\n } catch (e: any) {\n if (e instanceof UserRejectError) {\n throw e\n }\n\n if (e.error?.code === RpcErrorCode.USER_REJECTION) {\n throw new UserRejectError()\n }\n\n throw new LeatherWalletAdapterError(e)\n }\n}\n"],"names":["LEATHER_PROVIDER_ID","localStorageKey","LeatherWalletAdapterImpl","request","resp","stored","handleRpcError","WalletAdapterNotConnectedError","addresses","a","isMainnet","WalletAdapterBitcoinNetwork","WalletAdapterAddressPurpose","WalletAdapterAddressType","hex","addressToScriptPubKey","getBitcoinNetwork","getTapInternalKeyOf_P2TR_publicKey","address","message","addressType","paymentType","BitcoinWalletAdapterError","SignMessageAlgorithm","fromAddress","receiverAddress","satoshiAmount","options","inscriptionId","txid","psbtHex","signIndices","signingAccount","account","signIndex","callback","stopped","tick","error","LeatherWalletAdapterError","rpcError","promise","UserRejectError"],"mappings":"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"}
|