buildGrantSignerKey
Builds an unsigned contract call to pox-5 grant-signer-key, which records that a signer key authorizes a signer-manager to register it. The authorization is a SIP-018 signature from the signer key over the signer-manager and an authId.
Usage
import {
buildGrantSignerKey,
fetchEligibleGrantSignerKey,
signSignerGrant,
} from '@stacks/bitcoin-staking';
import { STACKS_MAINNET } from '@stacks/network';
import {
fetchNonce,
privateKeyToAddress,
privateKeyToPublic,
publicKeyToHex,
} from '@stacks/transactions';
const network = 'mainnet';
const signerPrivateKey = process.env.SIGNER_KEY!;
const signerKey = publicKeyToHex(privateKeyToPublic(signerPrivateKey));
const signerManager = 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.my-signer-manager';
const authId = 1n;
const signerSignature = signSignerGrant({
signerManager,
authId,
chainId: STACKS_MAINNET.chainId,
privateKey: signerPrivateKey,
});
const check = await fetchEligibleGrantSignerKey({ signerKey, signerManager, authId, signerSignature, network });
if (!check.ok) throw new Error(`grant-signer-key would fail: ${check.reasons}`);
// contract-caller must equal signerManager: see Notes.
const senderKey = process.env.SENDER_KEY!;
const tx = await buildGrantSignerKey({
signerKey,
signerManager,
authId,
signerSignature,
publicKey: publicKeyToHex(privateKeyToPublic(senderKey)),
fee: 10_000n, // micro-STX
nonce: await fetchNonce({ address: privateKeyToAddress(senderKey, network), network }),
network,
});Notes
pox-5 requires
contract-callerto equalsignerManagerand fails withERR_UNAUTHORIZED_SIGNER_REGISTRATION (u26)otherwise (pox-5.clar L2743-L2811). This builder calls pox-5 directly, socontract-calleris the transaction's origin account. With a signer-manager contract assignerManager, the call fails with u26: the signer-manager contract has to submit the grant itself. signSignerGrant and verifySignerGrant produce and check the signature it forwards. See Deploy a signer-manager contract.Each
(signerKey, signerManager, authId)can be granted once (ERR_SIGNER_KEY_GRANT_USED (u12)). Check with fetchSignerKeyGrantUsed.pox-5 recovers a public key from
signerSignatureover the grant hash and compares it withsignerKey. An unrecoverable signature fails withERR_INVALID_SIGNATURE_RECOVER (u13), a different key withERR_INVALID_SIGNATURE_PUBKEY (u14). The hash includes the chain ID pox-5 runs on, so sign with the target network'schainId.fetchEligibleGrantSignerKey dry-runs the replay and signature checks. It does not run the caller check.
On success, pox-5 marks the
authIdused and sets the grant for(signerKey, signerManager).register-signerand every staking entry point require that grant. Remove it with buildRevokeSignerGrant.No asset moves, so the call needs no post conditions.
A txid from broadcastTransaction confirms submission only. The call can still fail on-chain: read the mined transaction's result and pass an
(err uN)to parsePox5Error.
Signature
args is a BuildGrantSignerKeyTxArgs, which includes TxParams.
Returns
Promise<StacksTransactionWire>
Resolves to an unsigned StacksTransactionWire that calls pox-5 grant-signer-key. Sign it with TransactionSigner, then send it with broadcastTransaction.
Parameters
args.signerKey (required)
Type:
Uint8Array | string
Compressed secp256k1 public key of the signer, 33 bytes, as bytes or hex.
args.signerManager (required)
Type:
string
Stacks principal of the signer-manager being authorized.
args.authId (required)
Type:
IntegerType
Replay nonce. It must be the value the signer signed.
args.signerSignature (required)
Type:
Uint8Array | string
65-byte recoverable signature in RSV order, as bytes or hex, from signSignerGrant.
args.fee (required)
Type:
IntegerType
Transaction fee in micro-STX.
args.nonce (required)
Type:
IntegerType
Nonce of the origin account. Read it with fetchNonce.
args.network (required)
Type:
StacksNetworkName | StacksNetwork
A name such as 'mainnet' or 'testnet', or a StacksNetwork object. Sets the contract address (the network's boot address, SP000000000000000000002Q6VF78 on mainnet) and the transaction version and chain ID.
args.publicKey (required for a single-sig origin)
Type:
string
Hex public key of the account that signs the transaction.
args.publicKeys and args.numSignatures (required for a multisig origin)
Type:
PublicKey[]andnumber
Pass these instead of publicKey to build for an M-of-N multisig origin. This package defaults useNonSequentialMultiSig to true; pass false for the sequential hash mode. Pass address to check the key order against the multisig address.
args.postConditions (optional)
Type:
PostCondition[]
Post conditions to attach. The builder adds none.
args.postConditionMode (optional)
Type:
PostConditionModeName
'allow', 'deny' or 'originator'. Defaults to 'deny'.
Was this helpful?