@qubic.org/tx
Binary transaction builder, signer, verifier, and payload codec for Qubic transactions.
Introduction
Transaction lifecycle
A Qubic transaction goes through four steps before it can be broadcast:
Build — buildTransaction assembles the binary header from source key, destination, amount, tick, and input type.
Sign — signTransaction computes a K12 digest of the header and signs it with the source seed via SchnorrQ.
Encode — encodeTransaction converts the signed binary to a base64 string for the HTTP broadcast endpoint.
Broadcast — pass the base64 string to live.broadcastTransaction from @qubic.org/rpc.
Smart contract payloads
For smart contract calls, you attach a binary payload to the transaction. buildPayload and readField in this package let you construct and inspect those payloads by field — without needing the full ABI registry. For ABI-driven encoding, use @qubic.org/registry or the generated wrappers in @qubic.org/contracts.
vs @qubic.org/wallet
@qubic.org/wallet wraps buildTransaction + signTransaction + encodeTransaction into a single wallet.buildTransfer call. Use @qubic.org/tx directly when you need fine-grained control over the binary format or are building tooling outside the wallet abstraction.
Installation
bun add @qubic.org/txnpm install @qubic.org/txpnpm add @qubic.org/txAPI reference
| Page | What's covered |
|---|---|
| Build transaction | buildTransaction — assemble the binary transaction header |
| Sign transaction | signTransaction, encodeTransaction, hashTransaction, verifyTransaction |
| Payload | buildPayload, readField, PayloadField — structured contract input encoding |
All exports
import {
// Core transaction lifecycle
buildTransaction,
signTransaction,
encodeTransaction,
// Utilities
hashTransaction,
verifyTransaction,
// Payload codec
buildPayload,
readField,
type PayloadField,
} from "@qubic.org/tx"Examples
Simple QU transfer
import { buildTransaction, signTransaction, encodeTransaction } from "@qubic.org/tx"
import { publicKeyFromSeed, identityToPublicKey } from "@qubic.org/crypto"
import { createLiveClient } from "@qubic.org/rpc"
import { toSeed, toIdentity } from "@qubic.org/types"
const live = createLiveClient()
const { tick } = await live.getTickInfo()
const seed = toSeed("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
const sourcePublicKey = publicKeyFromSeed(seed)
const destinationPublicKey = identityToPublicKey(
toIdentity("CFBMEMZOIDEXQAUXYYSZIURADQLAPWPMNJXQSNVQZAHYVOPYUKKJBJUCTVJL")
)
const unsigned = buildTransaction({
sourcePublicKey,
destinationPublicKey,
amount: 1_000_000n,
targetTick: tick + 5,
inputType: 0,
})
const signed = await signTransaction(unsigned, seed)
const encoded = encodeTransaction(signed)
const result = await live.broadcastTransaction(encoded)
console.log(`Broadcast to ${result.peersBroadcastedTo} peers`)Smart contract call with payload
import { buildTransaction, signTransaction, encodeTransaction, buildPayload } from "@qubic.org/tx"
import { publicKeyFromSeed, identityToPublicKey } from "@qubic.org/crypto"
import { toSeed, toIdentity } from "@qubic.org/types"
const seed = toSeed("aaaa...")
const sourcePublicKey = publicKeyFromSeed(seed)
// Zero-address destination for SC calls
const destinationPublicKey = new Uint8Array(32)
// Build a simple payload manually (use @qubic.org/contracts for ABI-typed encoding)
const payload = buildPayload([
{ name: "amount", type: "uint64" },
], { amount: 10_000_000n })
const unsigned = buildTransaction({
sourcePublicKey,
destinationPublicKey,
amount: 10_000_000n,
targetTick: tick + 5,
inputType: 6, // Qearn LOCK_INPUT_TYPE
inputSize: payload.length,
payload,
})
const signed = await signTransaction(unsigned, seed)
const encoded = encodeTransaction(signed)Verify a transaction you received
import { hashTransaction, verifyTransaction } from "@qubic.org/tx"
const hash = hashTransaction(signedTxBytes)
const valid = await verifyTransaction(signedTxBytes)
console.log("Hash:", Buffer.from(hash).toString("hex"))
console.log("Signature valid:", valid)