buildTransaction
Construct the unsigned binary header for a Qubic transaction.
buildTransaction serializes a transaction header into 80 bytes (plus optional payload). The result is unsigned — pass it to signTransaction next.
buildTransaction(params)
import { buildTransaction } from "@qubic.org/tx"
import { publicKeyFromSeed } from "@qubic.org/crypto"
import { toSeed } from "@qubic.org/types"
const seed = toSeed("...")
const sourcePublicKey = publicKeyFromSeed(seed)
const destinationPublicKey = new Uint8Array(32) // zero = contract calls
const unsigned = buildTransaction({
sourcePublicKey,
destinationPublicKey,
amount: 1_000_000n,
targetTick: currentTick + 5,
inputType: 0, // 0 = plain transfer
inputSize: 0, // no payload
})
// unsigned is Uint8Array (80 bytes for a plain transfer)Parameters
| Name | Type | Description |
|---|---|---|
sourcePublicKey | Uint8Array | 32-byte sender public key |
destinationPublicKey | Uint8Array | 32-byte recipient public key |
amount | bigint | Transfer amount in QU |
targetTick | number | Tick by which the node must process the transaction |
inputType | number | 0 for transfers; procedure index for contract calls |
inputSize | number | Payload byte length (0 for plain transfers) |
payload | Uint8Array | undefined | Optional payload bytes for contract calls |
Returns Uint8Array — 80-byte header (+ inputSize payload bytes).
Target tick
targetTick is a deadline, not a schedule. The network rejects the transaction if the current tick has already passed targetTick when the node processes it. If targetTick is in the future, the node will process the transaction when it reaches that tick — or drop it after a grace period.
const { tick } = await live.getTickInfo()
const targetTick = tick + 5 // deadline: process within the next 5 ticksSetting targetTick too low (e.g. tick + 1) risks rejection if the network is even slightly ahead of your clock. Setting it higher (e.g. tick + 20) gives more leeway but means the transaction sits pending longer before expiring if something goes wrong. The PROTOCOL.TICKS_TO_EXPIRY constant from @qubic.org/types defaults to 5 — a reasonable default for most conditions.
Header field layout
| Field | Offset | Size | Description |
|---|---|---|---|
sourcePublicKey | 0 | 32 B | Sender FourQ public key |
destinationPublicKey | 32 | 32 B | Recipient FourQ public key |
amount | 64 | 8 B (LE) | QU amount as little-endian int64 |
targetTick | 72 | 4 B (LE) | Target tick as little-endian uint32 |
inputType | 76 | 2 B (LE) | Procedure index |
inputSize | 78 | 2 B (LE) | Payload byte length |
Plain transfer vs contract call
For a plain transfer (identity to identity):
destinationPublicKey= recipient's public key (fromidentityToPublicKey)inputType=0inputSize=0, nopayload
For a contract call (SC transaction):
destinationPublicKey= 32 zero bytes (the contract's canonical address)inputType= the procedure's input type constantinputSize=payload.lengthpayload= encoded procedure input from abuild*Inputfunction