NAV Navbar

Introduction

QuarkChain is an innovative permissionless blockchain architecture that aims to provide a secure, decentralized, and scalable blockchain solution to deliver 100,000+ on-chain TPS.

QuarkChain fully supports Ethereum smart contract enabling developers to write and debug smart contract quickly using popular tools like remix and build scalable DApps that will be free from network congestion. As you may know, CryptoKitties, one of the most popular blockchain games, severely slowed down the transactions on Ethereum in Dec 2017 and resulted in network congestion for weeks. It shows the importance of scalability issues.

QuarkChain has launched a public testnet with 6450 nodes and 256 shards and presented a live demo of 10K+ TPS which is about 500X Ethereum’s throughput in 2018, and the mainnet has launched on 4/30, 2019.

The main features of QuarkChain include:

Basic Concepts

Address

A QuarkChain address consists of a normal 20-byte Ethereum address (which is called the recipient of a QuarkChain address) and a 4-byte full shard key.

To better support re-sharding and dynamic updates without affecting existing shards, we proposed a middle layer abstraction between the whole network and the underlying shards, which is called, well, chains: a QuarkChain network, contains multiple chains, where each chain contains multiple shards. Note that a chain is merely a conceptual layer, all the consensus logic (e.g. root-chain-first-consensus, or cross-shard transaction implementation) still apply to all the shards.

For example, the following is a QuarkChain address.

To find the chain an address belongs to, we use the following function

And to find the shard an address belongs to, use the following function

Now the 4-byte full shard ID is encoded as following (using 0x0001000f as an example):

  1. Use first two bytes to denote chain ID. In the example the chain ID is 1 (0x0001)
  2. The remaining two bytes follow the same encoding as before. Assume chain 1 has 8 shards, 0x000f corresponds to shard 7 because SHARD_ID = FULL_SHARD_ID & (SHARD_SIZE - 1)

Therefore 0x0001000f should be interpreted as chain 1 shard 7.

With the same formula you can build addresses of the same recipient for different shards. This will allow a single recipient to receive QKC in any shard.

QuarkChain network consists of a certain number of chains and each chain has a certain number of shards (SHARD_SIZE) which is always a power of 2.

Another common value returned in JSON RPC is called branch, which is simply a wrapper over aforementioned ID encoding, also it's used interchangeably with fullShardId

Note SHARD_SIZE is encoded in the latter 2 bytes as the most significant bit.

Also, addresses used in an EVM smart contract are still 20 bytes (the recipient in QuarkChain) as the execution scope of a smart contract cannot go beyond the shard it belongs to.

For a more detailed comparison between full shard keys v.s. full shard IDs (or branches), take a look at this GitHub issue.

Transaction

These are the fields for a transaction:

fields = [
  ("nonce", big_endian_int),
  ("gasprice", big_endian_int),
  ("startgas", big_endian_int),
  ("to", utils.address),
  ("value", big_endian_int),
  ("data", binary),
  ("network_id", big_endian_int),
  ("from_full_shard_key", BigEndianInt(4)),
  ("to_full_shard_key", BigEndianInt(4)),
  ("gas_token_id", big_endian_int),
  ("transfer_token_id", big_endian_int),
  ("version", big_endian_int),
  ("v", big_endian_int),
  ("r", big_endian_int),
  ("s", big_endian_int),
]

To the right is the Python definition of a transaction in Quarkchain.

Six fields are added onto the existing Ethereum transaction data structure.

