Skip to content

Transactions

Paul edited this page Nov 3, 2022 · 21 revisions

In this tutorial we will skim through the transaction format in 3DPass and how to create, sign, and broadcast transactions. Like the other pages in this guide, this page demonstrates some of the available tools. Always refer to each tool's documentation when integrating.

Summary

Once you have all the necessary information, you will need to:

  1. Construct an unsigned transaction.
  2. Create a signing payload.
  3. Sign the payload.
  4. Serialize the signed payload into a transaction.
  5. Submit the serialized transaction.

Transaction Format

3DPass has some basic transaction information which is common to all transactions:

  • Address: The SS58-encoded address of the sending account.
  • Block Hash: The hash of the ckeckpont block.
  • Block Number: The number of the checkpoint block.
  • Genesis Hash: The genesis hash of the chain.
  • Metadata: The SCALE-encoded metadata for the runtime when submitted.
  • Nonce: The nonce for this transaction. **
  • Spec Version: The current spec version for the runtime.
  • Transaction Version: The current version for transaction format.
  • Tip: additional fee to increase transaction priority.

** The nonce queried from the System module does not account for pending transactions. You must track and increment the nonce manually if you want to submit multiple valid transactions at the same time.

Each transaction will have its own (or no) parameters to add. For example, the transferKeepAlive function from the Balances pallet will take:

  • dest: Destination address
  • #[compact] value: Number of tokens (compact encoding)

Before being submitted, transactions are serialized. Serialized transactions are hex encoded SCALE-encoded bytes. The specific serialization is defined in the runtime and can change if the runtime is upgraded, but in general the serialization format can be described as follows:

  • Compact encoded number of SCALE encoded bytes following this.
  • 1 bit: it is a 0 if no signature is present, or a 1 if it is.
  • 7 bits: the extrinsic version, it is equal to 4 in decimal.- 4 bytes: Spec version of the runtime.
  • 4 bytes: Transaction version of the runtime.
  • 32 bytes: Genesis hash of the chain.
  • 32 bytes: Block hash serving as the era reference. If the transaction is immortal, then this would be the genesis hash.
  • If there is a signature:
    1. a SCALE encoded sp_runtime::MultiAddress::Id<AccountId32, u32> indicating the signer(s) of the transaction.
    2. a SCALE encoded sp_runtime::MultiSignature::{SigningScheme} with the signature **.
    3. Compact encoded u32 with the nonce.
    4. Compact encoded u128 with the tip paid to the block producer.
    5. a SCALE encoded sp_runtime::traits::SignedExtension<Vec<Text>> with the additional data and logic associated with this transaction.
  • The specific transaction parameters or call data, which consists of:
    1. 1 byte: the pallet index the transaction is calling into.
    2. 1 byte: the function in the pallet the transaction is calling.
    3. variable: the SCALE-encoded parameters required by the function being called.

** 3DPass supports sr25519, ed25519, and ECDSA as signing schemes.

The metadata provides you with all of the information required to know how to construct the serialized call data specific to your transaction. You can read more about the metadata, its format and how to get it in the Substrate documentation.

Polkadot-JS Tools

Polkadot-JS Tools contains a set of command line tools for interacting with a Substrate client, including one called "Signer CLI" to create, sign, and broadcast transactions.

This example will use the signer submit command, which will create and submit the transaction. The signer sendOffline command has the exact same API, but will not broadcast the transaction. submit and sendOffline must be connected to a node to fetch the current metadata and construct a valid transaction. Their API has the format:

yarn run:signer <submit|sendOffline> --account <from-account-ss58> --ws <endpoint> <module.method> [param1] [...] [paramX]

Signing:

yarn run:signer sign --account <from-account-ss58> --seed <seed> --type <sr25519|ed25519> <payload>

For example, let's send 0.5 P3D from d1GLtigmE1nf4ZH89fTQCm88qkFMmwjqWHihxsHq8kFkpBU9N to d1EJvnsCUTYL6ZLrj2Sih8Xaryf7f82R7jh9gvpqan6WUq4Ly

yarn run:signer submit --account d1GLtigmE1nf4ZH89fTQCm88qkFMmwjqWHihxsHq8kFkpBU9N --ws ws://127.0.0.1:9944 balances.transferKeepAlive d1EJvnsCUTYL6ZLrj2Sih8Xaryf7f82R7jh9gvpqan6WUq4Ly 500000000000

Save the output and bring it to the machine that you will broadcast from, enter it into submit's signature field, and send the transaction (or just return the serialized transaction if using sendOffline).

Polkadot-JS RPC examples

3DPass web wallet examples

3DPass web wallet uses Polkadot-JS RPC. Follow the code examples down below as a reference to its exact implementation:

Transaction status evaluation

Once transaction has been added in block, it's considered to be valid. However, the best chain might still be reorganized until the block is gotten finalized. And so, it's recommended to trust to the blocks finalized only. Read more about block finalization. Follow the transfer events examples to track the current status of your transaction.

Transaction list

One of the common ways to get transaction list and retrieve some additional data is to use the block explorer API server. Follow 3DPscan repository to learn how to run it up as a standalone server.