Stake Bitcoin to BitHive with Relayer API.
@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.
pnpm install @bithive/relayer-api
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
// 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 and finalize the PSBT with wallet
if (!provider.signPsbt) {
throw Error('signPsbt is not supported');
}
const signedPsbt = await provider.signPsbt(unsignedPsbt);
// 3. Submit the finalized PSBT for broadcasting and relaying
await relayer.deposit.submitFinalizedPsbt({
psbt: signedPsbt,
});
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 confirmed deposit
const confirmedDeposit = deposits.find(
(deposit) =>
['DepositConfirmed', 'DepositConfirmedInvalid'].includes(
deposit.status,
),
);
if (!confirmedDeposit) {
throw Error('No confirmed deposit that is ready to unstake');
}
// 1. Build the unstaking message that is ready for signing
const { message } = await relayer.unstake.buildUnsignedMessage({
deposits: [{
txHash: confirmedDeposit.depositTxHash,
vout: confirmedDeposit.depositVout,
}],
publicKey,
});
// 2. Sign the unstaking message with wallet
if (!provider.signMessage) {
throw Error('signMessage is not supported');
}
const signature = await provider.signMessage(message);
// 3. Submit the unstaking signature and relay to BitHive contract on NEAR
await relayer.unstake.submitSignature({
deposits: [{
txHash: confirmedDeposit.depositTxHash,
vout: confirmedDeposit.depositVout,
}],
publicKey,
signature: Buffer.from(signature, 'base64').toString('hex'),
});
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,
});
let partiallySignedPsbt: string | undefined = undefined;
if (account.pendingSignPsbt) {
// If there's a pending PSBT for signing, user cannot request signing a new PSBT
partiallySignedPsbt = account.pendingSignPsbt.psbt;
} else {
// Get the deposits by public key
const { deposits } = await relayer.user.getDeposits({
publicKey,
});
// Find the first deposit that is ready to withdraw
const unstakedDeposit = deposits.find(
(deposit) =>
['UnstakeConfirmed'].includes(deposit.status),
);
// 1. Build the PSBT that is ready for signing
const { psbt: unsignedPsbt } = await relayer.withdraw.buildUnsignedPsbt({
deposits: {
txHash: unstakedDeposit.depositTxHash,
vout: unstakedDeposit.depositVout,
},
recipientAddress,
publicKey,
// Optional: specify `fee` or `feeRate` here if needed
});
// 2. Sign the PSBT with wallet. Don't finalize it.
if (!provider.signPsbt) {
throw Error('signPsbt is not supported');
}
partiallySignedPsbt = await provider.signPsbt(unsignedPsbt, {
autoFinalized: false,
toSignInputs: [{
index: 0,
publicKey,
}],
});
}
// 3. Sign the PSBT with NEAR Chain Signatures
const { psbt: fullySignedPsbt } = await relayer.withdraw.chainSignPsbt({
psbt: partiallySignedPsbt,
});
// 4. Submit the finalized PSBT for broadcasting and relaying
await relayer.withdraw.submitFinalizedPsbt({
psbt: fullySignedPsbt,
});