Skip to content

signAssociatedTransaction

Sign parent-child (associated) transactions using the wallet. The wallet constructs child transactions from a source transaction and signs them all together.

Usage

ts
const { txraws } = await Turing.signAssociatedTransaction({
  sourceTxraw,
  sourceUtxos,
  inputs,
  outputs,
});

Parameters

ts
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
}
ParameterTypeRequiredDescription
sourceTxrawstringYesSource transaction raw hex string
sourceUtxosInput[]YesArray of UTXOs from the source transaction
inputsInput[][]No2D array — each sub-array represents the inputs of a child transaction
outputsOutput[][]No2D array — each sub-array represents the outputs of a child transaction

Returns

ts
interface SignAssociatedTransactionResponse {
  txraws: string[];  // Assembled transaction hex strings ready for broadcast
}
FieldTypeDescription
txrawsstring[]Signed parent-child transactions ready for broadcast

Error Handling

ts
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:

ts
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 requires contractTxId and ftVersion)

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:

  1. Set the sequence of every stablecoin input to 0xFFFFFFFE.
  2. Set the transaction's nLockTime to the maximum lockTime value found in the tape of all spent stablecoin UTXOs.

Reference implementation:

ts
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 sourceUtxos must 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:

ts
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:

ts
{
  outputIndex: 0,
  scriptSigType: "tbc20_coin_contract",
  contractTxId: "<contract transaction ID>",
  ftVersion: 2,
}