Field Type Description
from_full_shard_key 4 bytes fixed int Identifies the source chain/shard of the transaction
to_full_shard_key 4 bytes fixed int Identifies the destination chain/shard of the transaction
network_id int identifies the network e.g. devnet, mainnet (similar to ethereum's chain id which is hacked into the 'v' field)
version int identifies the signature style; 0: eth-style signature; 1: typed signature (EIP-712) as implemented by MetaMask before #4803; 2: typed signature (EIP-155)
gas_token_id int id of a native token
transfer_token_id int id of a native token

Note that when constructing a transaction, from_full_shard_key should be the last 4 bytes of the sender's address, to should be the recipient of the receiver’s address, i.e., first 20 bytes from receiver's address, and to_full_shard_key should be the full shard key, i.e., last 4 bytes of the receiver's address. network_id should be 255 for current beta version of devnet, or 1 for the mainnet.

On native token, the current mainnet only supports QKC token (ID: 35760 or "0x8bb0"). For the rationale of multi-native-token design, please check out this article.

Transaction Id and Block Id

In QuarkChain we use transaction id and block id to identify transaction and block rather than the transaction hash and block hash used in Ethereum. The id is simply the hash with a full shard key appended so that the object can be looked up directly from the chain/shard.

Root block id is equal to its hash as it does not belong to any chain/shard.

Minor block refers to the block on each chain/shard.

Smart Contracts

QuarkChain runs EVM on each chain/shard and thus supports all Ethereum smart contract bytecode compiled from Solidity.

Deployment

A smart contract is always deployed to a specific chain/shard decided by toFullShardKey in the transaction. Similar to Ethereum, leave the to field empty and put the byte code in the data field.

fromFullShardKey and toFullShardKey must map to the same chain/shard in order to succeed, i.e., the same chain/shard id according to Eq. (1). The fullShardKey of the contract address created will be the same as toFullShardKey. Normally you should just set toFullShardKey the same as fromFullShardKey.

A couple of comments on smart contract deployment:

Calling a Smart Contract

Calling a smart contract is simliar to Ethereum -- you can either use the UI on the blockchain explorer and load the ABI, or you can use a library like web3 that handles the interfacing for you. As a note, fromFullShardKey and toFullShardKey must map to the same chain/shard in order for the call to succeed. Otherwise gas will be consumed but the contract will not be called.

Tutorial

Support for DApp development is still at early stage though we aim at providing the same level of development experience as Ethereum eventually. This tutorial assumes readers have basic knowledge of Ethereum smart contract development and thus it focuses on the contract deployment and invocation on QuarkChain network. Also please read the Basic Concepts before proceeding with the tutorial.

MetaMask

QuarkChain supports using MetaMask to perform non-cross-chain operations (such as transfers, contract calls), the usage is same as Ethereum. The following table is the configuration of MetaMask for mainnet and devnet.

Network Name RPC URL Chain ID Currency Symbol Block Explorer URL
Quarkchain S0 http://eth-jrpc.mainnet.quarkchain.io:39000 100001 QKC https://mainnet.quarkchain.io/0
Quarkchain S1 http://eth-jrpc.mainnet.quarkchain.io:39001 100002 QKC https://mainnet.quarkchain.io/1
Quarkchain S2 http://eth-jrpc.mainnet.quarkchain.io:39002 100003 QKC https://mainnet.quarkchain.io/2
Quarkchain S3 http://eth-jrpc.mainnet.quarkchain.io:39003 100004 QKC https://mainnet.quarkchain.io/3
Quarkchain S4 http://eth-jrpc.mainnet.quarkchain.io:39004 100005 QKC https://mainnet.quarkchain.io/4
Quarkchain S5 http://eth-jrpc.mainnet.quarkchain.io:39005 100006 QKC https://mainnet.quarkchain.io/5
Quarkchain S6 http://eth-jrpc.mainnet.quarkchain.io:39006 100007 QKC https://mainnet.quarkchain.io/6
Quarkchain S7 http://eth-jrpc.mainnet.quarkchain.io:39007 100008 QKC https://mainnet.quarkchain.io/7
Network Name RPC URL Chain ID Currency Symbol Block Explorer URL
Quarkchain Dev S0 http://eth-jrpc.devnet.quarkchain.io:39900 110001 QKC https://devnet.quarkchain.io/0
Quarkchain Dev S1 http://eth-jrpc.devnet.quarkchain.io:39901 110002 QKC https://devnet.quarkchain.io/1
Quarkchain Dev S2 http://eth-jrpc.devnet.quarkchain.io:39902 110003 QKC https://devnet.quarkchain.io/2
Quarkchain Dev S3 http://eth-jrpc.devnet.quarkchain.io:39903 110004 QKC https://devnet.quarkchain.io/3
Quarkchain Dev S4 http://eth-jrpc.devnet.quarkchain.io:39904 110005 QKC https://devnet.quarkchain.io/4
Quarkchain Dev S5 http://eth-jrpc.devnet.quarkchain.io:39905 110006 QKC https://devnet.quarkchain.io/5
Quarkchain Dev S6 http://eth-jrpc.devnet.quarkchain.io:39906 110007 QKC https://devnet.quarkchain.io/6
Quarkchain Dev S7 http://eth-jrpc.devnet.quarkchain.io:39907 110008 QKC https://devnet.quarkchain.io/7

Quarkchain + Web3.js

QuarkChain’s client library quarkchain-web3.js is built around web3.js which is the Javascript-based client library for Ethereum. Please visit the quarkchain-web3.js github repo for the API and examples. MetaMask is required to manage accounts and sign transactions if you are using quarkchain-web3.js. Follow the steps below to try it out, or you can navigate to the API Access section for more direct usage.

The below Javascript will retrieve your QKC balance:

QuarkChain.injectWeb3(web3, "http://jrpc.devnet.quarkchain.io:38391");
var ethAddr = web3.eth.accounts[0];  // current ETH account in MetaMask
var qkcAddr = QuarkChain.getQkcAddressFromEthAddress(ethAddr);
web3.qkc.getBalance(qkcAddr).toString(10);  // balance in wei

 1. Install MetaMask and create an account.

 2. Visit http://devnet.quarkchain.io/wallet and verify your MetaMask account is shown on the page

 3. Open the browser console where web3 is automatically injected by MetaMask

 4. Run the Javascript command to verify everything has been set up correctly (ping us on Telegram if you need devnet tokens)

Create wallet

Disable MetaMask and navigate to https://devnet.quarkchain.io/wallet to get a new address. Copy-paste the private key somewhere for signing transactions and recover the address later.

Send Transaction

Below you will find the Javascript code change to ethereumjs-tx that we use in our devnet frontend.

var fields = [{
  name: 'nonce',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'gasPrice',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'gasLimit',
  alias: 'gas',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'to',
  allowZero: true,
  length: 20,
  default: new Buffer([])
}, {
  name: 'value',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'data',
  alias: 'input',
  allowZero: true,
  default: new Buffer([])
}, {
  name: 'networkId',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'fromFullShardKey',
  length: 4,
}, {
  name: 'toFullShardKey',
  length: 4,
}, {
  name: 'gasTokenId',
  length: 8,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'transferTokenId',
  length: 8,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'version',
  length: 32,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 'v',
  allowZero: true,
  default: new Buffer([])
}, {
  name: 'r',
  length: 32,
  allowZero: true,
  allowLess: true,
  default: new Buffer([])
}, {
  name: 's',
  length: 32,
  allowZero: true,
  allowLess: true,
  default: new Buffer([])
}];

Both contract deployment and invocation are performed through sending specially crafted transactions to the QuarkChain network through JSON RPC sendRawTransaction which accepts a serialized transaction object in RLP. Existing Ethereum libraries (e.g., ethereumjs-tx) can be used to create, sign, and serialize transaction objects. However, small changes are required to accommodate addtional fields added specifically for QuarkChain. An alternative is using sendTransaction endpoint by directly passing the transaction data as a JSON object, which requires the caller to have the signatures ready (v, r, and s).

With the above changes we can use the following Javascript code to build a transaction, sign the transaction, and send it to the QuarkChain devnet API.

const txParams = {
    nonce: '0x00',
    gasPrice: '0x09184e72a000',
    gasLimit: '0x2710',
    to: '0x1234567890123456789012345678901234567890',  // recipient of to address
    value: '0x12',
    data: '0x7f746573743',
    fromFullShardKey: '0x12345678',
    toFullShardKey: '0x12345678',
    networkId: '0x1',
    gasTokenId: '0x8bb0',
    transferTokenId: '0x8bb0'
}

const tx = new ethereumjs.Tx(txParams)
const key = '0x...'
tx.sign(ethereumjs.Util.toBuffer(key))
const rawTx = "0x" + tx.serialize().toString("hex")

// Send raw transaction through the devnet web server
try {
    var txResp = await axios.post("https://devnet.quarkchain.io/sendRawTx", {
        rawTx: rawTx,
    });
    // To check transaction status use this id to call getTransactionReceipt
    const txId = txResp.data.txId;
} catch (error) {
    console.log("Sending transaction failed");
}

Contract Deployment

We have three ways to deploy contracts. 1. Deploy the contract through Remix and use MetaMask to point to the shard.

  1. Go to https://devnet.quarkchain.io/contract and deploy the contract through the UI. On the transaction status page you may find the contract address once the transaction is confirmed.

  2. Send a transaction with 'to' left empty, toFullShardKey set to the same value as fromFullShardKey, data filled with the bytecode in hex. Once the transaction is confirmed call getTransactionReceipt with the transaction id to retrieve the contract address.

Note: the bytecode of the contract you use to deploy can be obtained through a tool like Remix.

Contract Invocation

Calling via the devnet API endpoint

try {
    var txResp = await axios.post("https://devnet.quarkchain.io/call", {
        rawTx: rawTx,
    });
    console.log(txResp);
} catch (error) {
    console.log("Call failed");
}

Read

To read data from the contract without modifying the state on the blockchain, create a transaction with the contract function or variable encoded into the data field and use the JSON RPC call interface to retrieve the results. Ethereumjs-abi or other similar libraries can be used to handle encoding.

Write

Similar to read but use sendRawTransaction instead of call to submit the transaction. Like previous example check transaction status through getTransactionReceipt.

JSON RPC

QuarkChain JSON RPC shares the similar interfaces with Ethereum and follows the same HEX value encoding. The most notable difference is the chain/shard id in certain APIs.

The RPCs run on HTTP. All the operations are performed on the lastest blocks.

networkInfo

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "networkInfo",
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "networkId": "0x1",
    "chainSize": "0x8",
    "shardSizes": ["0x1", "0x1", "0x1", "0x1", "0x1", "0x1", "0x1", "0x1"],
    "syncing": false,
    "mining": false,
    "shardServerCount": 4
  },
  "id": 1
}
Param Name Type Description
- N/A N/A
Return Value Type Description
networkId QUANTITY integer of the network id
chainSize QUANTITY integer of the current number of chains in the network
shardSizes QUANTITY integer of the current number of shards by chain in the network
shardServerCount QUANTITY
syncing BOOL whether the cluster is syncing (depends on which cluster the API connects to)
mining BOOL whether is mining locally

