diff --git a/packages/stacking/README.md b/packages/stacking/README.md index 112d912fe..97f932c59 100644 --- a/packages/stacking/README.md +++ b/packages/stacking/README.md @@ -93,6 +93,8 @@ const amountMicroStx = 100000000000n; const privateKey = 'd48f215481c16cbe6426f8e557df9b78895661971d71735126545abddcd5377001'; // block height at which to stack const burnBlockHeight = 2000; +// signer key hex +const signerKey = '03bae4a7...e2e2c6b7e'; // Refer to initialization section to create client instance const stackingResults = await client.stack({ @@ -101,6 +103,7 @@ const stackingResults = await client.stack({ cycles, privateKey, burnBlockHeight, + signerKey, }); // { diff --git a/packages/stacking/src/index.ts b/packages/stacking/src/index.ts index 6ffb25db6..beef45e3f 100644 --- a/packages/stacking/src/index.ts +++ b/packages/stacking/src/index.ts @@ -1,5 +1,5 @@ // @ts-ignore -import { IntegerType, intToBigInt } from '@stacks/common'; +import { IntegerType, hexToBytes, intToBigInt } from '@stacks/common'; import { StacksNetwork } from '@stacks/network'; import { BurnchainRewardListResponse, @@ -21,6 +21,7 @@ import { TxBroadcastResult, UIntCV, broadcastTransaction, + bufferCV, callReadOnlyFunction, cvToString, getFee, @@ -36,6 +37,7 @@ import { PoxOperationPeriod, StackingErrors } from './constants'; import { ensureLegacyBtcAddressForPox1, ensurePox2Activated, + ensureSignerKeyForPox4, poxAddressToTuple, unwrap, unwrapMap, @@ -233,6 +235,8 @@ export interface LockStxOptions { amountMicroStx: IntegerType; /** the burnchain block height to begin lock */ burnBlockHeight: number; + /** hex-encoded signer key `(buff 33)`, required for >= pox-4 */ + signerKey?: string; } /** @@ -661,6 +665,8 @@ export class StackingClient { } /** + * `stack-stx` + * * Generate and broadcast a stacking transaction to lock STX * @param {LockStxOptions} options - a required lock STX options object * @returns {Promise} that resolves to a broadcasted txid if the operation succeeds @@ -670,6 +676,7 @@ export class StackingClient { poxAddress, cycles, burnBlockHeight, + signerKey, ...txOptions }: LockStxOptions & BaseTxOptions): Promise { const poxInfo = await this.getPoxInfo(); @@ -677,6 +684,7 @@ export class StackingClient { const contract = await this.getStackingContract(poxOperationInfo); ensureLegacyBtcAddressForPox1({ contract, poxAddress }); + ensureSignerKeyForPox4({ contract, signerKey }); const callOptions = this.getStackOptions({ amountMicroStx, @@ -684,6 +692,7 @@ export class StackingClient { poxAddress, contract, burnBlockHeight, + signerKey, }); const tx = await makeContractCall({ ...callOptions, @@ -1006,21 +1015,31 @@ export class StackingClient { cycles, contract, burnBlockHeight, + signerKey, }: { cycles: number; poxAddress: string; amountMicroStx: IntegerType; contract: string; burnBlockHeight: number; + signerKey?: string; }) { const address = poxAddressToTuple(poxAddress); const [contractAddress, contractName] = this.parseContractId(contract); + + const functionArgs = [ + uintCV(amountMicroStx), + address, + uintCV(burnBlockHeight), + uintCV(cycles), + ] as ClarityValue[]; + if (signerKey) functionArgs.push(bufferCV(hexToBytes(signerKey))); + const callOptions: ContractCallOptions = { contractAddress, contractName, functionName: 'stack-stx', - // sum of uStx, address, burn_block_height, num_cycles - functionArgs: [uintCV(amountMicroStx), address, uintCV(burnBlockHeight), uintCV(cycles)], + functionArgs, validateWithAbi: true, network: this.network, anchorMode: AnchorMode.Any, diff --git a/packages/stacking/src/utils.ts b/packages/stacking/src/utils.ts index 3372dd681..c8fe5abc2 100644 --- a/packages/stacking/src/utils.ts +++ b/packages/stacking/src/utils.ts @@ -349,3 +349,19 @@ export function ensureLegacyBtcAddressForPox1({ throw new Error('PoX-1 requires P2PKH/P2SH/P2SH-P2WPKH/P2SH-P2WSH bitcoin addresses'); } } + +/** + * @internal + * Throws unless a signerKey is given for >= PoX-4. + */ +export function ensureSignerKeyForGtePox4({ + contract, + signerKey, +}: { + contract: string; + signerKey?: string; +}) { + if (signerKey) return; + if (/\.pox(-[2-3])?$/.test(contract)) return; + throw new Error('PoX-4 requires a signer-key (buff 33) to stack'); +}