@bigmi/react 0.4.3 → 0.4.5
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/CHANGELOG.md +4 -0
- package/README.md +354 -23
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +3 -3
- package/package.json.tmp +3 -3
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [0.4.5](https://github.com/lifinance/bigmi/compare/v0.4.4...v0.4.5) (2025-08-27)
|
|
6
|
+
|
|
7
|
+
### [0.4.4](https://github.com/lifinance/bigmi/compare/v0.4.3...v0.4.4) (2025-08-18)
|
|
8
|
+
|
|
5
9
|
### [0.4.3](https://github.com/lifinance/bigmi/compare/v0.4.2...v0.4.3) (2025-07-31)
|
|
6
10
|
|
|
7
11
|
|
package/README.md
CHANGED
|
@@ -31,38 +31,33 @@ Bigmi is modularized into several packages, each suited to different use cases:
|
|
|
31
31
|
```sh
|
|
32
32
|
pnpm add @bigmi/react
|
|
33
33
|
```
|
|
34
|
+
|
|
34
35
|
```sh
|
|
35
36
|
pnpm add @bigmi/core
|
|
36
37
|
```
|
|
38
|
+
|
|
37
39
|
```sh
|
|
38
40
|
pnpm add @bigmi/client
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
## Getting Started
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
### Node.js
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
+
How to setup Bigmi on the backend with Node.js:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// main.ts
|
|
47
51
|
import {
|
|
48
|
-
|
|
52
|
+
createClient,
|
|
49
53
|
bitcoin,
|
|
50
|
-
|
|
51
|
-
getBlockCount,
|
|
54
|
+
blockchair,
|
|
52
55
|
sendUTXOTransaction,
|
|
53
56
|
waitForTransaction,
|
|
54
|
-
|
|
55
|
-
fallback,
|
|
56
|
-
rpcSchema
|
|
57
|
-
ankr,
|
|
58
|
-
blockchair,
|
|
59
|
-
blockcypher,
|
|
60
|
-
mempool
|
|
57
|
+
getBalance,
|
|
61
58
|
} from '@bigmi/core'
|
|
62
|
-
import { useAccount } from '@bigmi/react'
|
|
63
|
-
|
|
64
59
|
|
|
65
|
-
// Create a
|
|
60
|
+
// Create a client for Bitcoin mainnet
|
|
66
61
|
const publicClient = createClient({
|
|
67
62
|
chain: bitcoin,
|
|
68
63
|
rpcSchema: rpcSchema<UTXOSchema>(),
|
|
@@ -103,23 +98,359 @@ const transaction = await waitForTransaction(publicClient, {
|
|
|
103
98
|
});
|
|
104
99
|
|
|
105
100
|
console.log('Transaction confirmed:', transaction);
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### React
|
|
105
|
+
|
|
106
|
+
Simple bigmi setup with a react app:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
// App.tsx
|
|
110
|
+
|
|
111
|
+
import { bitcoin, http, createClient } from '@bigmi/core'
|
|
112
|
+
import { BigmiProvider, createConfig } from '@bigmi/react'
|
|
113
|
+
import { binance, xverse, phantom } from '@bigmi/client'
|
|
114
|
+
|
|
115
|
+
const chainId = bitcoin.id
|
|
116
|
+
|
|
117
|
+
// Create bigmi config object
|
|
118
|
+
const config = createConfig({
|
|
119
|
+
chains: [bitcoin],
|
|
120
|
+
connectors: [binance({chainId}), xverse({chainId}), phantom({chainId})],
|
|
121
|
+
client: ({ chain }) => createClient({ chain, transport: http() }),
|
|
122
|
+
ssr: true // If using Next.js or SSR
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
function App() {
|
|
127
|
+
return (
|
|
128
|
+
// Wrap your application with the necessary providers:
|
|
129
|
+
<BigmiProvider config={config}>
|
|
130
|
+
<YourApp />
|
|
131
|
+
</BigmiProvider>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
// YourApp.tsx
|
|
138
|
+
|
|
139
|
+
// Import the hooks from bigmi/react library
|
|
140
|
+
import { useAccount, useBalance, useConnect } from '@bigmi/react'
|
|
141
|
+
|
|
142
|
+
const { address, isConnected } = useAccount()
|
|
143
|
+
const { balance } = useBalance()
|
|
144
|
+
const { connect } = useConnect()
|
|
145
|
+
|
|
146
|
+
function YourApp() {
|
|
147
|
+
return (
|
|
148
|
+
<div>
|
|
149
|
+
{isConnected ? (
|
|
150
|
+
<p>Connected: {address}: {balance}BTC</p>
|
|
151
|
+
) : (
|
|
152
|
+
<button onClick={connect}>Connect Wallet</button>
|
|
153
|
+
)}
|
|
154
|
+
</div>
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Creating Bitcoin Transactions
|
|
160
|
+
|
|
161
|
+
While Bigmi excels at blockchain data retrieval and transaction broadcasting, it doesn't include transaction creation functions. For generating valid transaction hex, we recommend using **bitcoinjs-lib** (which Bigmi already depends on).
|
|
162
|
+
|
|
163
|
+
### Basic Transaction Creation
|
|
164
|
+
|
|
165
|
+
Here's how to create a Bitcoin transaction using bitcoinjs-lib with Bigmi:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
169
|
+
import {
|
|
170
|
+
createClient,
|
|
171
|
+
getUTXOs,
|
|
172
|
+
sendUTXOTransaction,
|
|
173
|
+
waitForTransaction,
|
|
174
|
+
getBlockStats,
|
|
175
|
+
getBlockCount
|
|
176
|
+
} from '@bigmi/core';
|
|
177
|
+
|
|
178
|
+
async function createAndSendTransaction(
|
|
179
|
+
client: Client,
|
|
180
|
+
fromAddress: string,
|
|
181
|
+
toAddress: string,
|
|
182
|
+
amount: number, // in satoshis
|
|
183
|
+
privateKey: Buffer
|
|
184
|
+
) {
|
|
185
|
+
// 1. Get UTXOs for the address using Bigmi
|
|
186
|
+
const utxos = await getUTXOs(client, { address: fromAddress });
|
|
187
|
+
|
|
188
|
+
// 2. Create a new transaction using bitcoinjs-lib
|
|
189
|
+
const psbt = new bitcoin.Psbt();
|
|
190
|
+
|
|
191
|
+
// 3. Add inputs from UTXOs
|
|
192
|
+
let inputValue = 0;
|
|
193
|
+
const estimatedFee = 1000; // You should calculate this properly
|
|
194
|
+
|
|
195
|
+
for (const utxo of utxos) {
|
|
196
|
+
psbt.addInput({
|
|
197
|
+
hash: utxo.txId,
|
|
198
|
+
index: utxo.vout,
|
|
199
|
+
witnessUtxo: {
|
|
200
|
+
script: Buffer.from(utxo.scriptHex, 'hex'),
|
|
201
|
+
value: utxo.value,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
inputValue += utxo.value;
|
|
205
|
+
if (inputValue >= amount + estimatedFee) break;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 4. Add recipient output
|
|
209
|
+
psbt.addOutput({
|
|
210
|
+
address: toAddress,
|
|
211
|
+
value: amount,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// 5. Add change output if needed
|
|
215
|
+
const change = inputValue - amount - estimatedFee;
|
|
216
|
+
if (change > 546) { // Dust threshold
|
|
217
|
+
psbt.addOutput({
|
|
218
|
+
address: fromAddress,
|
|
219
|
+
value: change,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// 6. Sign the transaction
|
|
224
|
+
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
|
|
225
|
+
psbt.signAllInputs(keyPair);
|
|
226
|
+
psbt.finalizeAllInputs();
|
|
227
|
+
|
|
228
|
+
// 7. Get the raw transaction hex
|
|
229
|
+
const rawTx = psbt.extractTransaction().toHex();
|
|
230
|
+
|
|
231
|
+
// 8. Broadcast using Bigmi
|
|
232
|
+
const txId = await sendUTXOTransaction(client, { hex: rawTx });
|
|
233
|
+
|
|
234
|
+
// 9. Wait for confirmation using Bigmi
|
|
235
|
+
const confirmedTx = await waitForTransaction(client, {
|
|
236
|
+
txId,
|
|
237
|
+
txHex: rawTx,
|
|
238
|
+
senderAddress: fromAddress,
|
|
239
|
+
confirmations: 1,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
return confirmedTx;
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Fee Estimation
|
|
247
|
+
|
|
248
|
+
Proper fee estimation is crucial for transaction confirmation:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
async function estimateFee(
|
|
252
|
+
client: Client,
|
|
253
|
+
numInputs: number,
|
|
254
|
+
numOutputs: number
|
|
255
|
+
): Promise<number> {
|
|
256
|
+
// Get recent block stats for fee estimation
|
|
257
|
+
const blockHeight = await getBlockCount(client);
|
|
258
|
+
const blockStats = await getBlockStats(client, {
|
|
259
|
+
blockNumber: blockHeight,
|
|
260
|
+
stats: ['avgfeerate']
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Estimate transaction size
|
|
264
|
+
// P2WPKH: ~68 bytes per input, ~31 bytes per output, ~10 bytes overhead
|
|
265
|
+
const estimatedSize = (numInputs * 68) + (numOutputs * 31) + 10;
|
|
266
|
+
|
|
267
|
+
// Calculate fee (satoshis per byte * size)
|
|
268
|
+
const feeRate = blockStats.avgfeerate || 1; // fallback to 1 sat/byte
|
|
269
|
+
return Math.ceil(feeRate * estimatedSize);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Complete Example with Error Handling
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
277
|
+
import { createClient, getBalance, getUTXOs, sendUTXOTransaction, waitForTransaction } from '@bigmi/core';
|
|
278
|
+
|
|
279
|
+
async function safeSendBitcoin(
|
|
280
|
+
client: Client,
|
|
281
|
+
fromAddress: string,
|
|
282
|
+
toAddress: string,
|
|
283
|
+
amount: number,
|
|
284
|
+
privateKey: Buffer
|
|
285
|
+
) {
|
|
286
|
+
try {
|
|
287
|
+
// Check balance
|
|
288
|
+
const balance = await getBalance(client, { address: fromAddress });
|
|
289
|
+
if (balance < amount + 1000) {
|
|
290
|
+
throw new Error('Insufficient balance');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Get UTXOs
|
|
294
|
+
const utxos = await getUTXOs(client, {
|
|
295
|
+
address: fromAddress,
|
|
296
|
+
minValue: amount + 1000,
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (utxos.length === 0) {
|
|
300
|
+
throw new Error('No UTXOs available');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Create transaction
|
|
304
|
+
const psbt = new bitcoin.Psbt();
|
|
305
|
+
|
|
306
|
+
let totalInput = 0;
|
|
307
|
+
for (const utxo of utxos) {
|
|
308
|
+
psbt.addInput({
|
|
309
|
+
hash: utxo.txId,
|
|
310
|
+
index: utxo.vout,
|
|
311
|
+
witnessUtxo: {
|
|
312
|
+
script: Buffer.from(utxo.scriptHex, 'hex'),
|
|
313
|
+
value: utxo.value,
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
totalInput += utxo.value;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Add outputs
|
|
320
|
+
psbt.addOutput({
|
|
321
|
+
address: toAddress,
|
|
322
|
+
value: amount,
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Calculate fee and change
|
|
326
|
+
const fee = await estimateFee(client, utxos.length, 2);
|
|
327
|
+
const change = totalInput - amount - fee;
|
|
328
|
+
|
|
329
|
+
if (change < 0) {
|
|
330
|
+
throw new Error('Insufficient funds for fee');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (change > 546) { // Dust threshold
|
|
334
|
+
psbt.addOutput({
|
|
335
|
+
address: fromAddress,
|
|
336
|
+
value: change,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Sign and finalize
|
|
341
|
+
const keyPair = bitcoin.ECPair.fromPrivateKey(privateKey);
|
|
342
|
+
psbt.signAllInputs(keyPair);
|
|
343
|
+
psbt.finalizeAllInputs();
|
|
344
|
+
|
|
345
|
+
// Get transaction hex
|
|
346
|
+
const txHex = psbt.extractTransaction().toHex();
|
|
347
|
+
|
|
348
|
+
// Broadcast with Bigmi
|
|
349
|
+
const txId = await sendUTXOTransaction(client, { hex: txHex });
|
|
350
|
+
|
|
351
|
+
// Wait for confirmation
|
|
352
|
+
const confirmed = await waitForTransaction(client, {
|
|
353
|
+
txId,
|
|
354
|
+
txHex,
|
|
355
|
+
senderAddress: fromAddress,
|
|
356
|
+
confirmations: 1,
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
txId,
|
|
361
|
+
fee,
|
|
362
|
+
confirmed,
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
} catch (error) {
|
|
366
|
+
console.error('Transaction failed:', error);
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
106
371
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
372
|
+
### Working with Different Address Types
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { getAddressInfo } from '@bigmi/core';
|
|
376
|
+
|
|
377
|
+
function createInputForUTXO(utxo: UTXO, addressInfo: AddressInfo) {
|
|
378
|
+
const input: any = {
|
|
379
|
+
hash: utxo.txId,
|
|
380
|
+
index: utxo.vout,
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
switch (addressInfo.type) {
|
|
384
|
+
case 'p2wpkh':
|
|
385
|
+
case 'p2wsh':
|
|
386
|
+
// Witness UTXOs for SegWit
|
|
387
|
+
input.witnessUtxo = {
|
|
388
|
+
script: Buffer.from(utxo.scriptHex, 'hex'),
|
|
389
|
+
value: utxo.value,
|
|
390
|
+
};
|
|
391
|
+
break;
|
|
392
|
+
case 'p2pkh':
|
|
393
|
+
case 'p2sh':
|
|
394
|
+
// Need full transaction for legacy
|
|
395
|
+
input.nonWitnessUtxo = Buffer.from(fullTransactionHex, 'hex');
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return input;
|
|
400
|
+
}
|
|
401
|
+
```
|
|
110
402
|
|
|
111
|
-
|
|
403
|
+
### RBF (Replace-By-Fee) Support
|
|
404
|
+
|
|
405
|
+
Create transactions with RBF enabled for fee bumping:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
const psbt = new bitcoin.Psbt();
|
|
409
|
+
|
|
410
|
+
// Add inputs with RBF sequence
|
|
411
|
+
for (const utxo of utxos) {
|
|
412
|
+
psbt.addInput({
|
|
413
|
+
hash: utxo.txId,
|
|
414
|
+
index: utxo.vout,
|
|
415
|
+
sequence: 0xfffffffd, // RBF enabled
|
|
416
|
+
witnessUtxo: {
|
|
417
|
+
script: Buffer.from(utxo.scriptHex, 'hex'),
|
|
418
|
+
value: utxo.value,
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
}
|
|
112
422
|
```
|
|
113
423
|
|
|
424
|
+
### Alternative Libraries
|
|
425
|
+
|
|
426
|
+
While we recommend bitcoinjs-lib, you can also use:
|
|
427
|
+
- **@scure/btc-signer** - Modern, audited Bitcoin transaction library
|
|
428
|
+
- **bitcore-lib** - Alternative to bitcoinjs-lib
|
|
429
|
+
- **bcoin** - Full Bitcoin implementation
|
|
430
|
+
|
|
431
|
+
### Security Best Practices
|
|
432
|
+
|
|
433
|
+
1. **Never expose private keys** in client-side code
|
|
434
|
+
2. **Use hardware wallets** for production applications
|
|
435
|
+
3. **Validate all inputs** before creating transactions
|
|
436
|
+
4. **Test on testnet** before mainnet deployment
|
|
437
|
+
5. **Implement proper error handling** for all edge cases
|
|
438
|
+
|
|
114
439
|
## Examples
|
|
115
440
|
|
|
116
|
-
|
|
441
|
+
- [See Node.js examples](./docs/core/examples.md)
|
|
442
|
+
- [See React examples](./docs/react/examples.md)
|
|
117
443
|
|
|
118
|
-
|
|
444
|
+
You can explore the [LI.FI Widget](https://github.com/lifinance/widget) and [LI.FI SDK](https://github.com/lifinance/sdk) for detailed production examples.
|
|
119
445
|
|
|
120
446
|
## Documentation
|
|
121
447
|
|
|
122
|
-
|
|
448
|
+
- [Learn more about Configuration](./docs/core/config.md)
|
|
449
|
+
- [See Core Docs](./docs/core/index.md)
|
|
450
|
+
- [See Client Docs](./docs/client/index.md)
|
|
451
|
+
- [See React Docs](./docs/react/index.md)
|
|
452
|
+
|
|
453
|
+
- [Want to add support for your wallet?](./docs/client/connectors.md)
|
|
123
454
|
|
|
124
455
|
## Support
|
|
125
456
|
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const name = "@bigmi/react";
|
|
2
|
-
export declare const version = "0.4.
|
|
2
|
+
export declare const version = "0.4.5";
|
package/dist/esm/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigmi/react",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "React primitives for Bitcoin apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/esm/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"hooks"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@bigmi/client": "^0.4.
|
|
33
|
-
"@bigmi/core": "^0.4.
|
|
32
|
+
"@bigmi/client": "^0.4.5",
|
|
33
|
+
"@bigmi/core": "^0.4.5"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@tanstack/react-query": ">=5.68.0",
|
package/package.json.tmp
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigmi/react",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "React primitives for Bitcoin apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
"@bigmi/core": "workspace:^"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"cpy-cli": "^
|
|
50
|
+
"cpy-cli": "^6.0.0",
|
|
51
51
|
"madge": "^8.0.0",
|
|
52
52
|
"react": "^19.1.1",
|
|
53
53
|
"react-dom": "^19.1.1",
|
|
54
|
-
"typescript": "^5.
|
|
54
|
+
"typescript": "^5.9.2"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@tanstack/react-query": ">=5.68.0",
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@bigmi/react'
|
|
2
|
-
export const version = '0.4.
|
|
2
|
+
export const version = '0.4.5'
|