Searchโ€ฆ
TxWrapper
Parity provides an SDK called TxWrapper to generate and sign transactions offline. We have wrapped up a Bifrost version of TxWrapper at your convenience. See the examples for a guide.

Understanding Transaction Format

First we need to know the transaction format so that we can construct a qulified offline transaction.
Polkadot has some basic transaction information that is common to all transactions.
  • Address: The SS58-encoded address of the sending account.
  • Block Hash: The hash of the checkpoint 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: Optional, the tip to increase transaction priority.
  • Era Period: Optional, the number of blocks after the checkpoint for which a transaction is valid. If zero, the transaction is immortal.
*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 transfer function from the Balances pallet will take:
  • value : Number of tokens
  • dest : Destination address
    Once you have all the necessary information, you will need to:
    1. 1.
      Construct an unsigned transaction.
    2. 2.
      Create a signing payload.
    3. 3.
      Sign the payload.
    4. 4.
      Serialize the signed payload into a transaction.
    5. 5.
      Submit the serialized transaction.

Walking through the Exampleโ€‹

1.Provide a private key
You can either create a key ring in the document or import one.
  • Direct creation
1
import { Keyring } from "@polkadot/api";
2
โ€‹
3
const keyring = new Keyring();
4
const alice = keyring.addFromUri("//Alice", { name: "Alice" }, "sr25519");
Copied!
  • import a privateKey
1
import { importPrivateKey } from '@substrate/txwrapper';
2
โ€‹
3
const keypair = importPrivateKey(โ€œpulp gaze fuel ... mercy inherit equalโ€);
Copied!
2. Construct a transaction offline
1
import { methods } from "@substrate/txwrapper";
2
โ€‹
3
const unsigned = methods.balances.transfer(
4
{
5
value: "90071992547409910",
6
dest: "14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3", // Bob
7
},
8
{
9
address: deriveAddress(alice.publicKey, 6), // TODO, use correct prefix
10
blockHash,
11
blockNumber: registry
12
.createType("BlockNumber", block.header.number)
13
.toNumber(),
14
eraPeriod: 64,
15
genesisHash,
16
metadataRpc,
17
nonce: 0, // Assuming this is Alice's first tx on the chain
18
specVersion,
19
tip: 0,
20
transactionVersion,
21
},
22
{
23
metadataRpc,
24
registry,
25
}
26
);
Copied!
3. Construct a signing payload
1
import { createSigningPayload } from '@substrate/txwrapper';
2
3
const decodedUnsigned = decode(unsigned, {
4
metadataRpc,
5
registry,
6
});
Copied!
4. Serialize a signed transaction
1
const signature = signWith(alice, signingPayload, {
2
metadataRpc,
3
registry,
4
});
5
โ€‹
6
const tx = construct.signedTx(unsigned, signature, {
7
metadataRpc,
8
registry,
9
});
Copied!
5. Decode payload types You may want to decode payloads to verify their contents prior to submission.
1
const decodedUnsigned = decode(unsigned, {
2
metadataRpc,
3
registry,
4
});
5
6
const payloadInfo = decode(signingPayload, {
7
metadataRpc,
8
registry,
9
});
10
11
const txInfo = decode(tx, {
12
metadataRpc,
13
registry,
14
});
Copied!
6. Check a transaction's hash
1
const expectedTxHash = construct.txHash(tx);
Copied!
7. Submitting a Signed Payload
1
const actualTxHash = await rpcToLocalNode("author_submitExtrinsic", [tx]);
Copied!

How to use txwrapper-bifrost

Here's a mini-tutorial on how txwrapper-bifrost can interact with a Bifrost chain. We're using a Bifrost dev chain (https://github.com/bifrost-finance/bifrost)

Run the Example

  1. 1.
    Fetch the latest Bifrost node from the above link. Follow instructions to build it, and start a dev chain.
    target/release/bifrost --dev
  2. 2.
    Install dependencies and build the JS target
    1
    # from this repos root directory run
    2
    yarn install
    3
    # build the JS target
    4
    yarn build
    Copied!
  3. 3.
    Run the example script (see src/bifrost-poa.ts. It will interact with your local node.
    yarn bifrost

Expected Output

Here's a sample output of the above script, using a Polkadot node. Your payload to sign and signature will of course differ from this example.
1
Alice's SS58-Encoded Address: gXCcrjjFX3RPyhHYgwZDmw8oe4JFpd5anko3nTY8VrmnJpe
2
2021-03-17 15:27:03 REGISTRY: Unable to resolve type CurrencyId, it will fail on construction
3
โ€‹
4
Decoded Transaction
5
To: [object Object]
6
Amount: 90071992547409910
7
โ€‹
8
Payload to Sign: 0xb00600008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4813f6ffffffffff3f01750200000100000001000000472fb2b977307379477a6be2cb6e23ade0343797d564e54b1fe33d291ee4146874b19ef9828fd83dca228286e9e7b421429574b4def3e15e643e75cb37d719b2
9
โ€‹
10
Decoded Transaction
11
To: [object Object]
12
Amount: 90071992547409910
13
โ€‹
14
Signature: 0x010c8d39b3c70da71719b9889f7785e0552ed538de2c06acbaa1f070f402739d7214cf1bcbeb873b6f955dd3c11345b92705ddc6c910f67aa590abbcc4d6956b8b
15
โ€‹
16
Transaction to Submit: 0x4d028400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d010c8d39b3c70da71719b9889f7785e0552ed538de2c06acbaa1f070f402739d7214cf1bcbeb873b6f955dd3c11345b92705ddc6c910f67aa590abbcc4d6956b8b750200000600008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4813f6ffffffffff3f01
17
โ€‹
18
Expected Tx Hash: 0x80c321fd3a2ce59c299850b250ed4aa3d869297789bbb50a54c35e829f69c066
19
Actual Tx Hash: 0x80c321fd3a2ce59c299850b250ed4aa3d869297789bbb50a54c35e829f69c066
20
โ€‹
21
Decoded Transaction
22
To: [object Object]
23
Amount: 90071992547409910
Copied!
Last modified 1mo ago