getTransactionCount

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getTransactionCount",
  "params": ["0x04E823bfD0EE5a05f072C346282e252e15CCa98D0003c32E"],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": "0x0",
  "id": 1
}

Returns the number of transactions sent from an address. Similar to Ethereum, the transaction count is guaranteed to be non-decreasing.

Param Name Type Description
-- DATA, 24 bytes address you want balance of
Return Value Type Description
-- QUANTITY number of transactions sent from the address

getBalances

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getBalances",
  "params": ["0x04E823bfD0EE5a05f072C346282e252e15CCa98D0006C32E"],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "branch": "0x60001",
    "fullShardId": "0x60001",
    "shardId": "0x0",
    "chainId": "0x6",
    "balances": [{
      "tokenId": "0x3de",
      "tokenStr": "QI",
      "balance": "0x19c00f6b4cbcc00000"
    }, {
      "tokenId": "0x8bb0",
      "tokenStr": "QKC",
      "balance": "0x246fb022c10140f000"
    }]
  },
  "id": 1
}

Returns the balances of the account of given address including native token balances.

Param Name Type Description
-- DATA, 24 bytes address you want balance of
Return Value Type Description
balances JSON array list of tokens' balance object in wei

getAccountData

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getAccountData",
  "params": ["0x04E823bfD0EE5a05f072C346282e252e15CCa98D0003c32E", "latest", true],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "primary": {
      "fullShardId": "0x30001",
      "shardId": "0x0",
      "chainId": "0x3",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    },
    "shards": [{
      "fullShardId": "0x1",
      "shardId": "0x0",
      "chainId": "0x0",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x40001",
      "shardId": "0x0",
      "chainId": "0x4",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x10001",
      "shardId": "0x0",
      "chainId": "0x1",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x50001",
      "shardId": "0x0",
      "chainId": "0x5",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x20001",
      "shardId": "0x0",
      "chainId": "0x2",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x60001",
      "shardId": "0x0",
      "chainId": "0x6",
      "balances": [{
        "tokenId": "0x8bb0",
        "tokenStr": "QKC",
        "balance": "0x8ac7230489e80000"
      }],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x30001",
      "shardId": "0x0",
      "chainId": "0x3",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }, {
      "fullShardId": "0x70001",
      "shardId": "0x0",
      "chainId": "0x7",
      "balances": [],
      "transactionCount": "0x0",
      "isContract": false
    }]
  },
  "id": 1
}

