Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/wasm example #85

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

riverKanies
Copy link
Contributor

@riverKanies riverKanies commented Nov 19, 2024

Here's the quickstart example in WASM.

The code could use some cleaning but I figured I'd go ahead and get some feedback on the direction here.

Seemed like the most important thing was to highlight some of the limitations of using BDK in wasm

UPDATE:
closer to full wallet than quickstart because wanted to include persistence as it is different in wasm

@notmandatory
Copy link
Member

notmandatory commented Nov 20, 2024

This looks like a great start. We might be able to soften the language a bit about the limitations since there are various ways to get around them. For example it should be possible to create a custom persister that uses the cloud or browser storage, and the Mutiny team got around the http(s) only limitation for their lightning wallet by building a proxy https <--> tcp.

For this example we should also figure out / demo the solution for bitcoindevkit/bdk#1683.

@darioAnongba
Copy link

Thanks so much @riverKanies !

@notmandatory I got the retry mechanism working but might be a bit too obscure as we dive into the unsafe: bitcoindevkit/bdk#1683 (comment)

Any function that requires system time, such as any sort of timestamp, must access system time through a wasm binding to the JavaScript environment. This means some BDK functions that are commonly used in rust won't work in WASM and instead an alternate rust function that takes a timestamp as an argument must be used (I.E. instead of `.apply_update()` we must use `.apply_update_at()`).

### Network access is limited to http(s)
This effectively means that the blockchain client must be an Esplora instance. Both RPC and Electrum clients require sockets and will not work for BDK in a WASM environment out of the box.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@notmandatory I understand very well this limitation for Electrum now but doesn't the Bitcoin node's RPC allow for HTTP? This works fine when I test with my Polar network, so why isn't the client working on the browser ?

curl --location 'http://127.0.0.1:18443' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic my_auth' \
--data '{
  "jsonrpc": "1.0",
  "id": "getblockchaininfo",
  "method": "getblockchaininfo",
  "params": []
}'

--8<-- "examples/wasm/rust/src/lib.rs:new"
```

Notice we are using an in-memory wallet with `.create_wallet_no_persist()`. If you try to use persistence through file or database you will get an error becuase those features require OS access. Instead we have to create a binding to pass the wallet data to the JavaScript environment where we can handle persistence.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we should mention that you should implement the WalletPersister or AsyncWalletPersister if you want persistence in the browser as not supported currently by BDK.

I implemented a persister myself: https://github.com/darioAnongba/bdk-wasm/blob/main/src/bitcoin/storage.rs. It is very specific to my use case but a LocalStoragePersister would be pretty easy to implement and then you can call create_wallet or create_wallet_async.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great! yes this is one of the main areas I'm wanting to detail more

"CC": "/opt/homebrew/opt/llvm/bin/clang"
},
"rust-analyzer.cargo.target": "wasm32-unknown-unknown",
"rust-analyzer.checkOnSave.allTargets": false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one is more optional ?

@riverKanies
Copy link
Contributor Author

@notmandatory ok I hear you, thanks for the feedback! I'll take that into consideration on my next iteration

@riverKanies
Copy link
Contributor Author

riverKanies commented Dec 4, 2024

I believe this is ready for a final review @notmandatory @thunderbiscuit @darioAnongba

The intention is just to be a minimal example of a custom WASM package for bdk, highlighting the particular considerations (limitations) of the WASM env compared to normal rust.

We'll have a separate example for using the bdk-wasm package out of the box at some point (hopefully)

}

// --8<-- [start:store]
pub fn take_staged(&mut self) -> JsResult<String> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@darioAnongba see use of serde_json here. note I'm converting to json string in this example rn because I'm just saving to localStorage, but you can pas JsValue json and stringify on js side

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants