@gear-js/api

A JavaScript library that provides functionality to connect GEAR Component APIs.

Usage no npm install needed!

<script type="module">
  import gearJsApi from 'https://cdn.skypack.dev/@gear-js/api';
</script>

README

GEAR


Description

A JavaScript library that provides functionality to connect GEAR Component APIs.

Installation

npm install @gear-js/api

or

yarn add @gear-js/api

Getting started

Start an API connection to a running node on localhost

import { GearApi } from '@gear-js/api';

const gearApi = await GearApi.create();

You can also connect to a different node

const gearApi = await GearApi.create({ providerAddress: 'wss://someIP:somePort' });

Getting node info

const chain = await gearApi.chain();
const nodeName = await gearApi.nodeName();
const nodeVersion = await gearApi.nodeVersion();
const genesis = gearApi.genesisHash.toHex();

Encode / decode payloads

Encode data

import { CreateType } from '@gear-js/api';

// If "TypeName" alredy registred
const result = CreateType.encode('TypeName', somePayload);
// Otherwise need to add metadata containing TypeName and all required types
const result = CreateType.encode('TypeName', somePayload, metadata);

By analogy data is decoded

const result = CreateType.decode('TypeName', someBytes);
// or
const result = CreateType.decode('TypeName', someBytes, metadata);

Result of this functions is data of type Codec and it has the next methods

result.toHex(); // - returns a hex represetation of the value
result.toHuman(); // - returns human friendly object representation of the value
result.toString(); //  - returns a string represetation of the value
result.toU8a(); // - encodes the value as a Unit8Array
result.toJSON(); // - converts the value to JSON

Getting metadata

Getting metadata from program.meta.wasm

import { getWasmMetadata } from '@gear-js/api';
const fileBuffer = fs.readFileSync('path/to/program.meta.wasm');
const meta = await getWasmMetadata(fileBuffer);

Sign messages

Creating signature

import { GearKeyring } from '@gear-js/api';
const message = 'your message';
const signature = GearKeyring.sign(keyring, message);

// Check signature
const publicKey = keyring.address;
const verified = GearKeyring.checkSign(publicKey, signature, message);

Upload program

const code = fs.readFileSync('path/to/program.wasm');

const program = {
  code,
  gasLimit: 1000000,
  value: 1000,
  initPayload: somePayload,
};

try {
  const { programId, salt } = await gearApi.program.submit(uploadProgram, meta);
} catch (error) {
  console.error(`${error.name}: ${error.message}`);
}

try {
  await gearApi.program.signAndSend(keyring, (event) => {
    console.log(event.toHuman());
  });
} catch (error) {
  console.error(`${error.name}: ${error.message}`);
}

Send message

try {
  const message = {
    destination: destination, // programId
    payload: somePayload,
    gasLimit: 10000000,
    value: 1000,
  };
  // In that case payload will be encoded using meta.handle_input type
  await gearApi.message.submit(message, meta);
  // So if you want to use another type you can specify it
  await gearApi.message.submit(message, meta, meta.async_handle_input); // For example
} catch (error) {
  console.error(`${error.name}: ${error.message}`);
}
try {
  await gearApi.message.signAndSend(keyring, (event) => {
    console.log(event.toHuman());
  });
} catch (error) {
  console.error(`${error.name}: ${error.message}`);
}

Submit code

const code = fs.readFileSync('path/to/program.opt.wasm');
const codeHash = gearApi.code.submit(code);
gearApi.code.signAndSend(alice, () => {
  events.forEach(({ event: { method, data } }) => {
    if (method === 'ExtrinsicFailed') {
      throw new Error(data.toString());
    } else if (method === 'CodeSaved') {
      console.log(data.toHuman());
    }
  });
});

Get gasSpent

For init message

const code = fs.readFileSync('demo_ping.opt.wasm');
const gas = await gearApi.program.gasSpent.init(
  '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', // source id
  code,
  '0x00',
);
console.log(gas.toHuman());

For handle message

const code = fs.readFileSync('demo_meta.opt.wasm');
const meta = await getWasmMetadata(fs.readFileSync('demo_meta.opt.wasm'));
const gas = await gearApi.program.gasSpent.handle(
  '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
  '0xa178362715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d', //program id
  {
    id: {
      decimal: 64,
      hex: '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
    },
  },
  meta,
);
console.log(gas.toHuman());

For reply message