Aggregates account data including both primary and secondary addresses (i.e. addresses in other shards).

Param Name Type Description
-- DATA, 24 bytes
-- STRING The latest block (current head of the blockchain)
-- BOOL true to include data from other shards, otherwise false
Return Value Type Description
primary JSON object account data from primary shard
shards JSON array list of account datas from secondary (other) shards
shardId QUANTITY integer of the shard id
chainId QUANTITY integer of the chain id
balances QUANTITY list of native token balances
tokenId QUANTITY numerical ID of the native token
tokenStr STRING symbol of the native token
balance QUANTITY native token balance
transactionCount QUANTITY number of transactions sent from address
isContract BOOL whether the current chain/shard is a smart contract address

sendTransaction

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "sendTransaction",
  "params": {
    "nonce": "0x4",
    "gasPrice": "0x2540be400",  // 10 Gwei
    "gas": "0x7530",  // 30000
    "value": "0xde0b6b3a7640000",  // 1 QKC
    "data": "0x",
    "fromFullShardKey": "0x19e189ec",
    "toFullShardKey": "0x18f9ba2c",
    "networkId": "0x3",
    "to": "0x283B50c1326F5C09BA792cc0Ad6C08b5035a36711",
    "v": "0x1a",
    "r": "0x293d59ef8705e34585d646f5899530d52a2d39b312fd061607036152e5fcf589",
    "s": "0x98d2e479720cee2be165703dd97085765adc65b18ed8d9dfbf3d6d7e7fe5a6e",
    "gasTokenId":"0x8bb0",
    "transferTokenId":"0x8bb0"
  },
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": "0xa786dc17bf8b302d8678666e5f97290c6467c4302a0a1402cb7693267152402519e189ec",
  "id": 1
}

Creates a new message call transaction or a contract creation, if the data field contains code. Note the transaction needs to be signed by the client (for example, ethereumjs-tx).

