For the complete documentation index, see llms.txt. This page is also available as Markdown.

fetchConstructLockupScript

Calls the pox-5 construct-lockup-script read-only and returns the L1 lockup witness script the contract builds for a staker, unlock height and pair of unlock subscripts. Use it to check a script built locally with buildLockScript before you fund it.


Usage

import { bytesToHex } from '@stacks/common';
import {
  buildLockScript,
  buildUnlockScript,
  fetchBond,
  fetchBondL1UnlockHeight,
  fetchConstructLockupScript,
} from '@stacks/bitcoin-staking';

const bond = await fetchBond({ bondIndex: 1, network: 'mainnet' });
if (!bond) throw new Error('bond 1 is not set up');

const params = {
  stxAddress: 'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7',
  unlockHeight: await fetchBondL1UnlockHeight({ bondIndex: 1, network: 'mainnet' }),
  unlockBytes: buildUnlockScript('0316e35d38b52d4886e40065e4952a49535ce914e02294be58e252d1998f129b19'), // staker's compressed public key
  earlyUnlockBytes: bond.earlyUnlockBytes,
};

const onchain = await fetchConstructLockupScript({ ...params, network: 'mainnet' });
const local = buildLockScript(params);

if (bytesToHex(onchain) !== bytesToHex(local)) {
  throw new Error('Local lockup script does not match pox-5. Do not fund it.');
}

Notes

  • Wraps construct-lockup-script. The script is OP_IF <unlockHeight> OP_CHECKLOCKTIMEVERIFY OP_ELSE OP_SIZE <32> OP_EQUALVERIFY OP_SHA256 <H> OP_EQUALVERIFY <earlyUnlockBytes> OP_ENDIF OP_VERIFY <unlockBytes>, where <H> is sha256(sha256(to-consensus-buff? staker)).

  • register-for-bond rebuilds this script for every L1 lockup output and fails with ERR_INVALID_LOCKUP_SCRIPT (u42) if the output does not pay to it (L2061-L2064, L2080-L2082).

  • An unlockHeight of 2^39 (549,755,813,888) or more makes the contract return ERR_INVALID_UNLOCK_HEIGHT (u52). The SDK then throws an Error whose message starts with construct-lockup-script returned (err u52), followed by the error's name and description.

  • This read-only does not check the bond's minimum unlock height or the 500,000,000 locktime threshold. register-for-bond does (L2074-L2079), so check the height against fetchBondL1UnlockHeight as well.

  • For the 34-byte P2WSH output script, use fetchConstructLockupOutputScript.

  • Throws an Error if the node returns a non-2xx status (the message starts with Error calling read-only function.) or answers okay: false (the message is the node's cause).


Signature


Returns

Promise<Uint8Array>

The raw witness script bytes.


Parameters

opts.stxAddress (required)

  • Type: string

Stacks address of the staker. A contract principal is also accepted.

opts.unlockHeight (required)

  • Type: IntegerType

Bitcoin block height for the OP_CHECKLOCKTIMEVERIFY branch. Must be below 2^39.

opts.unlockBytes (required)

  • Type: Uint8Array | string

Staker-signature subscript, as raw bytes or hex, at most 683 bytes. buildUnlockScript builds the single-key form.

opts.earlyUnlockBytes (required)

  • Type: Uint8Array | string

The bond's early-unlock subscript, earlyUnlockBytes from fetchBond, as raw bytes or hex, at most 683 bytes.

opts.network (optional)

  • Type: StacksNetworkName | StacksNetwork

The network to query: a name such as 'mainnet' or 'testnet', or a StacksNetwork object. Defaults to 'mainnet'.

opts.client (optional)

  • Type: { baseUrl?: string; fetch?: FetchFn }

Overrides the API base URL or the fetch function, for example to query your own node. Fields you set replace the network's defaults.

Was this helpful?