signAssociatedTransaction
Sign parent-child (associated) transactions using the wallet. The wallet constructs child transactions from a source transaction and signs them all together.
Usage
const { txraws } = await Turing.signAssociatedTransaction({
sourceTxraw,
sourceUtxos,
inputs,
outputs,
});Parameters
interface Input {
txId?: string; // Transaction ID (required for source transaction inputs)
script?: string; // Locking script, hex format only
satoshis?: number; // Satoshi value
outputIndex: number; // Output index
scriptSigType:
| "p2pkh"
| "tbc20" // Standard FT transfer unlock
| "tbc20_contract" // Standard FT unlock in contract / swap scenarios
| "tbc20_coin" // Stablecoin transfer unlock (FT.getFTunlock + isCoin)
| "tbc20_coin_contract" // Stablecoin unlock in contract / swap scenarios (FT.getFTunlockSwap + isCoin)
| "other"; // Custom script signature type
unfinishedScriptSig?: string; // For "other" type: custom script template (hex format), with the signature portion replaced by 097369676e6174757265
ftVersion?: 1 | 2; // FT version for "tbc20_contract" / "tbc20_coin_contract" types
contractTxId?: string; // Contract transaction ID for "tbc20_contract" / "tbc20_coin_contract" types
}
interface Output {
script: string; // Output locking script, hex format only
satoshis: number; // Output satoshi value
}
interface SignAssociatedTransactionRequestData {
sourceTxraw: string; // The source (parent) transaction raw hex
sourceUtxos: Input[]; // UTXOs from the source transaction
inputs?: Input[][]; // 2D array of child transaction inputs
outputs?: Output[][]; // 2D array of child transaction outputs
}| Parameter | Type | Required | Description |
|---|---|---|---|
sourceTxraw | string | Yes | Source transaction raw hex string |
sourceUtxos | Input[] | Yes | Array of UTXOs from the source transaction |
inputs | Input[][] | No | 2D array — each sub-array represents the inputs of a child transaction |
outputs | Output[][] | No | 2D array — each sub-array represents the outputs of a child transaction |
Returns
interface SignAssociatedTransactionResponse {
txraws: string[]; // Assembled transaction hex strings ready for broadcast
}| Field | Type | Description |
|---|---|---|
txraws | string[] | Signed parent-child transactions ready for broadcast |
Error Handling
try {
const { txraws } = await Turing.signAssociatedTransaction({
sourceTxraw,
sourceUtxos,
inputs,
outputs,
});
console.log("Signed transactions:", txraws);
} catch (error) {
console.error("Signing failed:", error);
}Example
FT transfer example with two child transactions:
const sourceUtxos: Input[] = [
{
txId: "",
outputIndex: 0,
satoshis: 500,
script: ftcode,
scriptSigType: "tbc20",
},
{
txId: "",
outputIndex: 2,
satoshis: 10000,
script: p2pkh,
scriptSigType: "p2pkh",
},
];
const inputs: Input[][] = [
[
{ outputIndex: 0, scriptSigType: "tbc20" },
{ outputIndex: 2, scriptSigType: "p2pkh" },
],
[
{ outputIndex: 0, scriptSigType: "tbc20" },
{ outputIndex: 2, scriptSigType: "p2pkh" },
],
];
const outputs: Output[][] = [
[
{
script: ftcode,
satoshis: 500,
},
{
script: fttape,
satoshis: 0,
},
{
script: p2pkh,
satoshis: 8000,
},
],
[
{
script: ftcode,
satoshis: 500,
},
{
script: fttape,
satoshis: 0,
},
{
script: p2pkh,
satoshis: 6000,
},
],
];
const { txraws } = await Turing.signAssociatedTransaction({
sourceTxraw,
sourceUtxos,
inputs,
outputs,
});Stablecoins (tbc20_coin / tbc20_coin_contract)
Stablecoins are a special kind of FT whose unlocking scripts differ from standard FT, so dedicated scriptSigType values are provided:
"tbc20_coin": Stablecoin standard transfer unlock"tbc20_coin_contract": Stablecoin unlock for contract / swap scenarios (also requirescontractTxIdandftVersion)
Child transactions (inputs / outputs)
Just mark the corresponding input's scriptSigType as "tbc20_coin" or "tbc20_coin_contract". All other fields are written exactly the same way as standard FT — you do not need to worry about sequence / nLockTime.
Source transaction (sourceTxraw)
sourceTxraw is a raw transaction the caller assembles themselves. If it contains stablecoin inputs, the caller must satisfy the following two conditions when building it:
- Set the
sequenceof every stablecoin input to0xFFFFFFFE. - Set the transaction's
nLockTimeto the maximumlockTimevalue found in the tape of all spent stablecoin UTXOs.
Reference implementation:
import { Transaction } from "tbc-lib-js";
import { stableCoin } from "tbc-contract";
const tx = new Transaction().from(coinUtxos).from(payUtxo);
// ...addOutput(...)
for (let i = 0; i < coinUtxos.length; i++) {
tx.setInputSequence(i, 0xFFFFFFFE);
}
let lockTimeMax = 0;
for (let i = 0; i < coinUtxos.length; i++) {
const lt = stableCoin.getLockTimeFromTape(
preTXs[i].outputs[coinUtxos[i].outputIndex + 1].script
);
lockTimeMax = Math.max(lockTimeMax, lt);
}
tx.setLockTime(lockTimeMax);
const sourceTxraw = tx.uncheckedSerialize();The corresponding entries in
sourceUtxosmust still be marked as"tbc20_coin"or"tbc20_coin_contract".
Stablecoin example
The parent transaction spends 1 stablecoin UTXO + 1 P2PKH UTXO and produces a new stablecoin UTXO (output 0/1 are code/tape, output 2 is the P2PKH change). The child transaction then spends that newly created stablecoin UTXO:
const sourceUtxos: Input[] = [
{
txId: coinUtxo.txId,
outputIndex: coinUtxo.outputIndex,
satoshis: 500,
script: coinCodeHex,
scriptSigType: "tbc20_coin",
},
{
txId: payUtxo.txId,
outputIndex: payUtxo.outputIndex,
satoshis: 10000,
script: p2pkhHex,
scriptSigType: "p2pkh",
},
];
const inputs: Input[][] = [
[
{ outputIndex: 0, scriptSigType: "tbc20_coin" },
{ outputIndex: 2, scriptSigType: "p2pkh" },
],
];
const outputs: Output[][] = [
[
{ script: newCoinCodeHex, satoshis: 500 },
{ script: newCoinTapeHex, satoshis: 0 },
{ script: p2pkhChangeHex, satoshis: 8000 },
],
];
const { txraws } = await Turing.signAssociatedTransaction({
sourceTxraw,
sourceUtxos,
inputs,
outputs,
});If the stablecoin needs to take the contract / swap path, change scriptSigType to "tbc20_coin_contract" and supply contractTxId and ftVersion:
{
outputIndex: 0,
scriptSigType: "tbc20_coin_contract",
contractTxId: "<contract transaction ID>",
ftVersion: 2,
}