Param Name Type Description
nonce QUANTITY (optional) integer of a nonce, for overriding your pending transactions that use the same nonce
gasPrice QUANTITY integer of the gas price used for each paid gas
gas QUANTITY integer of the gas provided for the transaction execution
value QUANTITY (optional) integer of the value sent with this transaction
data DATA compiled code of a contract, OR, the hash of the invoked method signature with encoded parameters
fromFullShardKey QUANTITY, 4 bytes integer of the full shard key for sending address, see Address for more info
toFullShardKey QUANTITY, 4 bytes integer of the full shard key for receiving address
networkId QUANTITY integer of the id of the network (e.g. devnet, mainnet)
to DATA, 20 bytes recipient's address, that does NOT include the full shard key
v QUANTITY ECDSA recovery id
r DATA, 32 bytes ECDSA signature r
s DATA, 32 bytes ECDSA signature s
gasTokenId QUANTITY integer of the id of the native token for gas
transferTokenId QUANTITY integer of the id of the native token to transfer

Notes:

Return Value Type Description
-- DATA, 36 bytes the transaction id or null on failure

sendRawTransaction

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "sendRawTransaction",
  "params": ["0xf87f0b8502540be40082520894d0bb6e0ed6c2e083274af28baa62d0953e4cfb28888ac7230489e800008081ff840000c32e840000f295828bb0828bb0801ba0e838ced32695d6196feae149db2502adadb19ab24ff0e3ea974b967282757f59a06c8d88598eece0d8be3eaf99185d26755c77f8372b129c920eb4a32183643e9b"],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": "0x78b8706047e04a34158f2775409733e2c984638e106e07709489d501722a53120000c32e",
  "id": 1
}

Creates new message call transaction or a contract creation for signed transactions.

Param Name Type Description
-- DATA signed transaction data
Return Value Type Description
-- DATA, 36 bytes the transaction id or null on failure

getTransactionById

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getTransactionById",
  "params": ["0x78b8706047e04a34158f2775409733e2c984638e106e07709489d501722a53120000c32e"],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "id": "0x78b8706047e04a34158f2775409733e2c984638e106e07709489d501722a53120000c32e",
    "hash": "0x78b8706047e04a34158f2775409733e2c984638e106e07709489d501722a5312",
    "nonce": "0xb",
    "timestamp": "0x5cef4ec9",
    "fullShardId": "0x1",
    "chainId": "0x0",
    "shardId": "0x0",
    "blockId": "0x2e86e836527ffe5a2244638955697c0af59c6140057cc08d891e7ea04000844a00000001",
    "blockHeight": "0x1b64a",
    "transactionIndex": "0x0",
    "from": "0x04e823bfd0ee5a05f072c346282e252e15cca98d",
    "to": "0xd0bb6e0ed6c2e083274af28baa62d0953e4cfb28",
    "fromFullShardKey": "0x0000c32e",
    "toFullShardKey": "0x0000f295",
    "value": "0x8ac7230489e80000",
    "gasPrice": "0x2540be400",
    "gas": "0x5208",
    "data": "0x",
    "networkId": "0xff",
    "transferTokenId": "0x8bb0",
    "gasTokenId": "0x8bb0",
    "transferTokenStr": "QKC",
    "gasTokenStr": "QKC",
    "r": "0xe838ced32695d6196feae149db2502adadb19ab24ff0e3ea974b967282757f59",
    "s": "0x6c8d88598eece0d8be3eaf99185d26755c77f8372b129c920eb4a32183643e9b",
    "v": "0x1b"
  },
  "id": 1
}

Gets transaction details with the transaction id returned from sendTransaction or sendRawTransaction.

Param Name Type Description
-- DATA, 36 bytes transaction id
Return Value Type Description
blockHeight QUANTITY integer of the block number this transaction was in
blockId DATA, 36 bytes hash of the block this transaction was in + full shard id
data DATA data sent along with the transaction
from DATA, 20 bytes sender's address, NOT including fromFullShardKey
fromFullShardKey QUANTITY, 4 bytes sender's full shard key
toFullShardKey QUANTITY, 4 bytes recipient's full shard key
gas QUANTITY gas provided by the sender
gasPrice QUANTITY gas provided by the sender in Wei
gasTokenId QUANTITY the id of the gas token
transferTokenId QUANTITY the id of the transfer token
gasTokenStr STRING the symbol of the gas token
transferTokenStr STRING the symbol of the transfer token
hash DATA, 32 bytes hash of the transaction
id DATA, 36 bytes the full transaction id with the fromFullShardKey appended
networkId QUANTITY integer of the id of the network (e.g. devnet, mainnet)
chainId QUANTITY integer of the id of the chain
shardId QUANTITY integer of the id of the shard
nonce QUANTITY number of transactions made by the sender prior to this one
timestamp QUANTITY unix time of the block this transaction is in (bigint)
to DATA, 20 bytes recipient's address, NOT including toFullShardKey
transactionIndex QUANTITY integer of this transaction's index position in the block
v QUANTITY ECDSA recovery id
r DATA, 32 bytes ECDSA signature r
s DATA, 32 bytes ECDSA signature s
value QUANTITY value transferred in Wei