const code = fs.readFileSync('demo_async.opt.wasm');
const meta = await getWasmMetadata(fs.readFileSync('demo_async.opt.wasm'));
const gas = await gearApi.program.gasSpent.reply(
  '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
  '0x518e6bc03d274aadb3454f566f634bc2b6aef9ae6faeb832c18ae8300fd72635', // message id
  0, // exit code
  'PONG',
  meta,
);
console.log(gas.toHuman());

Read state of program

const metaWasm = fs.readFileSync('path/to/meta.wasm');
const state = gearApi.programState.read(programId, metaWasm);
// If program expects inputValue in meta_state function it's possible to specify it
const state = gearApi.programState.read(programId, metaWasm, inputValue);

Subscribe to events

Subscribe to all events

const unsub = await gearApi.allEvents((events) => {
  console.log(event.toHuman());
});
// Unsubscribe
unsub();

Check what the event is

gearApi.allEvents((events) => {
  events
    .filter(({ event }) => gearApi.events.gear.InitMessageEnqueued.is(event))
    .forEach(({ event: { data } }) => {
      console.log(data.toHuman());
    });

  events
    .filter(({ event }) => gearApi.events.balances.Transfer.is(event))
    .forEach(({ event: { data } }) => {
      console.log(data.toHuman());
    });
});

Subscribe to Log events

const unsub = await gearApi.gearEvents.subscribeLogEvents(({ data: { id, source, dest, payload, reply } }) => {
  console.log(`
  logId: ${id.toHex()}
  source: ${source.toHex()}
  payload: ${payload.toHuman()}
  `);
});
// Unsubscribe
unsub();

Subscribe to Program events

const unsub = await gearApi.gearEvents.subscribeProgramEvents(({ method, data: { info, reason } }) => {
  console.log(method);
  console.log(`ProgramId: ${info.programId}`);
  reason && console.log(`Reason: ${reason.toHuman()}`);
});
// Unsubscribe
unsub();

Subscribe to Transfer events

const unsub = await gearApi.gearEvents.subscribeTransferEvents(({ data: { from, to, value } }) => {
  console.log(`
    Transfer balance:
    from: ${from.toHex()}
    to: ${to.toHex()}
    value: ${+value.toString()}
    `);
});
// Unsubscribe
unsub();

Subscribe to new blocks

const unsub = await gearApi.gearEvents.subscribeToNewBlocks((header) => {
  console.log(`New block with number: ${header.number.toNumber()} and hash: ${header.hash.toHex()}`);
});
// Unsubscribe
unsub();

Get block data

const data = await gearApi.blocks.get(blockNumberOrBlockHash);
console.log(data.toHuman());

Get block timestamp

const ts = await gearApi.blocks.getBlockTimestamp(blockNumberOrBlockHash);
console.log(ts.toNumber());

Get blockHash by block number

const hash = await gearApi.blocks.getBlockHash(blockNumber);
console.log(hash.toHex());

Get block number by blockhash

const hash = await gearApi.blocks.getBlockNumber(blockHash);
console.log(hash.toNumber());

Get all block's events

const events = await gearApi.blocks.getEvents(blockHash);
events.forEach((event) => {
  console.log(event.toHuman());
});

Get all block's extrinsics

const extrinsics = await gearApi.blocks.getExtrinsics(blockHash);
extrinsics.forEach((extrinsic) => {
  console.log(extrinsic.toHuman());
});

Create keyring

Creating a new keyring

import { GearKeyring } from '@gear-js/api';
const { keyring, json } = await GearKeyring.create('keyringName', 'passphrase');

Getting a keyring from JSON

const jsonKeyring = fs.readFileSync('path/to/keyring.json').toString();
const keyring = GearKeyring.fromJson(jsonKeyring, 'passphrase');

Getting JSON for keyring

const json = GearKeyring.toJson(keyring, 'passphrase');

Getting a keyring from seed

const seed = '0x496f9222372eca011351630ad276c7d44768a593cecea73685299e06acef8c0a';
const keyring = await GearKeyring.fromSeed(seed, 'name');

Getting a keyring from mnemonic

const mnemonic = 'slim potato consider exchange shiver bitter drop carpet helmet unfair cotton eagle';
const keyring = GearKeyring.fromMnemonic(mnemonic, 'name');

Generate mnemonic and seed

const { mnemonic, seed } = GearKeyring.generateMnemonic();

// Getting a seed from mnemonic
const { seed } = GearKeyring.generateSeed(mnemonic);