Construct, decode transactions and work with Clarity smart contracts on the Stacks blockchain.
The Stacks authentication process enables secure user sign-in for web apps by generating and handling encrypted authentication requests. It involves setting up an app domain, configuring permissions, and creating a UserSession to manage user data.
import { makeSTXTokenTransfer, broadcastTransaction, AnchorMode } from '@stacks/transactions';const txOptions = { recipient: 'SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159', amount: 12345n, senderKey: 'b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01', network: 'testnet', // for mainnet, use 'mainnet' memo: 'test memo', nonce: 0n, // set a nonce manually if you don't want builder to fetch from a Stacks node fee: 200n, // set a tx fee if you don't want the builder to estimate anchorMode: AnchorMode.Any,};const transaction = await makeSTXTokenTransfer(txOptions);// to see the raw serialized txconst serializedTx = transaction.serialize(); // Uint8Arrayconst serializedTxHex = bytesToHex(serializedTx); // hex string// broadcasting transaction to the specified networkconst broadcastResponse = await broadcastTransaction(transaction);const txId = broadcastResponse.txid;
import { makeContractCall, broadcastTransaction, AnchorMode, FungibleConditionCode, makeStandardSTXPostCondition, bufferCVFromString,} from '@stacks/transactions';import { StacksTestnet, StacksMainnet } from '@stacks/network';// for mainnet, use `StacksMainnet()`const network = new StacksTestnet();// Add an optional post condition// See below for details on constructing post conditionsconst postConditionAddress = 'SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE';const postConditionCode = FungibleConditionCode.GreaterEqual;const postConditionAmount = 1000000n;const postConditions = [ makeStandardSTXPostCondition(postConditionAddress, postConditionCode, postConditionAmount),];const txOptions = { contractAddress: 'SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X', contractName: 'contract_name', functionName: 'contract_function', functionArgs: [bufferCVFromString('foo')], senderKey: 'b244296d5907de9864c0b0d51f98a13c52890be0404e83f273144cd5b9960eed01', validateWithAbi: true, network, postConditions, anchorMode: AnchorMode.Any,};const transaction = await makeContractCall(txOptions);const broadcastResponse = await broadcastTransaction(transaction, network);const txId = broadcastResponse.txid;
In this example we construct a contract-call transaction with a post condition. We have set the validateWithAbi option to true, so the makeContractCall builder will attempt to fetch this contracts ABI from the specified Stacks network, and validate that the provided functionArgs match what is described in the ABI. This should help you avoid constructing invalid contract-call transactions. If you would prefer to provide your own ABI instead of fetching it from the network, the validateWithABI option also accepts ClarityABI objects, which can be constructed from ABI files like so:
import { ClarityAbi } from '@stacks/transactions';import { readFileSync } from 'fs';const abi: ClarityAbi = JSON.parse(readFileSync('abi.json').toString());// For sample abi json see: stacks.js/packages/transactions/tests/abi/test-abi.json
To generate a sponsored transaction, first create and sign the transaction as the origin. The sponsored property in the options object must be set to true.
To generate a multi-sig transaction, first create an unsigned transaction.
The numSignatures and publicKeys properties in the options object must be set:
import { makeUnsignedSTXTokenTransfer, createStacksPrivateKey, deserializeTransaction, pubKeyfromPrivKey, publicKeyToString, TransactionSigner, standardPrincipalCV, BytesReader, AnchorMode,} from '@stacks/transactions';const recipient = standardPrincipalCV('SP3FGQ8...');const amount = 2500000n;const fee = 0n;const memo = 'test memo';// private keys of the participants in the transactionconst privKeyStrings = ['6d430bb9...', '2a584d89...', 'd5200dee...'];// create private key objects from string arrayconst privKeys = privKeyStrings.map(createStacksPrivateKey);// corresponding public keysconst pubKeys = privKeyStrings.map(pubKeyfromPrivKey);// create public key string array from objectsconst pubKeyStrings = pubKeys.map(publicKeyToString);const transaction = await makeUnsignedSTXTokenTransfer({ recipient, amount, fee, memo, numSignatures: 2, // number of signature required publicKeys: pubKeyStrings, // public key string array with >= numSignatures elements anchorMode: AnchorMode.Any,});const serializedTx = transaction.serialize();
This transaction payload can be passed along to other participants to sign. In addition to
meeting the numSignatures requirement, the public keys of the parties who did not sign the
transaction must be appended to the signature.
// deserialize and sign transactionconst bytesReader = new BytesReader(serializedTx);// Partially signed or unsigned multi-sig tx can be deserialized to add the required signaturesconst deserializedTx = deserializeTransaction(bytesReader);const signer = new TransactionSigner(deserializedTx);// first signaturesigner.signOrigin(privKeys[0]);// second signaturesigner.signOrigin(privKeys[1]);// after meeting the numSignatures requirement, the public// keys of the participants who did not sign must be appendedsigner.appendOrigin(pubKeys[2]);// the serialized multi-sig txconst serializedSignedTx = deserializedTx.serialize();
Building transactions that call functions in deployed clarity contracts requires you to construct valid Clarity Values to pass to the function as arguments. The Clarity type system contains the following types:
a list of maximum length max-len, with entries of type entry-type
(response ok-type err-type)
object used by public functions to commit their changes or abort. May be returned or used by other functions as well, however, only public functions have the commit/abort behavior.
(optional some-type)
an option type for objects that can either be (some value) or none
(buff max-len)
byte buffer or maximum length max-len.
principal
object representing a principal (whether a contract principal or standard principal).
bool
boolean value ('true or 'false)
int
signed 128-bit integer
uint
unsigned 128-bit integer
This library contains Typescript types and classes that map to the Clarity types, in order to make it easy to construct well-typed Clarity values in Javascript. These types all extend the abstract class ClarityValue.
import { trueCV, falseCV, noneCV, someCV, intCV, uintCV, standardPrincipalCV, contractPrincipalCV, responseErrorCV, responseOkCV, listCV, tupleCV, bufferCV,} from '@stacks/transactions';import { utf8ToBytes } from '@stacks/common';// construct boolean clarity valuesconst t = trueCV();const f = falseCV();// construct optional clarity valuesconst nothing = noneCV();const something = someCV(t);// construct a buffer clarity value from an existing byte arrayconst bytes = utf8ToBytes('foo'); // Uint8Array(3) [ 102, 111, 111 ]const bufCV = bufferCV(bytes);// construct signed and unsigned integer clarity valuesconst i = intCV(-10);const u = uintCV(10);// construct principal clarity valuesconst address = 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B';const contractName = 'contract-name';const spCV = standardPrincipalCV(address);const cpCV = contractPrincipalCV(address, contractName);// construct response clarity valuesconst errCV = responseErrorCV(trueCV());const okCV = responseOkCV(falseCV());// construct tuple clarity valuesconst tupCV = tupleCV({ a: intCV(1), b: trueCV(), c: falseCV(),});// construct list clarity valuesconst l = listCV([trueCV(), falseCV()]);
If you develop in Typescript, the type checker can help prevent you from creating wrongly-typed Clarity values. For example, the following code won't compile since in Clarity lists are homogeneous, meaning they can only contain values of a single type. It is important to include the type variable BooleanCV in this example, otherwise the typescript type checker won't know which type the list is of and won't enforce homogeneity.
const l = listCV<BooleanCV>([trueCV(), intCV(1)]);
Warning
The Stacks blockchain's post-condition processor can NOT check ownership.
It checks whether or not a principal will send or will not send an NFT.
Post-conditions can NOT verify anything about the recipient of an asset.
If you want to verify conditions about asset recipients, you will need to use Clarity.