Giter Site home page Giter Site logo

bdk-rn's People

Contributors

bitcoinzavior avatar coreyphillips avatar czino avatar shobitb avatar staxolotl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bdk-rn's Issues

Typo's in the examples in README.md

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';

Thanks

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...)

Running on Expo

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:

  • ./node_modules/source-map-loader/dist/cjs.js
    You may need an additional loader to handle the result of these loaders.
    |
    | class BdkInterface {

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.

createWallet: Use`descriptor` if set, otherwise, use `mnemonic`. Throw if none or both are set.

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.

BlockChainConfig number types causing runtime errors

#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',
}

Create descriptors for standard wallet types(bip44/49/84)

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

Update Method Return Response

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.

Android - Compiled app fails at creating wallet

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.** { *; }

Plan for secure storage

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.

getTransactions API

Add getTransactions method to retrieve both pending and confirmed transactions.

Error: failed to lookup address information: nodename nor servname provided, or not known

          @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

When will this lib upgrade to the latest version of BDK 0.29.0 ?

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

`wallet.sync()` is scanning 200 addresses

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

TypeError: Cannot read property 'generateMnemonic' of undefined

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)

Add more examples to Readme

The readme can do with a few variations of the createDescriptor, createWallet, generateMnemonic and transaction related methods.

[Android] - initWallet - descriptor not always defined

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

fun walletInit(
descriptor: String,
changeDescriptor: String? = null,
network: String,
dbConfigID: String,
result: Promise
) {
Thread {
try {
val id = randomId()
_wallets[id] = Wallet(
_descriptors[descriptor]!!,
if (changeDescriptor != null) _descriptors[changeDescriptor]!! else null,
setNetwork(network),
_databaseConfigs[dbConfigID]!!
)
result.resolve(id)
} catch (error: Throwable) {
result.reject("Init wallet error", error.localizedMessage, error)
}
}.start()
}

Expo with BDK-RN

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

  1. Init expo
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"
  },
  1. Install bdk-rn
npm i --save bdk-rn
  1. Update App.tsx
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>
  );
}

...
  1. Run the app
npm start
  1. Use Expo Go to run the app (running on my iPhone 12)

Now I get the following error:

Possible unhandled promise rejection | TypeError: Cannot read property 'generateSeedFromWordCount' of null

cc @BitcoinZavior

`wallet.sync()` is blocking execution on android

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

[Android] Descriptor checksum mismatch

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.

DatabaseConfig().sqlite() not working on iOS 15 and below

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.

createWallet: error on bitcoin as network.

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))"

Exception in native call from JS

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);

getMnemonic() requires network parameter

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?

java.lang.String cannot be cast to java.lang.Double

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',
};

Ability to choose functionality selectively from BDK

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.

  1. HD Wallet functionality
    This would only require functionality to generate seed, derive keys and addresses and ability to sign messages

  2. Transaction creation and signing
    Creating and signing all supported transaction types

  3. Bitcoin Electrum Node Interaction
    Ability to receive and parse block information from Electrum nodes
    Ability to broadcast transactions to Electrum node

  4. Bitcoin Core Interaction
    Ability to receive and parse block information from Bitcoin Core
    Ability to broadcast transactions

  5. Bitcoin Electrs Interaction
    Ability to receive and parse data from Electrs indexer
    Ability to broadcast transactions to Electrs

update createDescriptor api

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.

[iOS] Crashes on init for some devices

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

  • iOS 16.3.1 - iPhone 12 Pro Max
  • iOS 15.5.0 - iPhone 13 Mini

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

getTransactions

we have getPending and getConfirmed, we need to add getTransactions method to retrieve both pending and confirmed transactions

Create descriptor with a xpub instead of xpriv

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.

PoC for using JSI instead of platform binary

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:

  • Eliminates constraints of RN bridge
  • Will allow reuse of bdk ffi rust code directly thus providing more api
  • Will reduce effort and maintenance in using native wrapper code in Android and iOS
  • Performance improvements
  • Eliminate cold start time

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.