import { Buffer , IntegerType , intToBigInt } from '@stacks/common' ; import { StacksTransaction } from './transaction' ; import { StacksNetwork , StacksMainnet , StacksTestnet } from '@stacks/network' ; import { createTokenTransferPayload , createSmartContractPayload , createContractCallPayload , serializePayload , Payload , } from './payload' ; import { createSingleSigSpendingCondition , createMultiSigSpendingCondition , createSponsoredAuth , createStandardAuth , } from './authorization' ; import { publicKeyToString , createStacksPrivateKey , getPublicKey , publicKeyToAddress , pubKeyfromPrivKey , publicKeyFromBuffer , createStacksPublicKey , } from './keys' ; import { TransactionSigner } from './signer' ; import { createSTXPostCondition , createFungiblePostCondition , createNonFungiblePostCondition , } from './postcondition' ; import { PostCondition , STXPostCondition , FungiblePostCondition , NonFungiblePostCondition , } from './postcondition-types' ; import { AddressHashMode , AddressVersion , FungibleConditionCode , NonFungibleConditionCode , PostConditionMode , PayloadType , AnchorMode , TransactionVersion , TxRejectedReason , SingleSigHashMode , } from './constants' ; import { createLPList } from './types' ; import { AssetInfo , createStandardPrincipal , createContractPrincipal } from './postcondition-types' ; import { cvToHex , parseReadOnlyResponse , omit , validateTxId } from './utils' ; import { fetchPrivate } from '@stacks/common' ; import { ClarityValue , PrincipalCV } from './clarity' ; import { validateContractCall , ClarityAbi } from './contract-abi' ; import { c32address } from 'c32check' ; param { string } address param { StacksNetwork } network return export async function getNonce ( address , network ? ) { const defaultNetwork = new StacksMainnet ( ) ; const url = network ? network . getAccountApiUrl ( address ) : defaultNetwork . getAccountApiUrl ( address ) ; const response = await fetchPrivate ( url ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error fetching nonce. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } const responseText = await response . text ( ) ; const result = JSON . parse ( responseText ) as { nonce : string ; } ; return BigInt ( result . nonce ) ; } deprecated Use the new  estimateTransaction function insterad.
 *
 * Estimate the total transaction fee in microstacks for a token transfer
 *
 *  param { StacksTransaction } transaction param { StacksNetwork } network return export async function estimateTransfer ( transaction , network ? ) { if ( transaction . payload . payloadType !== PayloadType . TokenTransfer ) { throw new Error ( `Transaction fee estimation only possible with ${ PayloadType [ PayloadType . TokenTransfer ] } transactions. Invoked with: ${ PayloadType [ transaction . payload . payloadType ] }` ) ; } const requestHeaders = { Accept : 'application/text' , } ; const fetchOptions = { method : 'GET' , headers : requestHeaders , } ; const defaultNetwork = new StacksMainnet ( ) ; const url = network ? network . getTransferFeeEstimateApiUrl ( ) : defaultNetwork . getTransferFeeEstimateApiUrl ( ) ; const response = await fetchPrivate ( url , fetchOptions ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error estimating transaction fee. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } const feeRateResult = await response . text ( ) ; const txBytes = BigInt ( transaction . serialize ( ) . byteLength ) ; const feeRate = BigInt ( feeRateResult ) ; return feeRate * txBytes ; } interface FeeEstimation { fee : number ; fee_rate : number ; } interface FeeEstimateResponse { cost_scalar_change_by_byte : bigint ; estimated_cost : { read_count : bigint ; read_length : bigint ; runtime : bigint ; write_count : bigint ; write_length : bigint ; } ; estimated_cost_scalar : bigint ; estimations : [ FeeEstimation , FeeEstimation , FeeEstimation ] ; } param { StacksTransaction } transaction param { number } estimatedLen param { StacksNetwork } network return export async function estimateTransaction ( transactionPayload , estimatedLen ? , network ? ) { const options = { method : 'POST' , headers : { 'Content-Type' : 'application/json' } , body : JSON . stringify ( { transaction_payload : serializePayload ( transactionPayload ) . toString ( 'hex' ) , ... ( estimatedLen ? { estimated_len : estimatedLen } : { } ) , } ) , } ; const defaultNetwork = new StacksMainnet ( ) ; const url = network ? network . getTransactionFeeEstimateApiUrl ( ) : defaultNetwork . getTransactionFeeEstimateApiUrl ( ) ; const response = await fetchPrivate ( url , options ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error estimating transaction fee. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } const data = await response . json ( ) ; return data . estimations ; } export type SerializationRejection = { error : string ; reason : TxRejectedReason . Serialization ; reason_data : { message : string ; } ; txid : string ; } ; export type DeserializationRejection = { error : string ; reason : TxRejectedReason . Deserialization ; reason_data : { message : string ; } ; txid : string ; } ; export type SignatureValidationRejection = { error : string ; reason : TxRejectedReason . SignatureValidation ; reason_data : { message : string ; } ; txid : string ; } ; export type BadNonceRejection = { error : string ; reason : TxRejectedReason . BadNonce ; reason_data : { expected : number ; actual : number ; is_origin : boolean ; principal : boolean ; } ; txid : string ; } ; export type FeeTooLowRejection = { error : string ; reason : TxRejectedReason . FeeTooLow ; reason_data : { expected : number ; actual : number ; } ; txid : string ; } ; export type NotEnoughFundsRejection = { error : string ; reason : TxRejectedReason . NotEnoughFunds ; reason_data : { expected : string ; actual : string ; } ; txid : string ; } ; export type NoSuchContractRejection = { error : string ; reason : TxRejectedReason . NoSuchContract ; reason_data ? : undefined ; txid : string ; } ; export type NoSuchPublicFunctionRejection = { error : string ; reason : TxRejectedReason . NoSuchPublicFunction ; reason_data ? : undefined ; txid : string ; } ; export type BadFunctionArgumentRejection = { error : string ; reason : TxRejectedReason . BadFunctionArgument ; reason_data : { message : string ; } ; txid : string ; } ; export type ContractAlreadyExistsRejection = { error : string ; reason : TxRejectedReason . ContractAlreadyExists ; reason_data : { contract_identifier : string ; } ; txid : string ; } ; export type PoisonMicroblocksDoNotConflictRejection = { error : string ; reason : TxRejectedReason . PoisonMicroblocksDoNotConflict ; reason_data ? : undefined ; txid : string ; } ; export type PoisonMicroblockHasUnknownPubKeyHashRejection = { error : string ; reason : TxRejectedReason . PoisonMicroblockHasUnknownPubKeyHash ; reason_data ? : undefined ; txid : string ; } ; export type PoisonMicroblockIsInvalidRejection = { error : string ; reason : TxRejectedReason . PoisonMicroblockIsInvalid ; reason_data ? : undefined ; txid : string ; } ; export type BadAddressVersionByteRejection = { error : string ; reason : TxRejectedReason . BadAddressVersionByte ; reason_data ? : undefined ; txid : string ; } ; export type NoCoinbaseViaMempoolRejection = { error : string ; reason : TxRejectedReason . NoCoinbaseViaMempool ; reason_data ? : undefined ; txid : string ; } ; export type ServerFailureNoSuchChainTipRejection = { error : string ; reason : TxRejectedReason . ServerFailureNoSuchChainTip ; reason_data ? : undefined ; txid : string ; } ; export type ServerFailureDatabaseRejection = { error : string ; reason : TxRejectedReason . ServerFailureDatabase ; reason_data : { message : string ; } ; txid : string ; } ; export type ServerFailureOtherRejection = { error : string ; reason : TxRejectedReason . ServerFailureOther ; reason_data : { message : string ; } ; txid : string ; } ; export type TxBroadcastResultOk = { txid : string ; error ? : undefined ; reason ? : undefined ; reason_data ? : undefined ; } ; export type TxBroadcastResultRejected = SerializationRejection | DeserializationRejection | SignatureValidationRejection | BadNonceRejection | FeeTooLowRejection | NotEnoughFundsRejection | NoSuchContractRejection | NoSuchPublicFunctionRejection | BadFunctionArgumentRejection | ContractAlreadyExistsRejection | PoisonMicroblocksDoNotConflictRejection | PoisonMicroblockHasUnknownPubKeyHashRejection | PoisonMicroblockIsInvalidRejection | BadAddressVersionByteRejection | NoCoinbaseViaMempoolRejection | ServerFailureNoSuchChainTipRejection | ServerFailureDatabaseRejection | ServerFailureOtherRejection ; export type TxBroadcastResult = TxBroadcastResultOk | TxBroadcastResultRejected ; param { StacksTransaction } transaction param { StacksNetwork } network returns { Promise } export async function broadcastTransaction ( transaction , network , attachment ? ) { const rawTx = transaction . serialize ( ) ; const url = network . getBroadcastApiUrl ( ) ; return broadcastRawTransaction ( rawTx , url , attachment ) ; } param { Buffer } rawTx param { string } url returns { Promise } export async function broadcastRawTransaction ( rawTx , url , attachment ? ) { const options = { method : 'POST' , headers : { 'Content-Type' : attachment ? 'application/json' : 'application/octet-stream' } , body : attachment ? JSON . stringify ( { tx : rawTx . toString ( 'hex' ) , attachment : attachment . toString ( 'hex' ) , } ) : rawTx , } ; const response = await fetchPrivate ( url , options ) ; if ( ! response . ok ) { try { return ( await response . json ( ) ) as TxBroadcastResult ; } catch ( e ) { throw Error ( `Failed to broadcast transaction: ${ ( e as Error ) . message }` ) ; } } const text = await response . text ( ) ; const txid = text . replace ( /["]+/g , '' ) ; const isValidTxId = validateTxId ( txid ) ; if ( isValidTxId ) { return { txid : txid , } as TxBroadcastResult ; } else { throw new Error ( text ) ; } } param { string } address param { string } contractName param { StacksNetwork } network returns { Promise } export async function getAbi ( address , contractName , network ) { const options = { method : 'GET' , } ; const url = network . getAbiApiUrl ( address , contractName ) ; const response = await fetchPrivate ( url , options ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error fetching contract ABI for contract "${ contractName }" at address ${ address }. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } return JSON . parse ( await response . text ( ) ) as ClarityAbi ; } export interface MultiSigOptions { numSignatures : number ; publicKeys : string [ ] ; signerKeys ? : string [ ] ; } /**
 * STX token transfer transaction options
 */ export interface TokenTransferOptions { /** the address of the recipient of the token transfer */ recipient : string | PrincipalCV ; /** the amount to be transfered in microstacks */ amount : IntegerType ; /** the transaction fee in microstacks */ fee ? : IntegerType ; /** the transaction nonce, which must be increased monotonically with each new transaction */ nonce ? : IntegerType ; /** the network that the transaction will ultimately be broadcast to */ network ? : StacksNetwork ; /** the transaction anchorMode, which specifies whether it should be
     * included in an anchor block or a microblock */ anchorMode : AnchorMode ; /** an arbitrary string to include in the transaction, must be less than 34 bytes */ memo ? : string ; /** the post condition mode, specifying whether or not post-conditions must fully cover all
     * transfered assets */ postConditionMode ? : PostConditionMode ; /** a list of post conditions to add to the transaction */ postConditions ? : PostCondition [ ] ; /** set to true if another account is sponsoring the transaction (covering the transaction fee) */ sponsored ? : boolean ; } export interface UnsignedTokenTransferOptions extends TokenTransferOptions { publicKey : string ; } export interface SignedTokenTransferOptions extends TokenTransferOptions { senderKey : string ; } export interface UnsignedMultiSigTokenTransferOptions extends TokenTransferOptions { numSignatures : number ; publicKeys : string [ ] ; } export interface SignedMultiSigTokenTransferOptions extends TokenTransferOptions { numSignatures : number ; publicKeys : string [ ] ; signerKeys : string [ ] ; } param { UnsignedTokenTransferOptions | UnsignedMultiSigTokenTransferOptions } txOptions return { Promis < StacksTransaction > } export async function makeUnsignedSTXTokenTransfer ( txOptions ) { const defaultOptions = { fee : BigInt ( 0 ) , nonce : BigInt ( 0 ) , network : new StacksMainnet ( ) , postConditionMode : PostConditionMode . Deny , memo : '' , sponsored : false , } ; const options = Object . assign ( defaultOptions , txOptions ) ; const payload = createTokenTransferPayload ( options . recipient , options . amount , options . memo ) ; let authorization = null ; let spendingCondition = null ; if ( 'publicKey' in options ) { spendingCondition = createSingleSigSpendingCondition ( AddressHashMode . SerializeP2PKH , options . publicKey , options . nonce , options . fee ) ; } else { spendingCondition = createMultiSigSpendingCondition ( AddressHashMode . SerializeP2SH , options . numSignatures , options . publicKeys , options . nonce , options . fee ) ; } if ( options . sponsored ) { authorization = createSponsoredAuth ( spendingCondition ) ; } else { authorization = createStandardAuth ( spendingCondition ) ; } const postConditions = [ ] ; if ( options . postConditions && options . postConditions . length > 0 ) { options . postConditions . forEach ( postCondition => { postConditions . push ( postCondition ) ; } ) ; } const lpPostConditions = createLPList ( postConditions ) ; const transaction = new StacksTransaction ( options . network . version , authorization , payload , lpPostConditions , options . postConditionMode , options . anchorMode , options . network . chainId ) ; if ( txOptions . fee === undefined || txOptions . fee === null ) { const estimatedLen = transaction . serialize ( ) . byteLength ; const txFee = await estimateTransaction ( payload , estimatedLen , options . network ) ; transaction . setFee ( txFee [ 1 ] . fee ) ; } if ( txOptions . nonce === undefined || txOptions . nonce === null ) { const addressVersion = options . network . version === TransactionVersion . Mainnet ? AddressVersion . MainnetSingleSig : AddressVersion . TestnetSingleSig ; const senderAddress = c32address ( addressVersion , transaction . auth . spendingCondition ! . signer ) ; const txNonce = await getNonce ( senderAddress , options . network ) ; transaction . setNonce ( txNonce ) ; } return transaction ; } param { SignedTokenTransferOptions | SignedMultiSigTokenTransferOptions } txOptions return { StacksTransaction } export async function makeSTXTokenTransfer ( txOptions ) { if ( 'senderKey' in txOptions ) { const publicKey = publicKeyToString ( getPublicKey ( createStacksPrivateKey ( txOptions . senderKey ) ) ) ; const options = omit ( txOptions , 'senderKey' ) ; const transaction = await makeUnsignedSTXTokenTransfer ( { publicKey , ... options } ) ; const privKey = createStacksPrivateKey ( txOptions . senderKey ) ; const signer = new TransactionSigner ( transaction ) ; signer . signOrigin ( privKey ) ; return transaction ; } else { const options = omit ( txOptions , 'signerKeys' ) ; const transaction = await makeUnsignedSTXTokenTransfer ( options ) ; const signer = new TransactionSigner ( transaction ) ; let pubKeys = txOptions . publicKeys ; for ( const key of txOptions . signerKeys ) { const pubKey = pubKeyfromPrivKey ( key ) ; pubKeys = pubKeys . filter ( pk => pk !== pubKey . data . toString ( 'hex' ) ) ; signer . signOrigin ( createStacksPrivateKey ( key ) ) ; } for ( const key of pubKeys ) { signer . appendOrigin ( publicKeyFromBuffer ( Buffer . from ( key , 'hex' ) ) ) ; } return transaction ; } } /**
 * Contract deploy transaction options
 */ export interface BaseContractDeployOptions { contractName : string ; /** the Clarity code to be deployed */ codeBody : string ; /** transaction fee in microstacks */ fee ? : IntegerType ; /** the transaction nonce, which must be increased monotonically with each new transaction */ nonce ? : IntegerType ; /** the network that the transaction will ultimately be broadcast to */ network ? : StacksNetwork ; /** the transaction anchorMode, which specifies whether it should be
     * included in an anchor block or a microblock */ anchorMode : AnchorMode ; /** the post condition mode, specifying whether or not post-conditions must fully cover all
     * transfered assets */ postConditionMode ? : PostConditionMode ; /** a list of post conditions to add to the transaction */ postConditions ? : PostCondition [ ] ; /** set to true if another account is sponsoring the transaction (covering the transaction fee) */ sponsored ? : boolean ; } export interface ContractDeployOptions extends BaseContractDeployOptions { /** a hex string of the private key of the transaction sender */ senderKey : string ; } export interface UnsignedContractDeployOptions extends BaseContractDeployOptions { /** a hex string of the public key of the transaction sender */ publicKey : string ; } deprecated Use the new  estimateTransaction function insterad.
 *
 * Estimate the total transaction fee in microstacks for a contract deploy
 *
 *  param { StacksTransaction } transaction param { StacksNetwork } network return export async function estimateContractDeploy ( transaction , network ? ) { if ( transaction . payload . payloadType !== PayloadType . SmartContract ) { throw new Error ( `Contract deploy fee estimation only possible with ${ PayloadType [ PayloadType . SmartContract ] } transactions. Invoked with: ${ PayloadType [ transaction . payload . payloadType ] }` ) ; } const requestHeaders = { Accept : 'application/text' , } ; const fetchOptions = { method : 'GET' , headers : requestHeaders , } ; const defaultNetwork = new StacksMainnet ( ) ; const url = network ? network . getTransferFeeEstimateApiUrl ( ) : defaultNetwork . getTransferFeeEstimateApiUrl ( ) ; const response = await fetchPrivate ( url , fetchOptions ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error estimating contract deploy fee. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } const feeRateResult = await response . text ( ) ; const txBytes = intToBigInt ( transaction . serialize ( ) . byteLength , false ) ; const feeRate = intToBigInt ( feeRateResult , false ) ; return feeRate * txBytes ; } param { ContractDeployOptions } txOptions return { StacksTransaction } export async function makeContractDeploy ( txOptions ) { const privKey = createStacksPrivateKey ( txOptions . senderKey ) ; const stacksPublicKey = getPublicKey ( privKey ) ; const publicKey = publicKeyToString ( stacksPublicKey ) ; const unsignedTxOptions = { ... txOptions , publicKey } ; const transaction = await makeUnsignedContractDeploy ( unsignedTxOptions ) ; if ( txOptions . senderKey ) { const signer = new TransactionSigner ( transaction ) ; signer . signOrigin ( privKey ) ; } return transaction ; } export async function makeUnsignedContractDeploy ( txOptions ) { const defaultOptions = { fee : BigInt ( 0 ) , nonce : BigInt ( 0 ) , network : new StacksMainnet ( ) , postConditionMode : PostConditionMode . Deny , sponsored : false , } ; const options = Object . assign ( defaultOptions , txOptions ) ; const payload = createSmartContractPayload ( options . contractName , options . codeBody ) ; const addressHashMode = AddressHashMode . SerializeP2PKH ; const pubKey = createStacksPublicKey ( options . publicKey ) ; let authorization = null ; const spendingCondition = createSingleSigSpendingCondition ( addressHashMode , publicKeyToString ( pubKey ) , options . nonce , options . fee ) ; if ( options . sponsored ) { authorization = createSponsoredAuth ( spendingCondition ) ; } else { authorization = createStandardAuth ( spendingCondition ) ; } const postConditions = [ ] ; if ( options . postConditions && options . postConditions . length > 0 ) { options . postConditions . forEach ( postCondition => { postConditions . push ( postCondition ) ; } ) ; } const lpPostConditions = createLPList ( postConditions ) ; const transaction = new StacksTransaction ( options . network . version , authorization , payload , lpPostConditions , options . postConditionMode , options . anchorMode , options . network . chainId ) ; if ( txOptions . fee === undefined || txOptions . fee === null ) { const estimatedLen = transaction . serialize ( ) . byteLength ; const txFee = await estimateTransaction ( payload , estimatedLen , options . network ) ; transaction . setFee ( txFee [ 1 ] . fee ) ; } if ( txOptions . nonce === undefined || txOptions . nonce === null ) { const addressVersion = options . network . version === TransactionVersion . Mainnet ? AddressVersion . MainnetSingleSig : AddressVersion . TestnetSingleSig ; const senderAddress = publicKeyToAddress ( addressVersion , pubKey ) ; const txNonce = await getNonce ( senderAddress , options . network ) ; transaction . setNonce ( txNonce ) ; } return transaction ; } /**
 * Contract function call transaction options
 */ export interface ContractCallOptions { /** the Stacks address of the contract */ contractAddress : string ; contractName : string ; functionName : string ; functionArgs : ClarityValue [ ] ; /** transaction fee in microstacks */ fee ? : IntegerType ; feeEstimateApiUrl ? : string ; /** the transaction nonce, which must be increased monotonically with each new transaction */ nonce ? : IntegerType ; /** the Stacks blockchain network that will ultimately be used to broadcast this transaction */ network ? : StacksNetwork ; /** the transaction anchorMode, which specifies whether it should be
     * included in an anchor block or a microblock */ anchorMode : AnchorMode ; /** the post condition mode, specifying whether or not post-conditions must fully cover all
     * transfered assets */ postConditionMode ? : PostConditionMode ; /** a list of post conditions to add to the transaction */ postConditions ? : PostCondition [ ] ; /** set to true to validate that the supplied function args match those specified in
     * the published contract */ validateWithAbi ? : boolean | ClarityAbi ; /** set to true if another account is sponsoring the transaction (covering the transaction fee) */ sponsored ? : boolean ; } export interface UnsignedContractCallOptions extends ContractCallOptions { publicKey : string ; } export interface SignedContractCallOptions extends ContractCallOptions { senderKey : string ; } export interface UnsignedMultiSigContractCallOptions extends ContractCallOptions { numSignatures : number ; publicKeys : string [ ] ; } export interface SignedMultiSigContractCallOptions extends ContractCallOptions { numSignatures : number ; publicKeys : string [ ] ; signerKeys : string [ ] ; } deprecated Use the new  estimateTransaction function insterad.
 *
 * Estimate the total transaction fee in microstacks for a contract function call
 *
 *  param { StacksTransaction } transaction param { StacksNetwork } network return export async function estimateContractFunctionCall ( transaction , network ? ) { if ( transaction . payload . payloadType !== PayloadType . ContractCall ) { throw new Error ( `Contract call fee estimation only possible with ${ PayloadType [ PayloadType . ContractCall ] } transactions. Invoked with: ${ PayloadType [ transaction . payload . payloadType ] }` ) ; } const requestHeaders = { Accept : 'application/text' , } ; const fetchOptions = { method : 'GET' , headers : requestHeaders , } ; const defaultNetwork = new StacksMainnet ( ) ; const url = network ? network . getTransferFeeEstimateApiUrl ( ) : defaultNetwork . getTransferFeeEstimateApiUrl ( ) ; const response = await fetchPrivate ( url , fetchOptions ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error estimating contract call fee. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } const feeRateResult = await response . text ( ) ; const txBytes = intToBigInt ( transaction . serialize ( ) . byteLength , false ) ; const feeRate = intToBigInt ( feeRateResult , false ) ; return feeRate * txBytes ; } param { UnsignedContractCallOptions | UnsignedMultiSigContractCallOptions } txOptions returns { Promise < StacksTransaction > } export async function makeUnsignedContractCall ( txOptions ) { const defaultOptions = { fee : BigInt ( 0 ) , nonce : BigInt ( 0 ) , network : new StacksMainnet ( ) , postConditionMode : PostConditionMode . Deny , sponsored : false , } ; const options = Object . assign ( defaultOptions , txOptions ) ; const payload = createContractCallPayload ( options . contractAddress , options . contractName , options . functionName , options . functionArgs ) ; if ( options ?. validateWithAbi ) { let abi ; if ( typeof options . validateWithAbi === 'boolean' ) { if ( options ?. network ) { abi = await getAbi ( options . contractAddress , options . contractName , options . network ) ; } else { throw new Error ( 'Network option must be provided in order to validate with ABI' ) ; } } else { abi = options . validateWithAbi ; } validateContractCall ( payload , abi ) ; } let spendingCondition = null ; let authorization = null ; if ( 'publicKey' in options ) { spendingCondition = createSingleSigSpendingCondition ( AddressHashMode . SerializeP2PKH , options . publicKey , options . nonce , options . fee ) ; } else { spendingCondition = createMultiSigSpendingCondition ( AddressHashMode . SerializeP2SH , options . numSignatures , options . publicKeys , options . nonce , options . fee ) ; } if ( options . sponsored ) { authorization = createSponsoredAuth ( spendingCondition ) ; } else { authorization = createStandardAuth ( spendingCondition ) ; } const postConditions = [ ] ; if ( options . postConditions && options . postConditions . length > 0 ) { options . postConditions . forEach ( postCondition => { postConditions . push ( postCondition ) ; } ) ; } const lpPostConditions = createLPList ( postConditions ) ; const transaction = new StacksTransaction ( options . network . version , authorization , payload , lpPostConditions , options . postConditionMode , options . anchorMode , options . network . chainId ) ; if ( txOptions . fee === undefined || txOptions . fee === null ) { const estimatedLen = transaction . serialize ( ) . byteLength ; const txFee = await estimateTransaction ( payload , estimatedLen , options . network ) ; transaction . setFee ( txFee [ 1 ] . fee ) ; } if ( txOptions . nonce === undefined || txOptions . nonce === null ) { const addressVersion = options . network . version === TransactionVersion . Mainnet ? AddressVersion . MainnetSingleSig : AddressVersion . TestnetSingleSig ; const senderAddress = c32address ( addressVersion , transaction . auth . spendingCondition ! . signer ) ; const txNonce = await getNonce ( senderAddress , options . network ) ; transaction . setNonce ( txNonce ) ; } return transaction ; } param { SignedContractCallOptions | SignedMultiSigContractCallOptions } txOptions return { StacksTransaction } export async function makeContractCall ( txOptions ) { if ( 'senderKey' in txOptions ) { const publicKey = publicKeyToString ( getPublicKey ( createStacksPrivateKey ( txOptions . senderKey ) ) ) ; const options = omit ( txOptions , 'senderKey' ) ; const transaction = await makeUnsignedContractCall ( { publicKey , ... options } ) ; const privKey = createStacksPrivateKey ( txOptions . senderKey ) ; const signer = new TransactionSigner ( transaction ) ; signer . signOrigin ( privKey ) ; return transaction ; } else { const options = omit ( txOptions , 'signerKeys' ) ; const transaction = await makeUnsignedContractCall ( options ) ; const signer = new TransactionSigner ( transaction ) ; let pubKeys = txOptions . publicKeys ; for ( const key of txOptions . signerKeys ) { const pubKey = pubKeyfromPrivKey ( key ) ; pubKeys = pubKeys . filter ( pk => pk !== pubKey . data . toString ( 'hex' ) ) ; signer . signOrigin ( createStacksPrivateKey ( key ) ) ; } for ( const key of pubKeys ) { signer . appendOrigin ( publicKeyFromBuffer ( Buffer . from ( key , 'hex' ) ) ) ; } return transaction ; } } param address param conditionCode param amount export function makeStandardSTXPostCondition ( address , conditionCode , amount ) { return createSTXPostCondition ( createStandardPrincipal ( address ) , conditionCode , amount ) ; } param address param contractName param conditionCode param amount return { STXPostCondition } export function makeContractSTXPostCondition ( address , contractName , conditionCode , amount ) { return createSTXPostCondition ( createContractPrincipal ( address , contractName ) , conditionCode , amount ) ; } param address param conditionCode param amount param assetInfo export function makeStandardFungiblePostCondition ( address , conditionCode , amount , assetInfo ) { return createFungiblePostCondition ( createStandardPrincipal ( address ) , conditionCode , amount , assetInfo ) ; } param address param contractName param conditionCode param amount param assetInfo export function makeContractFungiblePostCondition ( address , contractName , conditionCode , amount , assetInfo ) { return createFungiblePostCondition ( createContractPrincipal ( address , contractName ) , conditionCode , amount , assetInfo ) ; } param { String } address param { FungibleConditionCode } conditionCode param { AssetInfo } assetInfo param { ClarityValue } assetName return { NonFungiblePostCondition } export function makeStandardNonFungiblePostCondition ( address , conditionCode , assetInfo , assetName ) { return createNonFungiblePostCondition ( createStandardPrincipal ( address ) , conditionCode , assetInfo , assetName ) ; } param { String } address param { String } contractName param { FungibleConditionCode } conditionCode param { AssetInfo } assetInfo param { ClarityValue } assetName return { NonFungiblePostCondition } export function makeContractNonFungiblePostCondition ( address , contractName , conditionCode , assetInfo , assetName ) { return createNonFungiblePostCondition ( createContractPrincipal ( address , contractName ) , conditionCode , assetInfo , assetName ) ; } param { String } contractAddress param { String } contractName param { String } functionName param { [ ClarityValue ] } functionArgs param { StacksNetwork } network param { String } senderAddress export interface ReadOnlyFunctionOptions { contractName : string ; contractAddress : string ; functionName : string ; functionArgs : ClarityValue [ ] ; /** the network that the contract which contains the function is deployed to */ network ? : StacksNetwork ; /** address of the sender */ senderAddress : string ; } param { ReadOnlyFunctionOptions } readOnlyFunctionOptions return { ClarityValue } export async function callReadOnlyFunction ( readOnlyFunctionOptions ) { const defaultOptions = { network : new StacksMainnet ( ) , } ; const options = Object . assign ( defaultOptions , readOnlyFunctionOptions ) ; const { contractName , contractAddress , functionName , functionArgs , network , senderAddress } = options ; const url = network . getReadOnlyFunctionCallApiUrl ( contractAddress , contractName , functionName ) ; const args = functionArgs . map ( arg => cvToHex ( arg ) ) ; const body = JSON . stringify ( { sender : senderAddress , arguments : args , } ) ; const response = await fetchPrivate ( url , { method : 'POST' , body , headers : { 'Content-Type' : 'application/json' , } , } ) ; if ( ! response . ok ) { let msg = '' ; try { msg = await response . text ( ) ; } catch ( error ) { } throw new Error ( `Error calling read-only function. Response ${ response . status }: ${ response . statusText }. Attempted to fetch ${ url } and failed with the message: "${ msg }"` ) ; } return response . json ( ) . then ( responseJson => parseReadOnlyResponse ( responseJson ) ) ; } /**
 * Sponsored transaction options
 */ export interface SponsorOptionsOpts { /** the origin-signed transaction */ transaction : StacksTransaction ; /** the sponsor's private key */ sponsorPrivateKey : string ; /** the transaction fee amount to sponsor */ fee ? : IntegerType ; /** the nonce of the sponsor account */ sponsorNonce ? : IntegerType ; /** the hashmode of the sponsor's address */ sponsorAddressHashmode ? : AddressHashMode ; /** the Stacks blockchain network that this transaction will ultimately be broadcast to */ network ? : StacksNetwork ; } param { SponsorOptionsOpts } sponsorOptions return { ClarityValue } export async function sponsorTransaction ( sponsorOptions ) { const defaultOptions = { fee : 0 as IntegerType , sponsorNonce : 0 as IntegerType , sponsorAddressHashmode : AddressHashMode . SerializeP2PKH as SingleSigHashMode , } ; const options = Object . assign ( defaultOptions , sponsorOptions ) ; const network = sponsorOptions . network ?? ( options . transaction . version === TransactionVersion . Mainnet ? new StacksMainnet ( ) : new StacksTestnet ( ) ) ; const sponsorPubKey = pubKeyfromPrivKey ( options . sponsorPrivateKey ) ; if ( sponsorOptions . fee === undefined || sponsorOptions . fee === null ) { let txFee = 0 ; switch ( options . transaction . payload . payloadType ) { case PayloadType . TokenTransfer : case PayloadType . SmartContract : case PayloadType . ContractCall : const estimatedLen = options . transaction . serialize ( ) . byteLength ; try { txFee = ( await estimateTransaction ( options . transaction . payload , estimatedLen , network ) ) [ 1 ] . fee ; } catch ( e ) { throw e ; } break ; default : throw new Error ( `Sponsored transactions not supported for transaction type ${ PayloadType [ options . transaction . payload . payloadType ] }` ) ; } options . transaction . setFee ( txFee ) ; options . fee = txFee ; } if ( sponsorOptions . sponsorNonce === undefined || sponsorOptions . sponsorNonce === null ) { const addressVersion = network . version === TransactionVersion . Mainnet ? AddressVersion . MainnetSingleSig : AddressVersion . TestnetSingleSig ; const senderAddress = publicKeyToAddress ( addressVersion , sponsorPubKey ) ; const sponsorNonce = await getNonce ( senderAddress , network ) ; options . sponsorNonce = sponsorNonce ; } const sponsorSpendingCondition = createSingleSigSpendingCondition ( options . sponsorAddressHashmode , publicKeyToString ( sponsorPubKey ) , options . sponsorNonce , options . fee ) ; options . transaction . setSponsor ( sponsorSpendingCondition ) ; const privKey = createStacksPrivateKey ( options . sponsorPrivateKey ) ; const signer = TransactionSigner . createSponsorSigner ( options . transaction , sponsorSpendingCondition ) ; signer . signSponsor ( privKey ) ; return signer . transaction ; }