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 | 3;       // 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,
}

Live Example

Live Example

Turing.signAssociatedTransaction()

Unknown
Use the wallet control in the top navigation before running this example.

Includes sample data for preview. Clear it to use your own transaction data.

Code Preview
const params = {
  "sourceTxraw": "0a0000000111111111111111111111111111111111111111111111111111111111111111110000000000ffffffff02c0d40100000000001976a9141cfef3571aad5bf16174e9d39928ad1a5716769388ac08380100000000001976a914a3c6b1ee4a49d9f2af3b3802974744fba924164a88ac00000000",
  "sourceUtxos": [
    {
      "txId": "1111111111111111111111111111111111111111111111111111111111111111",
      "outputIndex": 0,
      "satoshis": 200000,
      "script": "76a914a3c6b1ee4a49d9f2af3b3802974744fba924164a88ac",
      "scriptSigType": "p2pkh"
    }
  ],
  "inputs": [],
  "outputs": []
};

const result = await Turing.signAssociatedTransaction(params);
console.log(result);
Make sure the browser extension is enabled, or open this page inside Turing Wallet on mobile.