otx-btc-wallet-connectors 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 +554 -0
- package/dist/base-IAFq7sd8.d.mts +53 -0
- package/dist/base-IAFq7sd8.d.ts +53 -0
- package/dist/binance/index.d.mts +81 -0
- package/dist/binance/index.d.ts +81 -0
- package/dist/binance/index.js +13 -0
- package/dist/binance/index.js.map +1 -0
- package/dist/binance/index.mjs +4 -0
- package/dist/binance/index.mjs.map +1 -0
- package/dist/bitget/index.d.mts +84 -0
- package/dist/bitget/index.d.ts +84 -0
- package/dist/bitget/index.js +13 -0
- package/dist/bitget/index.js.map +1 -0
- package/dist/bitget/index.mjs +4 -0
- package/dist/bitget/index.mjs.map +1 -0
- package/dist/chunk-5Z5Q2Y75.mjs +91 -0
- package/dist/chunk-5Z5Q2Y75.mjs.map +1 -0
- package/dist/chunk-7KK2LZLZ.mjs +208 -0
- package/dist/chunk-7KK2LZLZ.mjs.map +1 -0
- package/dist/chunk-AW2JZIHR.mjs +753 -0
- package/dist/chunk-AW2JZIHR.mjs.map +1 -0
- package/dist/chunk-EIJOSZXZ.js +331 -0
- package/dist/chunk-EIJOSZXZ.js.map +1 -0
- package/dist/chunk-EQHR7P7G.js +541 -0
- package/dist/chunk-EQHR7P7G.js.map +1 -0
- package/dist/chunk-EWRXLZO4.mjs +539 -0
- package/dist/chunk-EWRXLZO4.mjs.map +1 -0
- package/dist/chunk-FISNQZZ7.js +802 -0
- package/dist/chunk-FISNQZZ7.js.map +1 -0
- package/dist/chunk-HL4WDMGS.js +200 -0
- package/dist/chunk-HL4WDMGS.js.map +1 -0
- package/dist/chunk-IPYWR76I.js +314 -0
- package/dist/chunk-IPYWR76I.js.map +1 -0
- package/dist/chunk-JYYNWR5G.js +142 -0
- package/dist/chunk-JYYNWR5G.js.map +1 -0
- package/dist/chunk-LNKTYZJM.js +701 -0
- package/dist/chunk-LNKTYZJM.js.map +1 -0
- package/dist/chunk-LVZMONQL.mjs +699 -0
- package/dist/chunk-LVZMONQL.mjs.map +1 -0
- package/dist/chunk-MFXLQWOE.js +93 -0
- package/dist/chunk-MFXLQWOE.js.map +1 -0
- package/dist/chunk-NBIA4TTE.mjs +204 -0
- package/dist/chunk-NBIA4TTE.mjs.map +1 -0
- package/dist/chunk-O4DD2XJ2.js +206 -0
- package/dist/chunk-O4DD2XJ2.js.map +1 -0
- package/dist/chunk-P7HVBU2B.mjs +140 -0
- package/dist/chunk-P7HVBU2B.mjs.map +1 -0
- package/dist/chunk-Q7QVQYEB.js +210 -0
- package/dist/chunk-Q7QVQYEB.js.map +1 -0
- package/dist/chunk-RLZEG6KL.mjs +329 -0
- package/dist/chunk-RLZEG6KL.mjs.map +1 -0
- package/dist/chunk-SYLDBJ75.mjs +246 -0
- package/dist/chunk-SYLDBJ75.mjs.map +1 -0
- package/dist/chunk-TTEUU3CI.mjs +198 -0
- package/dist/chunk-TTEUU3CI.mjs.map +1 -0
- package/dist/chunk-V66BXDTR.mjs +292 -0
- package/dist/chunk-V66BXDTR.mjs.map +1 -0
- package/dist/chunk-X77ZT4OI.js +268 -0
- package/dist/chunk-X77ZT4OI.js.map +1 -0
- package/dist/imtoken/index.d.mts +116 -0
- package/dist/imtoken/index.d.ts +116 -0
- package/dist/imtoken/index.js +14 -0
- package/dist/imtoken/index.js.map +1 -0
- package/dist/imtoken/index.mjs +5 -0
- package/dist/imtoken/index.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +170 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +13 -0
- package/dist/index.mjs.map +1 -0
- package/dist/ledger/index.d.mts +290 -0
- package/dist/ledger/index.d.ts +290 -0
- package/dist/ledger/index.js +14 -0
- package/dist/ledger/index.js.map +1 -0
- package/dist/ledger/index.mjs +5 -0
- package/dist/ledger/index.mjs.map +1 -0
- package/dist/okx/index.d.mts +88 -0
- package/dist/okx/index.d.ts +88 -0
- package/dist/okx/index.js +13 -0
- package/dist/okx/index.js.map +1 -0
- package/dist/okx/index.mjs +4 -0
- package/dist/okx/index.mjs.map +1 -0
- package/dist/phantom/index.d.mts +96 -0
- package/dist/phantom/index.d.ts +96 -0
- package/dist/phantom/index.js +14 -0
- package/dist/phantom/index.js.map +1 -0
- package/dist/phantom/index.mjs +5 -0
- package/dist/phantom/index.mjs.map +1 -0
- package/dist/psbt-builder-CFOs69Z5.d.mts +131 -0
- package/dist/psbt-builder-CFOs69Z5.d.ts +131 -0
- package/dist/trezor/index.d.mts +155 -0
- package/dist/trezor/index.d.ts +155 -0
- package/dist/trezor/index.js +14 -0
- package/dist/trezor/index.js.map +1 -0
- package/dist/trezor/index.mjs +5 -0
- package/dist/trezor/index.mjs.map +1 -0
- package/dist/unisat/index.d.mts +75 -0
- package/dist/unisat/index.d.ts +75 -0
- package/dist/unisat/index.js +13 -0
- package/dist/unisat/index.js.map +1 -0
- package/dist/unisat/index.mjs +4 -0
- package/dist/unisat/index.mjs.map +1 -0
- package/dist/utils/index.d.mts +398 -0
- package/dist/utils/index.d.ts +398 -0
- package/dist/utils/index.js +120 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +3 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/xverse/index.d.mts +79 -0
- package/dist/xverse/index.d.ts +79 -0
- package/dist/xverse/index.js +13 -0
- package/dist/xverse/index.js.map +1 -0
- package/dist/xverse/index.mjs +4 -0
- package/dist/xverse/index.mjs.map +1 -0
- package/package.json +108 -0
- package/src/base.ts +132 -0
- package/src/binance/BinanceConnector.ts +307 -0
- package/src/binance/index.ts +1 -0
- package/src/bitget/BitgetConnector.ts +301 -0
- package/src/bitget/index.ts +1 -0
- package/src/imtoken/ImTokenConnector.ts +420 -0
- package/src/imtoken/index.ts +2 -0
- package/src/index.ts +78 -0
- package/src/ledger/LedgerConnector.ts +1019 -0
- package/src/ledger/index.ts +8 -0
- package/src/okx/OKXConnector.ts +230 -0
- package/src/okx/index.ts +1 -0
- package/src/phantom/PhantomConnector.ts +381 -0
- package/src/phantom/index.ts +2 -0
- package/src/trezor/TrezorConnector.ts +824 -0
- package/src/trezor/index.ts +6 -0
- package/src/unisat/UnisatConnector.ts +312 -0
- package/src/unisat/index.ts +1 -0
- package/src/utils/blockstream.ts +230 -0
- package/src/utils/btc-service.ts +364 -0
- package/src/utils/index.ts +56 -0
- package/src/utils/mempool.ts +232 -0
- package/src/utils/psbt-builder.ts +492 -0
- package/src/utils/types.ts +183 -0
- package/src/xverse/XverseConnector.ts +479 -0
- package/src/xverse/index.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# otx-btc-wallet-connectors
|
|
2
|
+
|
|
3
|
+
Bitcoin wallet connectors, blockchain services, and PSBT utilities for the `otx-btc-wallet` library.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add otx-btc-wallet-connectors otx-btc-wallet-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Supported Wallets
|
|
12
|
+
|
|
13
|
+
| Wallet | Connector | Type | Sign PSBT | Batch PSBT | Send BTC | Network Switch |
|
|
14
|
+
|--------|-----------|------|-----------|------------|----------|----------------|
|
|
15
|
+
| Unisat | `UnisatConnector` | Extension | Yes | Yes | Yes | Yes |
|
|
16
|
+
| Xverse | `XverseConnector` | Extension | Yes | No | Yes | Yes |
|
|
17
|
+
| OKX | `OKXConnector` | Extension | Yes | No | Yes | No* |
|
|
18
|
+
| Phantom | `PhantomConnector` | Extension | Yes | No | Yes | No** |
|
|
19
|
+
| Bitget | `BitgetConnector` | Extension | Yes | No | Yes | Yes |
|
|
20
|
+
| Binance | `BinanceConnector` | Extension | Yes | No | Yes | Yes |
|
|
21
|
+
| imToken | `ImTokenConnector` | Mobile | Yes | No | Yes | Yes |
|
|
22
|
+
| Ledger | `LedgerConnector` | Hardware | No*** | No | Yes | N/A |
|
|
23
|
+
| Trezor | `TrezorConnector` | Hardware | No*** | No | Yes | N/A |
|
|
24
|
+
|
|
25
|
+
\* OKX: Users switch network in the extension manually.
|
|
26
|
+
\*\* Phantom: Only supports mainnet for Bitcoin.
|
|
27
|
+
\*\*\* Hardware wallets use `sendTransaction()` directly with built-in PSBT construction.
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import {
|
|
33
|
+
UnisatConnector,
|
|
34
|
+
XverseConnector,
|
|
35
|
+
OKXConnector,
|
|
36
|
+
PhantomConnector,
|
|
37
|
+
BitgetConnector,
|
|
38
|
+
BinanceConnector,
|
|
39
|
+
ImTokenConnector,
|
|
40
|
+
LedgerConnector,
|
|
41
|
+
TrezorConnector,
|
|
42
|
+
} from 'otx-btc-wallet-connectors';
|
|
43
|
+
|
|
44
|
+
// Create a connector
|
|
45
|
+
const unisat = new UnisatConnector();
|
|
46
|
+
|
|
47
|
+
// Check if wallet is installed
|
|
48
|
+
if (unisat.ready) {
|
|
49
|
+
// Connect
|
|
50
|
+
const account = await unisat.connect('mainnet');
|
|
51
|
+
console.log(account.address, account.publicKey, account.type);
|
|
52
|
+
|
|
53
|
+
// Sign message
|
|
54
|
+
const signature = await unisat.signMessage('Hello Bitcoin!');
|
|
55
|
+
|
|
56
|
+
// Sign PSBT
|
|
57
|
+
const signedPsbt = await unisat.signPsbt(psbtHex, {
|
|
58
|
+
autoFinalize: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Batch sign PSBTs (Unisat only)
|
|
62
|
+
const signedPsbts = await unisat.signPsbts([psbt1, psbt2], {
|
|
63
|
+
autoFinalize: true,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Send Bitcoin (amount in satoshis)
|
|
67
|
+
const txid = await unisat.sendTransaction('bc1q...', 10000);
|
|
68
|
+
|
|
69
|
+
// Disconnect
|
|
70
|
+
await unisat.disconnect();
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Connector Interface
|
|
75
|
+
|
|
76
|
+
All connectors implement the `BitcoinConnector` interface from `otx-btc-wallet-core`:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface BitcoinConnector {
|
|
80
|
+
readonly id: string; // Unique identifier (e.g. 'unisat')
|
|
81
|
+
readonly name: string; // Display name (e.g. 'Unisat')
|
|
82
|
+
readonly icon: string; // Base64 SVG/PNG icon
|
|
83
|
+
ready: boolean; // Is the wallet installed/available?
|
|
84
|
+
|
|
85
|
+
connect(network?: BitcoinNetwork): Promise<WalletAccount>;
|
|
86
|
+
disconnect(): Promise<void>;
|
|
87
|
+
getAccounts(): Promise<WalletAccount[]>;
|
|
88
|
+
signMessage(message: string): Promise<string>;
|
|
89
|
+
signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string>;
|
|
90
|
+
signPsbts?(psbtHexs: string[], options?: SignPsbtOptions): Promise<string[]>;
|
|
91
|
+
sendTransaction(to: string, satoshis: number): Promise<string>;
|
|
92
|
+
getNetwork(): Promise<BitcoinNetwork>;
|
|
93
|
+
switchNetwork?(network: BitcoinNetwork): Promise<void>;
|
|
94
|
+
onAccountsChanged(callback: (accounts: WalletAccount[]) => void): () => void;
|
|
95
|
+
onNetworkChanged(callback: (network: BitcoinNetwork) => void): () => void;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Event Listeners
|
|
100
|
+
|
|
101
|
+
All connectors support account and network change events:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// Listen for account changes
|
|
105
|
+
const unsubscribe = connector.onAccountsChanged((accounts) => {
|
|
106
|
+
if (accounts.length === 0) {
|
|
107
|
+
console.log('Wallet disconnected');
|
|
108
|
+
} else {
|
|
109
|
+
console.log('Account changed:', accounts[0].address);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Listen for network changes
|
|
114
|
+
const unsubNetwork = connector.onNetworkChanged((network) => {
|
|
115
|
+
console.log('Network changed to:', network);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Cleanup listeners
|
|
119
|
+
unsubscribe();
|
|
120
|
+
unsubNetwork();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Hardware Wallets
|
|
124
|
+
|
|
125
|
+
### Ledger
|
|
126
|
+
|
|
127
|
+
Connects via WebUSB. Requires a Chromium-based browser (Chrome, Edge, Brave).
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { LedgerConnector } from 'otx-btc-wallet-connectors';
|
|
131
|
+
import type { LedgerConnectorOptions } from 'otx-btc-wallet-connectors';
|
|
132
|
+
|
|
133
|
+
const ledger = new LedgerConnector({
|
|
134
|
+
addressType: 'segwit', // 'legacy' | 'nested-segwit' | 'segwit' | 'taproot'
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Connect - opens USB device picker
|
|
138
|
+
const account = await ledger.connect('mainnet');
|
|
139
|
+
|
|
140
|
+
// Send Bitcoin (PSBT is built and signed internally)
|
|
141
|
+
const txid = await ledger.sendTransaction('bc1q...', 50000);
|
|
142
|
+
|
|
143
|
+
// Get multiple addresses from the device
|
|
144
|
+
const addresses = await ledger.getAddresses(0, 5); // indices 0-4
|
|
145
|
+
|
|
146
|
+
// Get extended public key
|
|
147
|
+
const xpub = await ledger.getExtendedPublicKey();
|
|
148
|
+
|
|
149
|
+
// Disconnect (closes USB transport)
|
|
150
|
+
await ledger.disconnect();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Ledger Options:**
|
|
154
|
+
|
|
155
|
+
| Option | Type | Default | Description |
|
|
156
|
+
|--------|------|---------|-------------|
|
|
157
|
+
| `addressType` | `AddressType` | `'segwit'` | Address derivation type |
|
|
158
|
+
|
|
159
|
+
### Trezor
|
|
160
|
+
|
|
161
|
+
Connects via [Trezor Connect](https://connect.trezor.io/).
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { TrezorConnector } from 'otx-btc-wallet-connectors';
|
|
165
|
+
import type { TrezorConnectorOptions } from 'otx-btc-wallet-connectors';
|
|
166
|
+
|
|
167
|
+
const trezor = new TrezorConnector({
|
|
168
|
+
addressType: 'segwit',
|
|
169
|
+
manifest: {
|
|
170
|
+
email: 'your@email.com',
|
|
171
|
+
appUrl: 'https://your-app.com',
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Connect - opens Trezor Connect popup
|
|
176
|
+
const account = await trezor.connect('mainnet');
|
|
177
|
+
|
|
178
|
+
// Send Bitcoin
|
|
179
|
+
const txid = await trezor.sendTransaction('bc1q...', 50000);
|
|
180
|
+
|
|
181
|
+
// Get multiple addresses
|
|
182
|
+
const addresses = await trezor.getAddresses(0, 5);
|
|
183
|
+
|
|
184
|
+
// Get extended public key
|
|
185
|
+
const xpub = await trezor.getExtendedPublicKey();
|
|
186
|
+
|
|
187
|
+
// Verify address on device screen
|
|
188
|
+
const verified = await trezor.getAddressWithVerification();
|
|
189
|
+
|
|
190
|
+
await trezor.disconnect();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Trezor Options:**
|
|
194
|
+
|
|
195
|
+
| Option | Type | Default | Description |
|
|
196
|
+
|--------|------|---------|-------------|
|
|
197
|
+
| `addressType` | `AddressType` | `'segwit'` | Address derivation type |
|
|
198
|
+
| `manifest.email` | `string` | `'support@optimex.com'` | Contact email for Trezor |
|
|
199
|
+
| `manifest.appUrl` | `string` | `'https://optimex.com'` | App URL for Trezor |
|
|
200
|
+
|
|
201
|
+
## Custom Connectors
|
|
202
|
+
|
|
203
|
+
Extend `BaseConnector` to add support for any Bitcoin wallet:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import { BaseConnector } from 'otx-btc-wallet-connectors';
|
|
207
|
+
import type {
|
|
208
|
+
WalletAccount,
|
|
209
|
+
BitcoinNetwork,
|
|
210
|
+
SignPsbtOptions,
|
|
211
|
+
} from 'otx-btc-wallet-core';
|
|
212
|
+
|
|
213
|
+
export class MyWalletConnector extends BaseConnector {
|
|
214
|
+
readonly id = 'my-wallet';
|
|
215
|
+
readonly name = 'My Wallet';
|
|
216
|
+
readonly icon = 'data:image/svg+xml;base64,...';
|
|
217
|
+
|
|
218
|
+
// Return the wallet's injected provider, or null if not installed
|
|
219
|
+
protected getProvider() {
|
|
220
|
+
return (window as any).myWallet ?? null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async connect(network: BitcoinNetwork = 'mainnet'): Promise<WalletAccount> {
|
|
224
|
+
this.ensureInstalled(); // Throws if getProvider() returns null
|
|
225
|
+
const provider = this.getProvider()!;
|
|
226
|
+
|
|
227
|
+
const accounts = await provider.requestAccounts();
|
|
228
|
+
const publicKey = await provider.getPublicKey();
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
address: accounts[0],
|
|
232
|
+
publicKey,
|
|
233
|
+
type: this.inferAddressType(accounts[0]), // Auto-detect from address prefix
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async disconnect(): Promise<void> {
|
|
238
|
+
this.cleanup(); // Removes event listeners
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async getAccounts(): Promise<WalletAccount[]> {
|
|
242
|
+
const provider = this.getProvider()!;
|
|
243
|
+
const accounts = await provider.getAccounts();
|
|
244
|
+
const publicKey = await provider.getPublicKey();
|
|
245
|
+
return accounts.map((addr: string) => ({
|
|
246
|
+
address: addr,
|
|
247
|
+
publicKey,
|
|
248
|
+
type: this.inferAddressType(addr),
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async signMessage(message: string): Promise<string> {
|
|
253
|
+
return this.getProvider()!.signMessage(message);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string> {
|
|
257
|
+
return this.getProvider()!.signPsbt(psbtHex, options);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async sendTransaction(to: string, satoshis: number): Promise<string> {
|
|
261
|
+
return this.getProvider()!.sendBitcoin(to, satoshis);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async getNetwork(): Promise<BitcoinNetwork> {
|
|
265
|
+
return this.getProvider()!.getNetwork();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### BaseConnector Protected Methods
|
|
271
|
+
|
|
272
|
+
| Method | Description |
|
|
273
|
+
|--------|-------------|
|
|
274
|
+
| `getProvider()` | Abstract. Return the wallet's injected provider object |
|
|
275
|
+
| `ensureInstalled()` | Throws error if `getProvider()` returns null/undefined |
|
|
276
|
+
| `inferAddressType(address)` | Detects address type from prefix (`1...` = legacy, `3...` = nested-segwit, `bc1q...` = segwit, `bc1p...` = taproot) |
|
|
277
|
+
| `handleError(error)` | Wraps errors with connector context |
|
|
278
|
+
| `emitAccountsChanged(accounts)` | Notify listeners of account changes |
|
|
279
|
+
| `emitNetworkChanged(network)` | Notify listeners of network changes |
|
|
280
|
+
| `cleanup()` | Remove all registered event listeners |
|
|
281
|
+
|
|
282
|
+
## BtcService
|
|
283
|
+
|
|
284
|
+
`BtcService` provides a unified API for querying Bitcoin blockchain data. It uses a dual-provider architecture with Mempool.space and Blockstream.info for reliability.
|
|
285
|
+
|
|
286
|
+
### Basic Usage
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { BtcService } from 'otx-btc-wallet-connectors';
|
|
290
|
+
|
|
291
|
+
const service = new BtcService('mainnet');
|
|
292
|
+
|
|
293
|
+
// Get UTXOs for an address
|
|
294
|
+
const utxos = await service.getUtxos('bc1q...');
|
|
295
|
+
|
|
296
|
+
// Get transaction hex
|
|
297
|
+
const txHex = await service.getTxHex('txid...');
|
|
298
|
+
|
|
299
|
+
// Get full transaction details
|
|
300
|
+
const tx = await service.getTransaction('txid...');
|
|
301
|
+
|
|
302
|
+
// Broadcast a signed transaction
|
|
303
|
+
const txid = await service.broadcastTransaction(signedTxHex);
|
|
304
|
+
|
|
305
|
+
// Get address balance
|
|
306
|
+
const balance = await service.getBalance('bc1q...');
|
|
307
|
+
|
|
308
|
+
// Get current fee rates (sat/vB)
|
|
309
|
+
const fees = await service.getFeeRates();
|
|
310
|
+
// { fastest: number, halfHour: number, hour: number, economy: number, minimum: number }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Standalone Functions
|
|
314
|
+
|
|
315
|
+
For convenience, you can also use standalone functions without creating an instance:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import {
|
|
319
|
+
getUtxos,
|
|
320
|
+
getTxHex,
|
|
321
|
+
getTransaction,
|
|
322
|
+
broadcastTransaction,
|
|
323
|
+
getBalance,
|
|
324
|
+
getFeeRates,
|
|
325
|
+
} from 'otx-btc-wallet-connectors';
|
|
326
|
+
|
|
327
|
+
const utxos = await getUtxos('mainnet', 'bc1q...');
|
|
328
|
+
const fees = await getFeeRates('mainnet');
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Custom RPC Endpoints
|
|
332
|
+
|
|
333
|
+
Configure custom Mempool.space or Blockstream.info endpoints globally:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import { configureBtcService } from 'otx-btc-wallet-connectors';
|
|
337
|
+
|
|
338
|
+
configureBtcService({
|
|
339
|
+
mempool: {
|
|
340
|
+
mainnet: 'https://my-mempool.example.com/api',
|
|
341
|
+
testnet: 'https://my-mempool.example.com/testnet/api',
|
|
342
|
+
},
|
|
343
|
+
blockstream: {
|
|
344
|
+
mainnet: 'https://my-blockstream.example.com/api',
|
|
345
|
+
},
|
|
346
|
+
preferredProvider: 'mempool', // 'mempool' | 'blockstream' | 'race' (default)
|
|
347
|
+
});
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Provider Modes:**
|
|
351
|
+
|
|
352
|
+
| Mode | Description |
|
|
353
|
+
|------|-------------|
|
|
354
|
+
| `'race'` | (Default) Sends requests to both providers simultaneously, uses whichever responds first |
|
|
355
|
+
| `'mempool'` | Only use Mempool.space |
|
|
356
|
+
| `'blockstream'` | Only use Blockstream.info |
|
|
357
|
+
|
|
358
|
+
### Per-Instance Configuration
|
|
359
|
+
|
|
360
|
+
You can also pass config when creating a `BtcService` instance:
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
const service = new BtcService('mainnet', {
|
|
364
|
+
mempool: { mainnet: 'https://my-mempool.example.com/api' },
|
|
365
|
+
preferredProvider: 'mempool',
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Configuration Types
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
import type { BtcServiceConfig, NetworkEndpoints } from 'otx-btc-wallet-connectors';
|
|
373
|
+
|
|
374
|
+
interface NetworkEndpoints {
|
|
375
|
+
mainnet?: string;
|
|
376
|
+
testnet?: string;
|
|
377
|
+
testnet4?: string;
|
|
378
|
+
signet?: string;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
interface BtcServiceConfig {
|
|
382
|
+
mempool?: NetworkEndpoints;
|
|
383
|
+
blockstream?: NetworkEndpoints;
|
|
384
|
+
preferredProvider?: 'mempool' | 'blockstream' | 'race';
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Get Current Config
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { getBtcServiceConfig } from 'otx-btc-wallet-connectors';
|
|
392
|
+
|
|
393
|
+
const currentConfig = getBtcServiceConfig();
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Service Types
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import type {
|
|
400
|
+
Utxo,
|
|
401
|
+
UtxoWithTx,
|
|
402
|
+
FeeRates,
|
|
403
|
+
Transaction,
|
|
404
|
+
FullTransaction,
|
|
405
|
+
AddressBalance,
|
|
406
|
+
IBtcService,
|
|
407
|
+
} from 'otx-btc-wallet-connectors';
|
|
408
|
+
|
|
409
|
+
interface Utxo {
|
|
410
|
+
txid: string;
|
|
411
|
+
vout: number;
|
|
412
|
+
value: number;
|
|
413
|
+
status: { confirmed: boolean; block_height?: number };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
interface FeeRates {
|
|
417
|
+
fastest: number;
|
|
418
|
+
halfHour: number;
|
|
419
|
+
hour: number;
|
|
420
|
+
economy: number;
|
|
421
|
+
minimum: number;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
interface AddressBalance {
|
|
425
|
+
confirmed: number;
|
|
426
|
+
unconfirmed: number;
|
|
427
|
+
total: number;
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## PSBT Builder Utilities
|
|
432
|
+
|
|
433
|
+
Low-level utilities for building Bitcoin transactions:
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import {
|
|
437
|
+
deriveAddressFromPublicKey,
|
|
438
|
+
detectAddressType,
|
|
439
|
+
estimateVBytes,
|
|
440
|
+
selectUtxos,
|
|
441
|
+
buildPsbt,
|
|
442
|
+
} from 'otx-btc-wallet-connectors';
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Derive Address from Public Key
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import { deriveAddressFromPublicKey } from 'otx-btc-wallet-connectors';
|
|
449
|
+
|
|
450
|
+
const address = deriveAddressFromPublicKey(
|
|
451
|
+
publicKeyHex, // Hex-encoded public key
|
|
452
|
+
'segwit', // 'legacy' | 'nested-segwit' | 'segwit' | 'taproot'
|
|
453
|
+
'mainnet', // Bitcoin network
|
|
454
|
+
);
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
## Individual Service Classes
|
|
458
|
+
|
|
459
|
+
You can use Mempool or Blockstream services directly:
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import { MempoolService, BlockstreamService } from 'otx-btc-wallet-connectors';
|
|
463
|
+
|
|
464
|
+
// Use Mempool.space directly
|
|
465
|
+
const mempool = new MempoolService('mainnet');
|
|
466
|
+
const utxos = await mempool.getUtxos('bc1q...');
|
|
467
|
+
|
|
468
|
+
// Use Blockstream.info directly
|
|
469
|
+
const blockstream = new BlockstreamService('mainnet');
|
|
470
|
+
const balance = await blockstream.getBalance('bc1q...');
|
|
471
|
+
|
|
472
|
+
// With custom endpoints
|
|
473
|
+
const customMempool = new MempoolService('mainnet', {
|
|
474
|
+
mainnet: 'https://my-mempool.example.com/api',
|
|
475
|
+
});
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Default API Endpoints
|
|
479
|
+
|
|
480
|
+
### Mempool.space
|
|
481
|
+
|
|
482
|
+
| Network | Endpoint |
|
|
483
|
+
|---------|----------|
|
|
484
|
+
| mainnet | `https://mempool.space/api` |
|
|
485
|
+
| testnet | `https://mempool.space/testnet/api` |
|
|
486
|
+
| testnet4 | `https://mempool.space/testnet4/api` |
|
|
487
|
+
| signet | `https://mempool.space/signet/api` |
|
|
488
|
+
|
|
489
|
+
### Blockstream.info
|
|
490
|
+
|
|
491
|
+
| Network | Endpoint |
|
|
492
|
+
|---------|----------|
|
|
493
|
+
| mainnet | `https://blockstream.info/api` |
|
|
494
|
+
| testnet | `https://blockstream.info/testnet/api` |
|
|
495
|
+
| testnet4 | `https://mempool.space/testnet4/api` (fallback) |
|
|
496
|
+
| signet | `https://mempool.space/signet/api` (fallback) |
|
|
497
|
+
|
|
498
|
+
## Full Exports
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
// Connectors
|
|
502
|
+
export { UnisatConnector } from './unisat';
|
|
503
|
+
export { XverseConnector } from './xverse';
|
|
504
|
+
export { OKXConnector } from './okx';
|
|
505
|
+
export { PhantomConnector } from './phantom';
|
|
506
|
+
export { BitgetConnector } from './bitget';
|
|
507
|
+
export { BinanceConnector } from './binance';
|
|
508
|
+
export { ImTokenConnector } from './imtoken';
|
|
509
|
+
export { LedgerConnector } from './ledger';
|
|
510
|
+
export type { LedgerConnectorOptions } from './ledger';
|
|
511
|
+
export { TrezorConnector } from './trezor';
|
|
512
|
+
export type { TrezorConnectorOptions } from './trezor';
|
|
513
|
+
|
|
514
|
+
// Base class for custom connectors
|
|
515
|
+
export { BaseConnector } from './base';
|
|
516
|
+
|
|
517
|
+
// Services
|
|
518
|
+
export { BtcService } from './utils/btc-service';
|
|
519
|
+
export { MempoolService } from './utils/mempool';
|
|
520
|
+
export { BlockstreamService } from './utils/blockstream';
|
|
521
|
+
|
|
522
|
+
// Configuration
|
|
523
|
+
export { configureBtcService, getBtcServiceConfig } from './utils/btc-service';
|
|
524
|
+
|
|
525
|
+
// PSBT Builder
|
|
526
|
+
export { deriveAddressFromPublicKey } from './utils/psbt-builder';
|
|
527
|
+
|
|
528
|
+
// Standalone functions
|
|
529
|
+
export {
|
|
530
|
+
getUtxos,
|
|
531
|
+
getTxHex,
|
|
532
|
+
getTransaction,
|
|
533
|
+
broadcastTransaction,
|
|
534
|
+
getBalance,
|
|
535
|
+
getFeeRates,
|
|
536
|
+
} from './utils/btc-service';
|
|
537
|
+
|
|
538
|
+
// Types
|
|
539
|
+
export type {
|
|
540
|
+
Utxo,
|
|
541
|
+
UtxoWithTx,
|
|
542
|
+
FeeRates,
|
|
543
|
+
Transaction,
|
|
544
|
+
FullTransaction,
|
|
545
|
+
AddressBalance,
|
|
546
|
+
IBtcService,
|
|
547
|
+
BtcServiceConfig,
|
|
548
|
+
NetworkEndpoints,
|
|
549
|
+
} from './utils/types';
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
## License
|
|
553
|
+
|
|
554
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { BitcoinConnector, AddressType, BitcoinNetwork, WalletAccount, SignPsbtOptions } from 'otx-btc-wallet-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all wallet connectors
|
|
5
|
+
* Provides common functionality and enforces the BitcoinConnector interface
|
|
6
|
+
*/
|
|
7
|
+
declare abstract class BaseConnector implements BitcoinConnector {
|
|
8
|
+
abstract readonly id: string;
|
|
9
|
+
abstract readonly name: string;
|
|
10
|
+
abstract readonly icon: string;
|
|
11
|
+
private _ready;
|
|
12
|
+
private _accountsChangedCallbacks;
|
|
13
|
+
private _networkChangedCallbacks;
|
|
14
|
+
constructor();
|
|
15
|
+
get ready(): boolean;
|
|
16
|
+
protected set ready(value: boolean);
|
|
17
|
+
protected abstract getProvider(): unknown;
|
|
18
|
+
protected checkReady(): void;
|
|
19
|
+
protected ensureInstalled(): void;
|
|
20
|
+
protected inferAddressType(address: string): AddressType;
|
|
21
|
+
protected handleError(error: unknown): never;
|
|
22
|
+
abstract connect(network?: BitcoinNetwork): Promise<WalletAccount>;
|
|
23
|
+
abstract disconnect(): Promise<void>;
|
|
24
|
+
abstract getAccounts(): Promise<WalletAccount[]>;
|
|
25
|
+
abstract signMessage(message: string): Promise<string>;
|
|
26
|
+
abstract signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string>;
|
|
27
|
+
abstract sendTransaction(to: string, satoshis: number): Promise<string>;
|
|
28
|
+
abstract getNetwork(): Promise<BitcoinNetwork>;
|
|
29
|
+
signPsbts?(psbtHexs: string[], options?: SignPsbtOptions): Promise<string[]>;
|
|
30
|
+
switchNetwork?(network: BitcoinNetwork): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to account changes
|
|
33
|
+
*/
|
|
34
|
+
onAccountsChanged(callback: (accounts: WalletAccount[]) => void): () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to network changes
|
|
37
|
+
*/
|
|
38
|
+
onNetworkChanged(callback: (network: BitcoinNetwork) => void): () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Emit account change event
|
|
41
|
+
*/
|
|
42
|
+
protected emitAccountsChanged(accounts: WalletAccount[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* Emit network change event
|
|
45
|
+
*/
|
|
46
|
+
protected emitNetworkChanged(network: BitcoinNetwork): void;
|
|
47
|
+
/**
|
|
48
|
+
* Clean up all listeners
|
|
49
|
+
*/
|
|
50
|
+
protected cleanup(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { BaseConnector as B };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { BitcoinConnector, AddressType, BitcoinNetwork, WalletAccount, SignPsbtOptions } from 'otx-btc-wallet-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for all wallet connectors
|
|
5
|
+
* Provides common functionality and enforces the BitcoinConnector interface
|
|
6
|
+
*/
|
|
7
|
+
declare abstract class BaseConnector implements BitcoinConnector {
|
|
8
|
+
abstract readonly id: string;
|
|
9
|
+
abstract readonly name: string;
|
|
10
|
+
abstract readonly icon: string;
|
|
11
|
+
private _ready;
|
|
12
|
+
private _accountsChangedCallbacks;
|
|
13
|
+
private _networkChangedCallbacks;
|
|
14
|
+
constructor();
|
|
15
|
+
get ready(): boolean;
|
|
16
|
+
protected set ready(value: boolean);
|
|
17
|
+
protected abstract getProvider(): unknown;
|
|
18
|
+
protected checkReady(): void;
|
|
19
|
+
protected ensureInstalled(): void;
|
|
20
|
+
protected inferAddressType(address: string): AddressType;
|
|
21
|
+
protected handleError(error: unknown): never;
|
|
22
|
+
abstract connect(network?: BitcoinNetwork): Promise<WalletAccount>;
|
|
23
|
+
abstract disconnect(): Promise<void>;
|
|
24
|
+
abstract getAccounts(): Promise<WalletAccount[]>;
|
|
25
|
+
abstract signMessage(message: string): Promise<string>;
|
|
26
|
+
abstract signPsbt(psbtHex: string, options?: SignPsbtOptions): Promise<string>;
|
|
27
|
+
abstract sendTransaction(to: string, satoshis: number): Promise<string>;
|
|
28
|
+
abstract getNetwork(): Promise<BitcoinNetwork>;
|
|
29
|
+
signPsbts?(psbtHexs: string[], options?: SignPsbtOptions): Promise<string[]>;
|
|
30
|
+
switchNetwork?(network: BitcoinNetwork): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Subscribe to account changes
|
|
33
|
+
*/
|
|
34
|
+
onAccountsChanged(callback: (accounts: WalletAccount[]) => void): () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Subscribe to network changes
|
|
37
|
+
*/
|
|
38
|
+
onNetworkChanged(callback: (network: BitcoinNetwork) => void): () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Emit account change event
|
|
41
|
+
*/
|
|
42
|
+
protected emitAccountsChanged(accounts: WalletAccount[]): void;
|
|
43
|
+
/**
|
|
44
|
+
* Emit network change event
|
|
45
|
+
*/
|
|
46
|
+
protected emitNetworkChanged(network: BitcoinNetwork): void;
|
|
47
|
+
/**
|
|
48
|
+
* Clean up all listeners
|
|
49
|
+
*/
|
|
50
|
+
protected cleanup(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { BaseConnector as B };
|