How To Propose A Multisig Transaction

To propose a transaction, submit a transaction to the propose action of the eosio.msig account.

Serializing Actions

The data field of the propose action has a tx field, which is a transaction type. This transaction type contains an action type, which contains bytes as it's data field. Because of this, we must first serialize a list of action objects.

serializeActions

In the example shown below, a transaction for the eosio updateauth action is serialized using the api object's serializeActions method.

const actions = [
  {
    account: 'eosio',
    name: 'updateauth',
    authorization: [
      {
        actor: 'useraaaaaaaa',
        permission: 'active',
      }
    ],
    data: {
      account: 'useraaaaaaaa',
      permission: 'active',
      parent: '',
      auth: {
        threshold: 1,
        keys: [
          {
            key: 'PUB_R1_6FPFZqw5ahYrR9jD96yDbbDNTdKtNqRbze6oTDLntrsANgQKZu',
            weight: 1
          }
        ],
        accounts:[],
        waits:[]
      }
    }
  }
];

(async () => {
  const serialized_actions = await api.serializeActions(actions)
}

An example output of serialized_actions call made above is shown below.

[
  {
    account: 'eosio',
    name: 'updateauth',
    authorization: [ [Object] ],
    data: 'F0F0C30F3FFCF0C300000000A8ED3232000000000000000001000000010003FD9ABF3D22615D5621BF74D2D0A652992DE1338E552AD85D5EAF1F39DCAADDB301000000'
  }
]

Propose Input

In the example shown below, the serialized_actions list created above is used in the actions field of the proposeInput's trx field.

Below useraaaaaaaa proposes a multi-sig transaction, which calls the updateauth action of the eosio account (see actions above). This proposal is called changeowner and both useraaaaaaaa and userbbbbbbbb must sign the multi-sig transaction before 2019-09-14T16:39:15.

const proposeInput = {
    proposer: 'useraaaaaaaa',
    proposal_name: 'changeowner',
    requested: [
      {
        actor: 'useraaaaaaaa',
        permission: 'active'
      },
      {
        actor: 'userbbbbbbbb',
        permission: 'active'
      }
    ],
    trx: {
      expiration: '2019-09-14T16:39:15',
      ref_block_num: 0,
      ref_block_prefix: 0,
      max_net_usage_words: 0,
      max_cpu_usage_ms: 0,
      delay_sec: 0,
      context_free_actions: [],
      actions: serialized_actions,
      transaction_extensions: []
    }
  };

Propose

In the example below, a transaction is submitted to the propose action of the eosio.msig contract using the proposeInput object created above.

await api.transact({
  actions: [{
    account: 'eosio.msig',
    name: 'propose',
    authorization: [{
      actor: 'useraaaaaaaa',
      permission: 'active',
    }],
    data: proposeInput,
  }]
}, {
  blocksBehind: 3,
  expireSeconds: 30,
  broadcast: true,
  sign: true
});

Propose a Multi-sig Transaction

Below all three steps to propose a multi-sig transaction are provided.

// CREATE ACTION TO PROPOSE
const actions = [
  {
    account: 'eosio',
    name: 'updateauth',
    authorization: [
      {
        actor: 'useraaaaaaaa',
        permission: 'active',
      }
    ], data: {
      account: 'useraaaaaaaa',
      permission: 'active',
      parent: '',
      auth: {
        threshold: 1,
        keys: [
          {
            key: 'PUB_R1_6FPFZqw5ahYrR9jD96yDbbDNTdKtNqRbze6oTDLntrsANgQKZu',
            weight: 1
          }
        ],
        accounts:[],
        waits:[]
      }
    },
  }
];

(async () => {
  const serialized_actions = await api.serializeActions(actions)

  // BUILD THE MULTISIG PROPOSE TRANSACTION
  proposeInput = {
    proposer: 'useraaaaaaaa',
    proposal_name: 'changeowner',
    requested: [
      {
        actor: 'useraaaaaaaa',
        permission: 'active'
      },
      {
        actor: 'userbbbbbbbb',
        permission: 'active'
      }
    ],
    trx: {
      expiration: '2019-09-16T16:39:15',
      ref_block_num: 0,
      ref_block_prefix: 0,
      max_net_usage_words: 0,
      max_cpu_usage_ms: 0,
      delay_sec: 0,
      context_free_actions: [],
      actions: serialized_actions,
      transaction_extensions: []
    }
  };

  //PROPOSE THE TRANSACTION
  const result = await api.transact({
    actions: [{
      account: 'eosio.msig',
      name: 'propose',
      authorization: [{
        actor: 'useraaaaaaaa',
        permission: 'active',
      }],
      data: proposeInput,
    }]
  }, {
    blocksBehind: 3,
    expireSeconds: 30,
    broadcast: true,
    sign: true
  });
})();