BTC Staking Simulation
Simulating a BTC staking transaction is a crucial step before broadcasting it to the network. Simulation helps:
- Prepare expected outputs
- Verify the success of the transaction
- Avoid errors like
No valid UTXO found for treasury fee
Example:
const resDeposit = await simulateStakeBTC({
motoChefContract,
stakeAmount,
feeAmount,
netStakeAmount,
treasuryAddressP2TR,
accountAddressTyped,
});
The returned object contains:
- Outputs: The fee and staking outputs to include
- Result: The simulated transaction to send later
Always run this simulation step before sendTransaction()
.
Full example:
This full implementation is an example taken from a MotoChef staking use case. It demonstrates how to manually construct simulation outputs for a specific pool and pass them to the contract before calling stakeBTC()
.
export async function simulateStakeBTC({
motoChefContract,
stakeAmount,
feeAmount,
netStakeAmount,
treasuryAddressP2TR,
accountAddressTyped,
}: {
motoChefContract: IMotoChef;
stakeAmount: bigint;
feeAmount: bigint;
netStakeAmount: bigint;
treasuryAddressP2TR: string;
accountAddressTyped: string;
}): Promise<{ result: StakeBTC; outputs: PsbtOutputExtended[] }> {
const outSimulation: StrippedTransactionOutput[] = [];
const outputs: PsbtOutputExtended[] = [];
let index = 2;
// Treasury output
outputs.push({
address: treasuryAddressP2TR,
value: Number(feeAmount),
});
outSimulation.push({
index,
to: treasuryAddressP2TR,
value: feeAmount,
flags: TransactionOutputFlags.hasTo,
scriptPubKey: undefined,
});
index++;
// Stake output
outputs.push({
address: accountAddressTyped,
value: Number(netStakeAmount),
});
outSimulation.push({
index,
to: accountAddressTyped,
value: netStakeAmount,
flags: TransactionOutputFlags.hasTo,
scriptPubKey: undefined,
});
// Set simulation details
const details: ParsedSimulatedTransaction = {
inputs: [],
outputs: outSimulation,
};
motoChefContract.setTransactionDetails(details);
// Simulate stakeBTC
const result = await motoChefContract.stakeBTC(stakeAmount);
if (!result.properties.success) throw new Error("Failed to simulate stake");
return { result, outputs };
}