getTransactionReceipt

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getTransactionReceipt",
  "params": ["0x74bea8114c65bab71e24bf0c87499edfe17486de259954c2102c26aca597d5f90006c32e"],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "transactionId": "0x74bea8114c65bab71e24bf0c87499edfe17486de259954c2102c26aca597d5f90006c32e",
    "transactionHash": "0x74bea8114c65bab71e24bf0c87499edfe17486de259954c2102c26aca597d5f9",
    "transactionIndex": "0x0",
    "blockId": "0xe3da26573a8fe7e38c373df7e62aa5cd4da2ba628cf509c5bc9f8b877c4a428f00060001",
    "blockHash": "0xe3da26573a8fe7e38c373df7e62aa5cd4da2ba628cf509c5bc9f8b877c4a428f",
    "blockHeight": "0x281d6",
    "blockNumber": "0x281d6",
    "cumulativeGasUsed": "0x7530",
    "gasUsed": "0x7530",
    "status": "0x1",
    "contractAddress": null,
    "logs": []
  },
  "id": 1
}

Gets the receipt of a transaction.

Param Name Type Description
-- DATA, 36 bytes transaction id
Return Value Type Description
transactionId DATA, 36 bytes transaction id, same as what you passed in the request
transactionHash DATA, 32 bytes transaction id minus the full shard id = the hash of the transaction
transactionIndex QUANTITY integer of this transaction's index position in the block
blockId DATA, 36 bytes hash of the block this transaction was in + full shard id
blockHash DATA, 32 bytes hash of the block
blockHeight QUANTITY integer of the block number this transaction was in
blockNumber QUANTITY integer of the block number this transaction was in
cumulativeGasUsed QUANTITY total amount of gas used when this transaction was executed in the block
gasUsed QUANTITY amount of gas used by this transaction alone
status QUANTITY either 1 (success) or 0 (failure)
contractAddress DATA, 24 bytes address of the contract created, if there was a contract created
logs JSONR array logs of contract invocation, with same structure as in Ethereum

getLogs

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "getLogs",
  "params": [{
    "topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]
  }, "0x12345678"],
  "id": 1
}'

# Result
{
  "id":1,
  "jsonrpc":"2.0",
  "result": [{
    "logIndex": "0x1", // 1
    "blockNumber":"0x1b4", // 436
    "blockHeight":"0x1b4", // 436
    "blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d",
    "transactionHash":  "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf",
    "transactionIndex": "0x0", // 0
    "address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
    "recipient": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
    "data":"0x0000000000000000000000000000000000000000000000000000000000000000",
    "topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"]
    },{
      ...
    }]
}

Gets the logs with given filter.

Param Name Type Description
-- JSON object topic filter, same as eth_getLogs
-- QUANTITY full shard key

The response is the same as eth_getfilterchanges

call

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "call",
  "params": [
    {
      "from": "0x04E823bfD0EE5a05f072C346282e252e15CCa98D0007c32e",
      "to": "0xA21faADC19aEd9F34Cb7DAf75Ec451C538b75ca10007C53F",
      "gasPrice": "0x0",
      "gas": "0xf4240",
      "data": "0x70a0823100000000000000000000000004e823bfd0ee5a05f072c346282e252e15cca98d",
      "value": "0x0",
      "gasTokenId": "0x8bb0",
      "transferTokenId": "0x8bb0"
    },
    "latest"
  ],
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": "0x00000000000000000000000000000000000000000000c0b332e7b55d5cc00000",
  "id": 1
}

Executes the byte code on the blockchain without creating a transaction.

Param Name Type Description
Roughly the same as sendTransaction, except that full shard key is directly included in address (thus 24 bytes)
Return Value Type Description
-- DATA the return value of the executed contract

estimateGas

curl -X POST --data '{
"jsonrpc": "2.0",
"method": "estimateGas",
"params": [
  {
    "data": "0x",
    "from": "0x04E823bfD0EE5a05f072C346282e252e15CCa98D0006C32E",
    "gasTokenId": "0x8bb0",
    "to": "0x7CBb25b228D9719d7061c5c91E396F3f1a405A9c0001C53F",
    "transferTokenId": "0x8bb0"
  }
],
"id": 1
}'

# Result
{
    "jsonrpc": "2.0",
    "result": "0x7530",
    "id": 1
}

Estimates the gas usage of a transaction.

Param Name Type Description
Same as Call, while gas field is not needed
Return Value Type Description
-- QUANTITY the amount of gas used

gasPrice

curl -X POST --data '{
  "jsonrpc": "2.0",
  "method": "gasPrice",
  "params": ["0x0006C32E", "0x8bb0"],
  "id": 1
}'

