@bithive/relayer-api
v0.0.5
Published
BitHive Relayer API
Downloads
298
Readme
BitHive Relayer API
Stake Bitcoin to BitHive with Relayer API.
Introduction
@bithive/relayer-api
is a library that provides a simple interface for staking Bitcoin to BitHive with minimal efforts. It is designed to be used in the browser and Node.js. It acts as a client for the BitHive Relayer.
Installation
pnpm install @bithive/relayer-api
Usage
Stake Bitcoin
import { createRelayerClient } from '@bithive/relayer-api';
// Create a relayer client
const relayer = createRelayerClient({ url: config.relayerRpcUrl });
// User public key (compressed)
const publicKey = "0277...288a";
// User address
// Supported Address Types
// - Native Segwit (P2WPKH)
// - Nested Segwit (P2SH-P2WPKH)
// - Taproot (P2TR)
// - Legacy (P2PKH)
const address = "tb1q...wrh8";
// Bitcoin amount that is within the valid scope
// e.g. between 0.005 and 0.1 BTC
const amount = 1000000; // 0.01 BTC
// BTC provider with `signPsbt` interface
const provider = window.unisat; // UniSat wallet
if (provider.signPsbt) {
// 1. Build the PSBT that is ready for signing
const { psbt: unsignedPsbt } = await relayer.deposit.buildUnsignedPsbt({
publicKey,
address,
amount,
// optional: specify `fee` or `feeRate` here if needed
});
// 2. Sign the PSBT with wallet
const signedPsbt = await provider.signPsbt(unsignedPsbt);
// 3. Submit the signed PSBT for broadcasting and relaying
await relayer.deposit.submitFinalizedPsbt({
psbt: signedPsbt,
publicKey,
});
} else {
throw Error("signPsbt is not supported");
}
Unstake Bitcoin
import { createRelayerClient } from '@bithive/relayer-api';
// Create a relayer client
const relayer = createRelayerClient({ url: config.relayerRpcUrl });
// User public key (compressed)
const publicKey = "0277...288a";
// BTC provider with `signMessage` interface
const provider = window.unisat; // UniSat wallet
// Get the deposits by public key
const { deposits } = await relayer.user.getDeposits({
publicKey,
});
// Find the first active deposit
const activeDeposit = deposits.find(
(deposit) =>
["DepositConfirmed", "DepositConfirmedInvalid"].includes(
deposit.status,
),
);
if (!activeDeposit) {
throw Error("No active deposit that is ready to unstake");
}
if (provider.signMessage) {
// 1. Build the unstake message that is ready for signing
const { message } = await relayer.unstake.buildUnsignedMessage({
deposits: [{
txHash: activeDeposit.depositTxHash,
vout: activeDeposit.depositVout,
}],
publicKey,
});
// 2. Sign the unstake message with wallet
const signature = await provider.signMessage(message);
// 3. Submit the signature and relaying to BitHive contract on NEAR
await relayer.unstake.submitSignature({
deposits: [{
txHash: activeDeposit.depositTxHash,
vout: activeDeposit.depositVout,
}],
publicKey,
signature: Buffer.from(signature, 'base64').toString('hex'),
});
} else {
throw Error("signMessage is not supported");
}
Withdraw Bitcoin
import { createRelayerClient } from '@bithive/relayer-api';
// Create a relayer client
const relayer = createRelayerClient({ url: config.relayerRpcUrl });
// User public key (compressed)
const publicKey = "0277...288a";
// Recipient address (can be different with user address)
const recipientAddress = "tb1q...wrh8";
// BTC provider with `signPsbt` interface
const provider = window.unisat; // UniSat wallet
// Get the account info by public key
const { account } = await relayer.user.getAccount({
publicKey,
});
// Get the deposits by public key
const { deposits } = await relayer.user.getDeposits({
publicKey,
});
// Filter the deposits that are ready to withdraw
const withdrawableDeposits = deposits.filter(
(deposit) =>
["UnstakeConfirmed", "ChainSignProcessing"].includes(
deposit.status,
),
);
let partiallySignedPsbt: string | undefined = undefined;
if (account.pendingSignPsbt) {
// If pending chain sign PSBT exists, user cannot chain sign other PSBT
partiallySignedPsbt = account.pendingSignPsbt.psbt;
} else if (provider.signPsbt) {
// 1. Build the PSBT that is ready for signing
const { psbt: unsignedPsbt } = await relayer.withdraw.buildUnsignedPsbt({
deposits: withdrawableDeposits.map((withdrawableDeposit) => ({
txHash: withdrawableDeposit.depositTxHash,
vout: withdrawableDeposit.depositVout,
})),
recipientAddress,
// optional: specify `fee` or `feeRate` here if needed
});
// 2. Sign the PSBT with wallet
partiallySignedPsbt = await provider.signPsbt(unsignedPsbt, {
autoFinalized: false, // Don't finalize it
toSignInputs: withdrawableDeposits.map((_, index) => ({
index,
publicKey,
})),
});
} else {
throw Error("signPsbt is not supported");
}
// 3. Sign the PSBT with NEAR Chain Signatures Service asynchronously
const { id } = await relayer.withdraw.chainSignPsbtAsync({
psbt: partiallySignedPsbt,
});
// 4. Poll fully signed PSBT
const { psbt: fullySignedPsbt } = await relayer.withdraw.pollChainSignedPsbt({ id });
// 5. Submit the fully signed PSBT for broadcasting and relaying
await relayer.withdraw.submitFinalizedPsbt({
psbt: fullySignedPsbt,
});