ltblightning / bdk-rn Goto Github PK
View Code? Open in Web Editor NEWBitcoin Development Kit - React Native Module
License: MIT License
Bitcoin Development Kit - React Native Module
License: MIT License
Hi guys, thanks for this great lib.
We're using it to make a new kind of wallet.
We need to access the public key byte array value from the Script class in order to construct a new transaction adding a hash time lock. The byte array is abstracted away and we have no access to it. We can access it in version 0.29 of BDK but this library is on 0.27.1
Any idea when the new version will be available?
We've had a go at upgrading the library ourselves but we're not too sure what we're doing and its giving us lots of errors.
Thanks
Transaction creation, signing and broadcast should be separate methods. This will allow more flexibility in user journeys as well as better error handling. This will also be required when doing multisig transactions.
NPM warns about vulnerabilities on install
12 vulnerabilities (1 low, 4 high, 7 critical)
Especially the 7 critical ones should be fixed.
we have getPending and getConfirmed, we need to add getTransactions
method to retrieve both pending and confirmed transactions
How can we achieve Wallet Recovery using this Package?
using version 0.1.1
java.lang.String cannot be cast to java.lang.Double
seems to crash with the electrum config.
const config: BlockchainElectrumConfig = {
url: 'ssl://electrum.blockstream.info:60002',
retry: '5',
timeout: '5',
stopGap: '5',
};
createDescriptor
method should be able to create a descriptor by using a public key instead of xPrv or mnemonic.
This could be an additional option to create a descriptor.
A product might choose to use its own specific tech stack or architecture to generate a mnemonic and its own specific path to generate a private key and then a public key. The app shouldn't have to specify the private key to create a descriptor.
Current implementation uses Android and iOA binaries as core modules for providing bdk functionality.
Do a Proof of concept to explore use of JSI interface to C++ as a alternate mechanism instead of using platform binaries.
This has a number of advantages:
With the new PR, we encounter a new occasional error, it appears often only once or twice and then not again during the session.
The _descriptor[descriptor] is not defined. Possibly a racing condition caused by wrapping every method in a Thread
bdk-rn/android/src/main/java/io/ltbl/bdkrn/BdkRnModule.kt
Lines 407 to 428 in 933cee7
bdk-rn
API needs to be updated to align with bdk-ffi
similar to what has been done for bdk-flutter here
Expose the entire PSBT in the bindings.
(https://docs.rs/bitcoin/0.29.2/bitcoin/util/psbt/struct.PartiallySignedTransaction.html)
This will allow the tx to be extracted with available data, verification of extracted tx.
This will also be useful and perhaps mandatory for multisig tx creation and signing.
Depends on bitcoindevkit/bdk-ffi#311
On rare occasions after a new install, the error Descriptor checksum mismatch
is thrown.
The workaround at the moment is to reinstall the app and the error won't appear anymore using the same private key.
Execute bdk methods in a new thread on the native side. Some methods already have this, need to add for the rest.
Error on iOS: "Code: Init Wallet Error Message: The operation couldn’t be completed. (bdk_rn.BdkError error 26.)"
Error on Android: "Code: Init Wallet Error Message: Descriptor(Key(InvalidNetwork))"
Hi. I am trying to make bdk-rn work with expo.
I can't even generate a 12 word mnemonic. 👇🏼
Replication steps:
Note: I am using Node v18.19.0, npm v10.5.0, windows machine
npx create-expo-app --template
Choose template: Blank (TypeScript)
"dependencies": {
"expo": "~50.0.14",
"expo-status-bar": "~1.11.1",
"react": "18.2.0",
"react-native": "0.73.6"
},
npm i --save bdk-rn
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, Button } from "react-native";
import { Mnemonic } from "bdk-rn";
import { WordCount } from "bdk-rn/lib/lib/enums";
import { useState } from "react";
export default function App() {
const [mnemonic, setMnemonic] = useState("");
const handleClick = async () => {
const mnemonic = await new Mnemonic().create(WordCount.WORDS12);
setMnemonic(mnemonic.asString());
};
return (
<View style={styles.container}>
<Text>Open up App.tsx to start working on your app!</Text>
<Button title="Generate" onPress={handleClick} />
<Text>Test: {mnemonic}</Text>
<StatusBar style="auto" />
</View>
);
}
...
npm start
Now I get the following error:
Possible unhandled promise rejection | TypeError: Cannot read property 'generateSeedFromWordCount' of null
Combined with issue #44, this becomes quickly problematic.
Performing a wallet.sync()
on app init result in at least 10 seconds waiting time.
Any other wallet.sync()
during the session makes the app unresponsive
#50 causing the following error when adhering to blockchain config type definitions:
JSON value '5' of type NSNumber cannot be converted to NSString
My erroneous config:
const config: BlockchainEsploraConfig = {
baseUrl: BLOCKEXPLORER,
proxy: '',
concurrency: 2,
timeout: 10,
stopGap: 25,
}
Working config (but with type errors):
const config: BlockchainEsploraConfig = {
baseUrl: BLOCKEXPLORER,
proxy: '',
concurrency: '2',
timeout: '10',
stopGap: '25',
}
Add a testing framework and test cases
The binary size of BDk for Android and IOS is quite large by default.
It would be great to have smaller binaries with different set of functionalities so that they can be used selectively for different applications.
This will be very useful for using BDK in mobile applications and Browsers(via WASM) and hardware wallets.
Below is an example of how functionality can be separated so that an application can select a suitable set of functionalities thereby reducing binary size. This is only an example, a better grouping of logical (and technically linked) components can be created based on BDK architecture.
HD Wallet functionality
This would only require functionality to generate seed, derive keys and addresses and ability to sign messages
Transaction creation and signing
Creating and signing all supported transaction types
Bitcoin Electrum Node Interaction
Ability to receive and parse block information from Electrum nodes
Ability to broadcast transactions to Electrum node
Bitcoin Core Interaction
Ability to receive and parse block information from Bitcoin Core
Ability to broadcast transactions
Bitcoin Electrs Interaction
Ability to receive and parse data from Electrs indexer
Ability to broadcast transactions to Electrs
I found that the change made in this line
https://github.com/LtbLightning/bdk-rn/blob/b31ab3dca45ddb4d98a56ecf2e8effdec54b201e/ios/BdkRnModule.swift#LL497C15-L497C15
Is now blocking the main thread iOS. Reverting the change fixes the issue.
Do you have any thoughts/feelings on updating the method return response for increased clarity on returned types?
At Synonym we use the following:
https://www.npmjs.com/package/@synonymdev/result
Example Usage:
const randomDataCheck = (data): Result<string> => {
if (!data) return err('No data available');
return ok('Data was provided');
};
const result = randomDataCheck('Some data');
if (result.isErr()) {
console.error(result.error.message); // "error message"
return;
}
const dataCheckRes = result.value;
This way we always know what's getting returned and it ensures we're checking each response before proceeding. It also helps keep our responses consistent across projects. I would be happy to create a PR with these changes if you believe it would benefit the bdk-rn library.
The readme can do with a few variations of the createDescriptor
, createWallet
, generateMnemonic
and transaction related methods.
Leaving this here for future reference.
I found and 2 issues after compiling my android APK. They did not occur while running react-native via react-native run-android
"code": "Init Wallet Error"
"message": "Can't obtain peer field ID for class com.sun.jna.Pointer"
&
"code": "Init Wallet Error"
"message": ""
The fix for these issues is simply adding the following proguard rules in my project:
# Package: bdk-rn
-keep class com.sun.jna.** { *; }
-keep class org.bitcoindevkit.** { *; }
Reference: https://github.com/LtbLightning/bdk-rn/tree/modify-create-wallet-interface#createdescriptor
Use xpriv
if provided else use mnemonic
, password
and network
Large variety of descriptors are possible reference: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md
createDescriptor
should be able to create as many of these descriptors as possible.
Add getTransactions method to retrieve both pending and confirmed transactions.
In createDescriptor:
Remove useMnemonic argument.
instead modify logic to:
use xpriv if set, otherwise, use mnemonic. Throw error if none or both are set.
if mnemonic flow is chosen network should be specified but password can be optional
The rest of the arguments should use default values.
npm install instructions in readme dont work
Upgrade API to align with v0.30.0 of bdk-ffi release https://github.com/bitcoindevkit/bdk-ffi/releases/tag/v0.30.0
I noticed that BdkRn.createWallet(...)
is blocking the UI thread on Android.
Is it something you are aware about?
When using DatabaseConfig().sqlite() it causes a crash on devices running iOS 15.
This is unfortunate since the alternative I'm using now is DatabaseConfig().memory(), however when using this you loose the benefits of persistence, which leads to address reuse in some cases.
ElectrumConfig
and EsploraConfig
method signatures do not match bdk ffi.
sock5
, retry
and validateDomain
argumentsReference:
ElectrumConfig
EsploraConfig
Currently, CreateDescriptors
creates descriptors
based on the path and script type specified by the user.
This is probably not as useful as having the ability to create a descriptor based on a standard BIP.
Because it assumes that the user knows the path and script type for a specific wallet type.
It will be more useful to have the ability to create descriptors for standard wallet types(bip44/49/84) based on BDK templates already available:
https://docs.rs/bdk/latest/bdk/descriptor/template/index.html
Templates currently available:
Bip44 BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/)
Bip44Public BIP44 public template. Expands to pkh(key/{0,1}/)
Bip49 BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/))
Bip49Public BIP49 public template. Expands to sh(wpkh(key/{0,1}/))
Bip84 BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/)
Bip84Public BIP84 public template. Expands to wpkh(key/{0,1}/)
P2Pkh P2PKH template. Expands to a descriptor pkh(key)
P2Wpkh P2WPKH template. Expands to a descriptor wpkh(key)
P2Wpkh_P2Sh P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))
Reference for descriptors: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md
I've downloaded this repository and have the wallet running locally however I am getting the errors below when I try to generate a mnemonic key:
WARN Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'generateMnemonic' of undefined
TypeError: Cannot read property 'generateMnemonic' of undefined
The repository for the code here that produces the error above is: https://github.com/inDemniFi/BitcoinWallet
Separately, I have also followed the instructions here on the website, https://bitcoindevkit.org/tutorials/exploring_bdk_rn/, and successfully have the wallet installed locally and loading on my phone, however I am getting the same error above.
Here is the entire error message:
WARN Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'generateMnemonic' of undefined
TypeError: Cannot read property 'generateMnemonic' of undefined
at ?anon_0_ (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4314:74)
at next (native)
at asyncGeneratorStep (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4493:26)
at _next (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4512:29)
at anonymous (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4517:14)
at tryCallTwo (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphoneos/lib/InternalBytecode/InternalBytecode.js:61:9)
at doResolve (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphoneos/lib/InternalBytecode/InternalBytecode.js:216:25)
at Promise (/private/var/folders/yw/6bx918xn4671rggfcdxz7fph0000gn/T/hermes/build_iphoneos/lib/InternalBytecode/InternalBytecode.js:82:14)
at anonymous (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4509:25)
at apply (native)
at getMnemonic (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:4323:26)
at _performTransitionSideEffects (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:66144:22)
at _receiveSignal (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:66094:45)
at onResponderRelease (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:65950:34)
at apply (native)
at invokeGuardedCallbackProd (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:82494:21)
at apply (native)
at invokeGuardedCallback (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:82670:42)
at apply (native)
at invokeGuardedCallbackAndCatchFirstError (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:82684:36)
at executeDispatch (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:82761:48)
at executeDispatchesInOrder (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:82783:26)
at executeDispatchesAndRelease (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84556:35)
at executeDispatchesAndReleaseTopLevel (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84563:43)
at forEach (native)
at forEachAccumulated (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:83377:22)
at runEventsInBatch (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84576:27)
at runExtractedPluginEventsInBatch (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84686:25)
at anonymous (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84657:42)
at batchedUpdates$1 (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:98122:20)
at batchedUpdates (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84532:36)
at _receiveRootNodeIDEvent (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84656:23)
at receiveTouches (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:84745:34)
at apply (native)
at __callFunction (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:6714:36)
at anonymous (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:6434:31)
at __guard (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:6651:15)
at callFunctionReturnFlushedQueue (http://192.168.1.107:8081/index.bundle//&platform=ios&dev=true&hot=false&lazy=true:6433:21)
As far as I understand, bdk-rn
currently allows to create a wallet only from a mnemonic. Would it make sense to have createWallet
taking a simple descriptor and expose generateExtendedKey
and restoreExtendedKey
so that the client app has more control?
Is it what this comment is about?
bdk has https://docs.rs/bdk/latest/bdk/wallet/tx_builder/struct.TxBuilder.html#method.add_foreign_utxo
it would be a great addition to bdk-rn
@BitcoinZavior yes, I am already using `concurrency` to speed things up a little
Originally posted by @Czino in #44 (comment)
Having set concurrency to just to 5 I noticed that in some instances the following error is thrown when a user calls the sync method around 5 times at the same time. (i.e. concurrency >= 25)
failed to lookup address information: nodename nor servname provided, or not known
After some digging I found the following explanation which is why I think concurrency might be the culprit behind
Wanted to take a note here, in case someone else hits this error and comes looking for it. Not sure if the issue should may be raised in the bdk/bdk-ffi repo
This may happen to just 0.5% of iPhone users and only for around the first 10 startups, after that it appears to be working.
Specifically I can see it happening for these
Crashed: com.facebook.react.JavaScript
EXC_BREAKPOINT 0x00000001d0549d7c
Crashed: com.facebook.react.JavaScript
0 libswiftCore.dylib 0x37d7c _assertionFailure(_:_:file:line:flags:) + 312
1 libswiftCore.dylib 0xadeb0 Dictionary.init<A>(_:uniquingKeysWith:) + 646
2 0x3b7898 BdkFunctions.init() + 27 (BdkFunctions.swift:27)
Not 100% sure but the issue might be resolved with #36
Trying to build a transaction. Unsure if im doing it correctly? I get the error
Exception in native call from JS
Any help much appreciated.
const txbuilder = await new TxBuilder().create();
await txbuilder.feeRate(2);
const addr = await new Address().create('muiFYa8MjFeorqCmboFqyNRc3aJReTdzC4');
await txbuilder.addRecipient(addr, 0.0001);
await txbuilder.finish(wallet);
When syncing, even after after creating a fresh wallet with a stopGap
setting of 5
, I am logging 200 requests on my electrum server.
Changing the stopGap
does not have any influence on these 200 requests. I even set it to 500 but still only see 200 requests.
I cannot find any setting to change the number of initial addresses to be scanned but I would expect it to be much lower (10/25/50)
Tested with BlockchainEsploraConfig
and BlockchainElectrumConfig
Tested on Android and iOS
Currently, bdk-rn
only store plain data (seedphase, password,..) in localstorage
that cause critical security issue. I glad to help you make change via PR, my plan is switch from localstorage
to react-native-keychain, but what do you think about it?
If everything is clear, I will create a PR for it.
It seems omitting the network
parameter on getMnemonic()
method results in a blocking error: Parameter specified as non-null is null.
Is there a reason setting the network is required at this stage?
A simpler API could be to use descriptor
if set, otherwise, use mnemonic
. Throw if none or both are set.
Originally posted by @testerez in #6 (comment)
For createWallet:
Remove useDescriptor argument.
instead modify logic to
use descriptor if set, otherwise, use mnemonic. Throw error if none or both are set.
if mnemonic flow is chosen network should be specified but password can be optional
the rest of the arguments should use default values.
Hi Bitcoin Zavior, thanks for writing this code to bridge react-native to BDK. This is the first time using and just noticed a few Typo's (I think) on the examples (which are now very different to the tutorial you did with with Conor from Bitcoin Developers...)
Create a Wallet & sync the balance of a descriptor
Current
const externalDescriptor = await new Descriptor().newBip44(descriptorSecretKey, KeyChainKind.External, Network.Testnet);
const internalDescriptor = await new Descriptor().newBip44(descriptorSecretKey, KeyChainKind.Internal, Network.Testnet);
I think KeyChainKind should be KeychainKind - c in chain is lowercase
and the import from 'bdk-rn/lib/lib/enums' need to include KeychainKind
Updated - changes show by * (star)
import { DescriptorSecretKey, Mnemonic, Blockchain, Wallet, DatabaseConfig, Descriptor } from 'bdk-rn';
import { WordCount, Network, *KeychainKind* } from 'bdk-rn/lib/lib/enums';
// ....
const mnemonic = await new Mnemonic().create(WordCount.WORDS12);
const descriptorSecretKey = await new DescriptorSecretKey().create(Network.Testnet, mnemonic);
const externalDescriptor = await new Descriptor().newBip44(descriptorSecretKey, *KeychainKind*.External, Network.Testnet);
const internalDescriptor = await new Descriptor().newBip44(descriptorSecretKey, *KeychainKind*.Internal, Network.Testnet);
A similar typo is in the second example
Create a public wallet descriptor
Current
import { WordCount, Network, KeyChainKind } from 'bdk-rn/lib/lib/enums';
Updated - changes show by * (star)
Lower case c in chain on import (case is correct in code)
import { WordCount, Network, *KeychainKind* } from 'bdk-rn/lib/lib/enums';
Quick question: for the Descriptor was using the old legacy .newBip44 intentional?
I was using Sparrow wallet on Testnet to check the mnemonic works and send some initial funds and took me a while to work out its Bip44 not Bip84.
I changed to Bip84 and sent testnet coins and the balance updated on Sparrow Wallet and using wallet.sync!
Which is great.
(I guess I could have made a legacy wallet with Sparrow and would have worked but...)
Hi, I'm new to both react native and BDK, so I'm sorry for the silly question.
I'm now running React Native with Expo:
npx expo start
and I get the error:
ERROR in ./node_modules/bdk-rn/src/index.ts 18:9
Module parse failed: Unexpected token (18:9)
File was processed with these loaders:
public _bdk: any;
|
| constructor() {
I tried to fix by adding:
pm i -D @expo/webpack-config
but it looks like I have to add a line in babel.config.js I tried adding bdk-nm but didn't manage to run it yet. (similar issue here)
Is there a way to run bdk-rn with expo or is not possible?
Thank you in advance for your time.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.