polkadot.ts 4.25 KiB
Newer Older
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/**
 * @ignore Don't show this file in documentation.
 */ /** */

import { Keyring } from '@polkadot/api';
import { cryptoWaitReady } from '@polkadot/util-crypto';

import {
	createSignedTx,
	createSigningPayload,
	decode,
	deriveAddress,
	getRegistry,
	getTxHash,
	methods,
	POLKADOT_SS58_FORMAT,
} from '../src';
import { rpcToNode, signWith } from './util';
 * Entry point of the script. This script assumes a Polkadot node is running
 * locally on `http://localhost:9933`.
 */
async function main(): Promise<void> {
	// Wait for the promise to resolve async WASM
	await cryptoWaitReady();
	// Create a new keyring, and add an "Alice" account
	const keyring = new Keyring();
	const alice = keyring.addFromUri('//Alice', { name: 'Alice' }, 'sr25519');
	console.log(
		"Alice's SS58-Encoded Address:",
		deriveAddress(alice.publicKey, POLKADOT_SS58_FORMAT)
	);
	// Construct a balance transfer transaction offline.
	// To construct the tx, we need some up-to-date information from the node.
	// `txwrapper` is offline-only, so does not care how you retrieve this info.
	// In this tutorial, we simply send RPC requests to the node.
	const { block } = await rpcToNode('chain_getBlock');
	const blockHash = await rpcToNode('chain_getBlockHash');
	const genesisHash = await rpcToNode('chain_getBlockHash', [0]);
	const metadataRpc = await rpcToNode('state_getMetadata');
	const { specVersion, transactionVersion } = await rpcToNode(
		'state_getRuntimeVersion'
	);
	// Create Polkadot's type registry.
	const registry = getRegistry('Polkadot', 'polkadot', specVersion);
	// Now we can create our `balances.transfer` unsigned tx. The following
	// function takes the above data as arguments, so can be performed offline
	// if desired.
emostov's avatar
emostov committed
	const unsigned = methods.balances.transfer(
emostov's avatar
emostov committed
			dest: '14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3', // Bob
		},
		{
			address: deriveAddress(alice.publicKey, POLKADOT_SS58_FORMAT),
			blockHash,
			blockNumber: registry
				.createType('BlockNumber', block.header.number)
				.toNumber(),
			eraPeriod: 64,
			genesisHash,
			metadataRpc,
			nonce: 0, // Assuming this is Alice's first tx on the chain
			specVersion,
			tip: 0,
			transactionVersion,
		},
		{
			metadataRpc,
			registry,
		}
	);
	// Decode an unsigned transaction.
	const decodedUnsigned = decode(
		unsigned,
		{
			metadataRpc,
			registry,
		},
		true
	);
	console.log(
		`\nDecoded Transaction\n  To: ${decodedUnsigned.method.args.dest}\n` +
			`  Amount: ${decodedUnsigned.method.args.value}`
	);
	// Construct the signing payload from an unsigned transaction.
	const signingPayload = createSigningPayload(unsigned, { registry });
	console.log(`\nPayload to Sign: ${signingPayload}`);
	// Decode the information from a signing payload.
	const payloadInfo = decode(
		signingPayload,
		{
			metadataRpc,
			registry,
		},
		true
	);
	console.log(
		`\nDecoded Transaction\n  To: ${payloadInfo.method.args.dest}\n` +
			`  Amount: ${payloadInfo.method.args.value}`
	);
	// Sign a payload. This operation should be performed on an offline device.
	const signature = signWith(alice, signingPayload, {
		metadataRpc,
		registry,
	});
	console.log(`\nSignature: ${signature}`);
	// Serialize a signed transaction.
	const tx = createSignedTx(unsigned, signature, { metadataRpc, registry });
	console.log(`\nTransaction to Submit: ${tx}`);
	// Derive the tx hash of a signed transaction offline.
	const expectedTxHash = getTxHash(tx);
	console.log(`\nExpected Tx Hash: ${expectedTxHash}`);
	// Send the tx to the node. Again, since `txwrapper` is offline-only, this
	// operation should be handled externally. Here, we just send a JSONRPC
	// request directly to the node.
	const actualTxHash = await rpcToNode('author_submitExtrinsic', [tx]);
	console.log(`Actual Tx Hash: ${actualTxHash}`);
	// Decode a signed payload.
	const txInfo = decode(
		tx,
		{
			metadataRpc,
			registry,
		},
		true
	);
	console.log(
		`\nDecoded Transaction\n  To: ${txInfo.method.args.dest}\n` +
			`  Amount: ${txInfo.method.args.value}\n`
	);
}

main().catch((error) => {