ledger-bitcoin
v0.2.3
Published
Ledger Hardware Wallet Bitcoin Application Client
Downloads
15,416
Maintainers
Readme
Ledger Bitcoin application client
Overview
TypeScript client for Ledger Bitcoin application. Supports versions 2.1.0 and above of the app.
Main repository and documentation: https://github.com/LedgerHQ/app-bitcoin-new
Install
$ yarn add ledger-bitcoin
Or if you prefer using npm:
$ npm install ledger-bitcoin
Building
$ yarn
$ yarn build
Getting started
The following example showcases all the main methods of the Client
's interface.
More examples can be found in the test suite.
Testing the signPsbt
method requires a valid PSBT, and provide the corresponding wallet policy; it is skipped by default in the following example.
import { AppClient, DefaultWalletPolicy, WalletPolicy } from 'ledger-bitcoin';
import Transport from '@ledgerhq/hw-transport-node-hid';
// This examples assumes the Bitcoin Testnet app is running.
// Make sure to use addresses compatible with mainnet otherwise, by using paths where the BIP-44 coin_type
// is "0'" and not "1'".
async function main(transport) {
const app = new AppClient(transport);
// ==> Get the master key fingerprint
const fpr = await app.getMasterFingerprint();
console.log("Master key fingerprint:", fpr.toString("hex"));
// ==> Get and display on screen the first taproot address
const firstTaprootAccountPubkey = await app.getExtendedPubkey("m/86'/1'/0'");
const firstTaprootAccountPolicy = new DefaultWalletPolicy(
"tr(@0/**)",
`[${fpr}/86'/1'/0']${firstTaprootAccountPubkey}`
);
const firstTaprootAccountAddress = await app.getWalletAddress(
firstTaprootAccountPolicy,
null,
0,
0,
true // show address on the wallet's screen
);
console.log("First taproot account receive address:", firstTaprootAccountAddress);
// ==> Register a multisig wallet named "Cold storage"
const ourPubkey = await app.getExtendedPubkey("m/48'/1'/0'/2'");
const ourKeyInfo = `[${fpr}/48'/1'/0'/2']${ourPubkey}`;
const otherKeyInfo = "[76223a6e/48'/1'/0'/2']tpubDE7NQymr4AFtewpAsWtnreyq9ghkzQBXpCZjWLFVRAvnbf7vya2eMTvT2fPapNqL8SuVvLQdbUbMfWLVDCZKnsEBqp6UK93QEzL8Ck23AwF";
const multisigPolicy = new WalletPolicy(
"Cold storage",
"wsh(sortedmulti(2,@0/**,@1/**))", // a 2-of-2 multisig policy template
[
otherKeyInfo, // some other bitcoiner
ourKeyInfo, // that's us
]
)
const [policyId, policyHmac] = await app.registerWallet(multisigPolicy);
console.log(`Policy hmac: ${policyHmac.toString("hex")}. Store it safely (together with the policy).`);
console.assert(policyId.compare(multisigPolicy.getId()) == 0) // should never fail
// ==> Derive and show an address for "Cold storage" that was just registered
const multisigAddress = await app.getWalletAddress(multisigPolicy, policyHmac, 0, 0, true);
console.log(`Multisig wallet address: ${multisigAddress}`);
// ==> Sign a psbt
// TODO: set a wallet policy and a valid psbt file in order to test psbt signing
const psbt = null; // a base64-encoded psbt, or a binary psbt in a Buffer
const signingPolicy = null; // an instance of WalletPolicy
const signingPolicyHmac = null; // if not a default wallet policy, this must also be set
if (!psbt || !signingPolicy) {
console.log("Nothing to sign :(");
await transport.close();
return;
}
// result will be a list of triples [i, partialSig], where:
// - i is the input index
// - partialSig is an instance of PartialSignature; it contains a pubkey and a signature,
// and it might contain a tapleaf_hash.
const result = await app.signPsbt(psbt, signingPolicy, signingPolicyHmac);
console.log("Returned signatures:");
console.log(result);
await transport.close();
}
Transport.default.create()
.then(main)
.catch(console.log);