# Result
{
    "jsonrpc": "2.0",
    "result": "0x2540be400", //10000000000
    "id": 1
}

Returns the current price per gas in wei on the specified chain/shard for the specified token (default to QKC if argument not provided).

Param Name Type Description
-- QUANTITY, 4 bytes full shard key, see Address section for more details
-- QUANTITY optional token ID, will default to QKC if not provided
Return Value Type Description
-- QUANTITY integer of the current gas price in wei

getRootBlockById

curl -X POST --data '{
    "jsonrpc": "2.0",
    "params": ["0x2a629116ab42c5856eaa73bc9a7ba4d81aeedf3810a64536f50b61d4276401e3"],
    "method": "getRootBlockById",
    "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "id": "0x2a629116ab42c5856eaa73bc9a7ba4d81aeedf3810a64536f50b61d4276401e3",
    "hash": "0x2a629116ab42c5856eaa73bc9a7ba4d81aeedf3810a64536f50b61d4276401e3",
    "height": "0x4b9",
    "idPrevBlock": "0x43e1f7803c27d4733a1f859b6322c0ec01b4456250e3673274aefe19ef053971",
    "hashPrevBlock": "0x43e1f7803c27d4733a1f859b6322c0ec01b4456250e3673274aefe19ef053971",
    "nonce": "0x0",
    "hashMerkleRoot": "0x9f8cffcea426dd7589dcc256e8f4d6916c18f29ca2f50498363fdac22495c845",
    "miner": "0x199bcc2ebf71a851e388bd926595376a49bdaa329c6485f3",
    "coinbase": [
      {
        "tokenId": "0x8bb0",
        "tokenStr": "QKC",
        "balance": "0x8fc3e4ad1a0ff0000"
      }
    ],
    "difficulty": "0x164ffb",
    "timestamp": "0x5b2a8d9e",
    "size": "0x1ddac",
    "minorBlockHeaders": [
      {
        "id": "0x80b8261dec92b2c2a33eb31e0c7c55387ef7583161bee84042696aadec9c0e7900050001",
        "height": "0x7b2f1",
        "hash": "0x80b8261dec92b2c2a33eb31e0c7c55387ef7583161bee84042696aadec9c0e79",
        "fullShardId": "0x50001",
        "chainId": "0x5",
        "shardId": "0x0",
        "hashPrevMinorBlock": "0x4621beafb7f56b2bfe6ef51783418757e3dca3716f5663af11bacdf19e4f4fbe",
        "idPrevMinorBlock": "0x4621beafb7f56b2bfe6ef51783418757e3dca3716f5663af11bacdf19e4f4fbe00050001",
        "hashPrevRootBlock": "0xc811deee2a7345f286132f221672c61bbdfae45aa0d7c069866037b9494f3609",
        "nonce": "0xfa1cf37c07150503",
        "difficulty": "0x9e9ff7458",
        "miner": "0xd786c575068c3d599739a7c11356361aa36389ae00050001",
        "coinbase": [
          {
            "tokenId": "0x8bb0",
            "tokenStr": "QKC",
            "balance": "0x2d1a51c7e0050000"
          }
        ],
        "timestamp": "0x5d1548ef"
      },
      …
    ]
  }
}

Get root block details by root block id.

Param Name Type Description
-- DATA, 32 bytes root block id
Return Value Type Description
id DATA, 32 bytes root block id (also the hash); they are the same since we don't have shard ids at the root block level
hash DATA, 32 bytes hash of the root block (also the id)
height QUANTITY integer of the root block number
idPrevBlock DATA, 32 bytes id of the previous block (same as hash)
hashPrevBlock DATA, 32 bytes hash of the previous block (same as id)
nonce DATA, 8 bytes hash of the generated proof-of-work
hashMerkleRoot DATA hash of the merkle root for this root block
miner DATA, 20 bytes address of the beneficiary to whom the mining rewards were given
coinbase JSON object coinbase tokens rewarded to the miner
difficulty QUANTITY integer of the difficulty for this block
timestamp QUANTITY unix time of the root block
size QUANTITY integer of the size of this block in bytes
minorBlockHeaders JSON array minor block headers included in this root block

getRootBlockByHeight

Get root block details by height.

Param Name Type Description
-- QUANTITY integer of the root block number. if not provided, will default to latest height
Return Value Type Description
Same as in getRootBlockById

getMinorBlockById

curl -X POST --data '{
  "jsonrpc": "2.0",
  "params": ["0x80b8261dec92b2c2a33eb31e0c7c55387ef7583161bee84042696aadec9c0e7900050001", false],
  "method": "getMinorBlockById",
  "id": 1
}'

