Wiki Home
Mini Bitcoin Wallet in F# using NBitcoin Output
Descriptors
#r "nuget:NBitcoin"
open NBitcoin
open NBitcoin.Scripting
open System.IO
type TWallet = {
Mnemonic: Mnemonic
[Network](Network.html): Network
}
let recoverWallet (mnemonic: Mnemonic) (network:Network) =
{ Mnemonic = mnemonic; Network = network }
let createWallet (network:Network) =
recoverWallet (Mnemonic (Wordlist.English, WordCount.Twelve)) network
let getExtKey (wallet: TWallet) =
wallet.Mnemonic.DeriveExtKey()
let getExtPubKey (wallet: TWallet) =
wallet
|> getExtKey
|> fun x -> x.Neuter();
let getKeyProvider (wallet: TWallet) =
let masterKey = wallet |> getExtKey
let masterPubKey = masterKey.Neuter()
let keyProvider = FlatSigningRepository()
keyProvider.SetSecret (masterPubKey.PubKey.Hash, masterKey)
keyProvider
let getOutputDescriptors (wallet: TWallet): OutputDescriptor list =
let parseDescriptor desc = OutputDescriptor.Parse (desc = desc, network = wallet.Network, repo = FlatSigningRepository())
let coin = if wallet.Network = Network.TestNet then 1 else 0
let xpub = wallet |> getExtPubKey |> fun x -> x.ToString(wallet.Network)
[
$"pkh({xpub}/44'/{coin}'/0'/0/*)"
$"pkh({xpub}/44'/{coin}'/0'/1/*)"
$"sh(wpkh({xpub}/49'/{coin}'/0'/0/*))"
$"sh(wpkh({xpub}/49'/{coin}'/0'/1/*))"
$"wpkh({xpub}/84'/{coin}'/0'/0/*)"
$"wpkh({xpub}/84'/{coin}'/0'/1/*)"
] |> List.map parseDescriptor
let derivateScript (index: uint32) (keyProvider: FlatSigningRepository) (descriptor: OutputDescriptor) =
let _, scripts = descriptor.TryExpand(index, keyProvider, keyProvider, cache = null)
scripts
let saveWallet (walletName:string) (wallet:TWallet) = async {
File.WriteAllTextAsync (walletName, wallet.Mnemonic.ToString()) |> Async.AwaitTask |> ignore
return wallet
}
let loadWallet (walletName:string) network = async {
let! mnemonicPhrase = File.ReadAllTextAsync walletName |> Async.AwaitTask
let mnemonic = Mnemonic(mnemonicPhrase, wordlist = null)
return recoverWallet mnemonic network
}
let saveNew walletName =
createWallet >> (saveWallet walletName)