mintBlue
GuidesTransactions

Combine outputs

Carry several outputs, of the same or different types, in one transaction, and read them back without relying on their position.

outputs is an array, and nothing in it has to match anything else in it. One transaction can therefore carry the invoice file and the invoice number that belongs to it, submitted together, returned under one transaction id.

That is the reason to combine rather than to submit twice: two transactions are two records that some later reader has to correlate. One transaction is one record with two parts.

Build the array

const fs = require('node:fs');

const outputs = [
  {
    type: 'file',
    value: {
      fileName: 'invoice.pdf',
      contentType: 'application/pdf',
      content: fs.readFileSync('invoice.pdf'),
    },
    sign: true,
    encrypt: true,
  },
  {
    type: 'data',
    value: {
      order: 'order#1234',
      customer: 'john@doe.com',
    },
    sign: true,
    encrypt: true,
  },
];

Two of the same type is allowed as well, which is how you keep one part encrypted and another readable by anyone:

const outputs = [
  {
    type: 'data',
    value: { order: 'order#1234', customer: 'john@doe.com' },
    sign: true,
    encrypt: true,
  },
  {
    type: 'data',
    value: { status: 'approved' },
    sign: true,
    encrypt: false,
  },
];

Each output carries its own sign and encrypt decision, so combining outputs is also how one record holds a private part and a public part.

Submit it

One call, one transaction, one id covering everything in the array.

const { txid } = await client.createTransaction({
  project_id: process.env.MINTBLUE_PROJECT_ID,
  outputs,
});

Check it worked

Read the transaction back and pick the outputs out by type, not by index.

const transaction = await client.getTransaction({ txid, parse: true });

const file = transaction.outputs.find((output) => output.type === 'file');
const records = transaction.outputs.filter((output) => output.type === 'data');

console.log(file.value.fileName, records.length);

Two habits are worth forming here, and both come from the same fact: the array you read back is not guaranteed to be the array you submitted.

  • Match on type. Index 0 is stable right up until somebody adds an output above it.
  • Do not assume the count. Filter for what you need and ignore the rest.

If your two data outputs have to be told apart, put a discriminator inside the value, for example a kind field, and select on that. The transaction does not label them for you.

Next

On this page