Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Latest commit

 

History

History
152 lines (107 loc) · 5.52 KB

tutorial.md

File metadata and controls

152 lines (107 loc) · 5.52 KB

Tutorial

A Quick Glance

Muta is a high-performance blockchain framework, aiming to build a high-quality blockchain system. @nervosnetwork/muta-sdk-jsis an SDK(Software Development Kit) implemented by TypeScript, and used to interact with Muta instance. The runnable demo in this tutorial works well in NodeJS >= 10 as it is written by JavaScript, and some structures that need to be explained will be described by TypeScript interface. It is highly recommended that editing the demo code in VS Code or WebStorm, since a modern IDE would be better to help you to auto-complete the code.

Installation

npm

npm install graphql@14.7 @mutadev/muta-sdk@dev

yarn

yarn add graphql@14.7 @mutadev/muta-sdk@dev

The SDK is organized with monorepo mode that means the SDK is modular, and the @mutadev/muta-sdk is an all-in-one module containing other modules. Therefore, we generally only need to use @mutadev/muta-sdk

General

  • Module in the SDK are exported as ES6 named module, so import always like this way const { SomeThing } = require('@mutadev/some-module');
  • Class are exported with first letter uppercase CamelCase , e.g. Client AssetService
  • function or static module are exported with first letter lowercase camelCase, e.g. utils createTransactionSignature
const { Client, Account, retry, /*...*/ } = require('@mutadev/muta-sdk');

async function main() {
    const client = new Client();
	const block = await client.getBlock();
    console.log(block);
}

The Service

There is a concept called service in Muta. Simply said, service is a class composed of multiple methods, so we can call them in the same way.

{
    "serviceName": "the_service_name",
    "method": "the_method_name",
    "payload": "{ \"a_payload_key\": \"a_value\" }"
}
  • serviceName: a string that means namespace of service, we can think of it as a class
  • method: a string that means a method of a service
  • payload: a string that means method arguments, in most case, it is a JSON serialized string

Here is a short demo to show how to query balance

await client.queryService({
    serviceName: 'asset',
    method: 'get_balance',
    payload: JSON.stringify({ 
        asset_id: '0x0000000000000000000000000000000000000000000000000000000000000000', 
        user: 'muta1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqggfy0d'
    })
});

Transaction

When we try to modify the service status, such as transfer, we need to send a signed transaction. A transaction is composed by following structure. In order to ensure security, the transaction processed by Muta will only be a transaction within a certain gap in the future, so the structure of the signature contains the timeout field. We can use the composeTransaction to help up to generate a raw(unsigned) transaction

The following code shows how to create a raw transaction, that used to call the asset service for transfer.

await client.composeTransaction({
    service: 'asset',
    method: 'transfer',
    payload: "{ \"user\": \"muta1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqggfy0d", \"value\": 1 }"
});

Signature

Muta will only execute transactions that have been correctly signed. So we need to sign the transaction before we send it.

The private key is essential for the signature process, and it is important to note that the private key should not be known to anyone other than you, otherwise you will be impersonated.

const account = new Account('0x0000000000000000000000000000000000000000000000000000000000000001');

We can sign a transaction in this way

const signedTransaction = account.signTransaction(rawTransaction);

The rawTransaction was generated by composeTransaction that we mentioned above. Next, just send the transaction to Muta, and we'll get a txHash from the Muta, meaning that the transaction is already known to Muta.

const txHash = await client.sendTransaction(signedTransaction);

The transfer wasn't successful until we got the receipt.

Receipt

Note that a receipt does not return immediately, it waits until the consensus node succeeds, so we can retry until it succeeds.

const receipt = await retry(() => client.getReceipt(txHash));

Configuration

We can see all the demo classes above constructed without argument, this is because the @mutadev/defaults provided the default variables. We can change the default variables by changing environment variables

export MUTA_ENDPOINT=http://127.0.0.1:8001

Also we can config when constructing

const client = new Client({
    endpoint: 'http://127.0.0.1:8001'
});

The configuration priorities is Constructor > Environment Variable > default variables.

Service Binding

Here is a short demo showing how we build an asset on Muta via @mutadev/service

const { AssetService } = require('@mutadev/service');

async function main() {
    const service = new AssetService();
    const created = await service.write.create_asset({
        name: 'MyToken',
        supply: 10000000,
        symbol: 'MT'
    });
    
    const asset = await service.read.get_asset({
        id: created.response.response.succeedData.id
    });
    console.log(`I have created an asset [${asset.succeedData.name}] on Muta succeffuly`);
}