# Result
{
  "jsonrpc": "2.0",
  "result": {
    "id": "0x80b8261dec92b2c2a33eb31e0c7c55387ef7583161bee84042696aadec9c0e7900050001",
    "height": "0x7b2f1",
    "hash": "0x80b8261dec92b2c2a33eb31e0c7c55387ef7583161bee84042696aadec9c0e79",
    "fullShardId": "0x50001",
    "chainId": "0x5",
    "shardId": "0x0",
    "hashPrevMinorBlock": "0x4621beafb7f56b2bfe6ef51783418757e3dca3716f5663af11bacdf19e4f4fbe",
    "idPrevMinorBlock": "0x4621beafb7f56b2bfe6ef51783418757e3dca3716f5663af11bacdf19e4f4fbe00050001",
    "hashPrevRootBlock": "0xc811deee2a7345f286132f221672c61bbdfae45aa0d7c069866037b9494f3609",
    "nonce": "0xfa1cf37c07150503",
    "hashMerkleRoot": "0xdaa77426c30c02a43d9fba4e841a6556c524d47030762eb14dc4af897e605d9b",
    "hashEvmStateRoot": "0xbad1c1f7b40d35b6e2e22a2821baafe79c754a8c075bb2d4907c8cd108023716",
    "miner": "0xd786c575068c3d599739a7c11356361aa36389ae00050001",
    "coinbase": [
      {
        "tokenId": "0x8bb0",
        "tokenStr": "QKC",
        "balance": "0x2d1a51c7e0050000"
      }
    ],
    "difficulty": "0x9e9ff7458",
    "extraData": "0x",
    "gasLimit": "0xb71b00",
    "gasUsed": "0x0",
    "timestamp": "0x5d1548ef",
    "size": "0x314",
    "transactions": []
  },
  "id": 1
}

Get shard block details by block ID.

Param Name Type Description
-- DATA, 36 bytes minor block id
-- BOOL true to return transactions with the minor block
Return Value Type Description
id DATA, 36 bytes minor block id (includes full shard id as last 4 bytes)
height QUANTITY integer of the minor block number
hash DATA, 32 bytes hash of the minor block
fullShardId QUANTITY integer of the full shard ID; see Address section for more details
chainId QUANTITY integer ID of the chain
shardId QUANTITY integer ID of the shard
hashPrevMinorBlock DATA, 32 bytes hash of the previous minor block
idPrevMinorBlock DATA, 36 bytes id of the previous minor block (includes full shard id)
hashPrevRootBlock DATA, 32 bytes id/hash of the root block it points to
nonce DATA, 8 bytes hash of the generated proof-of-work
hashMerkleRoot DATA, 32 bytes the merkle root for this minor block
hashEvmStateRoot DATA, 32 bytes the root of the evm state trie for this minor block
miner DATA, 20 bytes address of the beneficiary to whom the mining rewards were given
coinbase JSON object coinbase tokens rewarded to the miner
difficulty QUANTITY integer of the difficulty for this block
extraData DATA the "extra data" field of this block
gasLimit QUANTITY the maximum gas allowed in this block
gasUsed QUANTITY the total gas used by all transactions in this block
timestamp QUANTITY unix time of the root block
size QUANTITY integer of the size of this block in bytes
transactions JSON array list of the transactions in this block

getMinorBlockByHeight

curl -X POST --data '{
  "jsonrpc": "2.0",
  "params": [
    "0x50001",
    "0x7b2f1",
    false
  ],
  "method": "getMinorBlockByHeight",
  "id": 1
}'

Gets minor (shard) block details by shard and height.

Param Name Type Description
-- QUANTITY integer of the full shard ID; see Address section for more details
-- QUANTITY integer of the minor block number. if not provided, will default to latest height
-- BOOL true to return transactions with minor block
Return Value Type Description
Same as getMinorBlockById

getRootHashConfirmingMinorBlockById

curl -X POST --data '{
  "jsonrpc": "2.0",
  "params": [
    "0xab4b1d46c28d00bdc2cbe484440ed2f35715291a3bbca2b9bea09e1ff739012600000002"
  ],
  "method": "getRootHashConfirmingMinorBlockById",
  "id": 1
}'

Gets the root block that has included the minor block from the query.

Param Name Type Description
-- DATA, 36 bytes minor block id (hash+full_shard_id)
Return Value Type Description
-- DATA, 32 bytes id/hash of the root block that has included the minor block from the query

getTransactionConfirmedByNumberRootBlocks

curl -X POST --data '{
  "jsonrpc": "2.0",
  "params": [
    "0x1ff935396d9645aba36209b68f16aad3105f723a03c5c6468734c1be22a24c4700000000"
  ],
  "method": "getTransactionConfirmedByNumberRootBlocks",
  "id": 1
}'

Gets the root block that has included the minor block from the query.

Param Name Type Description
-- DATA, 36 bytes transaction id
Return Value Type Description
-- QUANTITY number of rootblocks that has confirmed the transaction; or None if the transaction has not been included by a minor block