Client experience, completely rethoughte
Transparency and speed
New approaches to sales and risk management
Get the most of your IoT & M2M devices
Better tech for both online and offline educators
Safe deals, remote interaction

Power_api

Native interface for integration with the platform and network participants

API is used to effectively implement the enterprise's business processes and create a single-space trusted environment Designed for remote calling of trusted procedures during the interactions of various participants in a trusted network and integration with devices and applications

API features:
  • Reading and writing data in blocks
  • Blockchain node settings management
  • Work with transactions
  • Work with addresses
  • Status Checks
  • Reading blocks
  • IoT Support
1. Common Terms
In the first version of The Power API, users are expected to interact with The Power net. Basic functionality includes the ability to conduct transactions, operations with blocks and with the wallet. In the future, the functionality will be extended.

APIs that assumed only for browsing do not require authorization. All actions of users, as a result of which the state of the network could change, are performed in the form of transactions signed by the user's private key.

All interaction with the network occurs via http protocol with the help of GET or POST requests.
2. Cryptography
Before we start talking about API methods, there is a need to deal with cryptography issues. This document will give examples of work with cryptography using openssl. Many programming languages are suitable for working with this program, thus the presented examples could be transferred to these languages without any extra difficulties.

The following version of openssl is used for given examples:

+ openssl version
OpenSSL 1.1.0h 27 Mar 2018
2.1. Generating a Private Key
In order to generate a private key using openssl, you can use the following command:

+ openssl ecparam -name secp256k1 -genkey -text -out ./key.priv.pem

A file with your private key will be result of performing it. This private key can be used later to sign all your wallet transactions. Example of a file obtained with a private key:

+ cat ./key.priv.pem

ASN1 OID: secp256k1
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEID/VMb8FeEUT25fMlECFXFFmrlN2JyIaAq8wCurYix/LoAcGBSuBBAAK
oUQDQgAEc9EfjNOS77aPvokdhShEXfJinwQ3dOqZp9YOVdegIIXz0uYvt+VY08nG
0o2127zrMVETlRG4/qJT8zz1hOMBGA==
-----END EC PRIVATE KEY-----
2.2. Generating a public key
For signing any data or documents, having a private key is necessary. This key is the only way to perform any actions with the wallet that was created for it. Please, ensure security of your private key, making access to it as limited as possible.

A public key is required to verify the signature. This key is passed to The Power in the moment of wallet registration (process of its registration will be discussed later). This key is kept in the blockchain and can be accessed by anyone. To get the public key as a pair for your private key, please use the command:

+ openssl ec -in ./key.priv.pem -pubout -out ./key.pub.pem
read EC key
writing EC key
The result is a file with your public key. The contents of this file should look like this:

+ cat ./key.pub.pem
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEc9EfjNOS77aPvokdhShEXfJinwQ3dOqZ
p9YOVdegIIXz0uYvt+VY08nG0o2127zrMVETlRG4/qJT8zz1hOMBGA==
-----END PUBLIC KEY-----
2.3. Data Signature

echo 'test123' >textfile.txt
openssl dgst -sha256 -sign ./key.priv.pem -out ./sign.bin textfile.txt
openssl base64 -in ./sign.bin -out ./sign.txt
In the 10th row of this example, a "textfile.txt" file is created with the contents of test123 (on some operating systems this command could add a newline character). In the 11th row, the data is signed in the file "textfile.txt". The signature itself is written in binary form to the file sign.bin. In the 12th line, the binary file sign.bin is converted to base64 (for convenience of display, sign.bin with binary data will be used for signature verification).

Signature obtained:

+ cat ./sign.txt
MEUCIQDYso2HZkuQHw82FT8PtYa8Qf832tWLTk9KYfzUlxa0ZQIgLS6ljjr0y5Mj
SEwTQt5biOLb+dsLhbv4SxbTIQPeiO0=
2.4. Signature verification
To verify the signature, use the following command:

openssl dgst -sha256 -verify ./key.pub.pem -signature ./sign.bin ./textfile.txt
Verified OK
2.5. Full Example body

#! /bin/sh -x

openssl version
openssl ecparam -name secp256k1 -genkey -text -out ./key.priv.pem
cat ./key.priv.pem
openssl ec -in ./key.priv.pem -pubout -out ./key.pub.pem
cat ./key.pub.pem
echo 'test123' >textfile.txt
openssl dgst -sha256 -sign ./key.priv.pem -out ./sign.bin textfile.txt
openssl base64 -in ./sign.bin -out ./sign.txt
cat ./sign.txt
openssl dgst -sha256 -verify ./key.pub.pem -signature ./sign.bin ./textfile.txt

+ openssl version
OpenSSL 1.1.0h  27 Mar 2018
+ openssl ecparam -name secp256k1 -genkey -text -out ./key.priv.pem
+ cat ./key.priv.pem
ASN1 OID: secp256k1
-----BEGIN EC PARAMETERS-----
BgUrgQQACg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHQCAQEEIA8XwLgEqy+WW9shqLrT2zrp4B4kSqC7RA6QrQLyXltsoAcGBSuBBAAK
oUQDQgAEIBSsyL1UjQlmML9w7ecF6fhnEaQgqXkyrgjdhYXgcNovMeWwoIp+SxQv
jNgdaTCr/dq5IlznxMaoBlHnqwKS2A==
-----END EC PRIVATE KEY-----
+ openssl ec -in ./key.priv.pem -pubout -out ./key.pub.pem
read EC key
writing EC key
+ cat ./key.pub.pem
-----BEGIN PUBLIC KEY-----
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEIBSsyL1UjQlmML9w7ecF6fhnEaQgqXky
rgjdhYXgcNovMeWwoIp+SxQvjNgdaTCr/dq5IlznxMaoBlHnqwKS2A==
-----END PUBLIC KEY-----
+ echo test123
+ openssl dgst -sha256 -sign ./key.priv.pem -out ./sign.bin textfile.txt
+ openssl base64 -in ./sign.bin -out ./sign.txt
+ cat ./sign.txt
MEQCIGfvYyBggaT0f3B1GxNxbJnYXciSfJFgi5J5UaWx7TnVAiBAnFmgAj1R/kni
dcXQU+3MEiN67owdK2aIaTQpVRDHWA==
+ openssl dgst -sha256 -verify ./key.pub.pem -signature ./sign.bin ./textfile.txt
Verified OK
2.6. Wallet Import Format
The current implementation of the wallet stores keys in WIF format. Guidelines for working with this format can be found here: https://en.bitcoin.it/wiki/Wallet_import_format
2.7. Key Conversion to DER format
In order to register, you need to create a compressed public key (such a key that has the Y coordinate in its entirety and the parity of the X coordinate). This key occupies 33 bytes without a header and the first byte here is 2 or 3, depending on the parity of the X coordinate.

From the private key created by openssl we get the key with the following command:

openssl ec -in key.priv.pem -conv_form compressed -outform DER | dd bs=1 skip=53 > key.raw.bin
In this example, the dd removes the first 53 bytes of the data received from the openssl program (it skips ASN.1 header and writes only the key to file 'key.raw.bin'). The size of the 'key.raw.bin' file should be 33 bytes.
3. Addresses
Currently, addresses can be presented in two formats. One way of address presentation is created for being read by a person; in the future, we will call such a representation a textual representation or a textual format. However, inside of transactions, in the blockchain itself, etc. addresses can be presented differently. Another way of address presentation is binary one.

It is recommended to use the text representation of the address wherever the user is supposed to work with it (interface display of the address, or when user sends the transaction to this address, etc.).

Example of address in textual representation: AA100000001677722412

Example of an address in a binary representation in the form hex: 800140000100000B

Moreover, the addresses also can be public and private. Public addresses are available globally (then it is possible to make a transaction in another chain), and private addresses, which can be used only within a private chain.
3.1. Address structure in binary representation
The address is actually 8 bytes of binary data. While encoding the address or in various transformations associated with it, the location of the BigEndian bits is used, i.e. the highest bits of the address on the left, the least significant bits of the address on the right. In binary form, the bits will have the following values:

100GGGGG GGGGGGGG GGGBBBBB BBBBBBBB BBBBBBBB AAAAAAAA AAAAAAAA AAAAAAAA
or:

101BBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB AAAAAAAA AAAAAAAA AAAAAAAA
The three high-order bits indicate the type of the address. 100 - public address, 101- private. Any other value in the three most significant bits makes the address invalid. The remaining bits have the following meaning:

G - the public address group ID.

B - the identifier of the address block.

A - the wallet identifier in the block.

3.2. Converting an address from a text representation to a binary one
In the textual format, private addresses have a length of 18 characters while public addresses have 20 characters length. Moreover, they are also converted in different ways. If you want to choose proper algorithm for this transformation, first you need to define public or private address you are dealing with.


To do this, look at the length, 18 characters - private (example of private address: 00000000FE00007DF0), 20 characters - public (example of public address: AA100000001677722412).

We break the address into parts, each of which is converted into a binary form according to different rules. The public address consists of the following parts:

AADDLLLLLLLLLLLLLLCC
A — Letters of the Latin alphabet;

D — Digits, together AADD encode the group identifier;

L — Digits, in this part the identifiers of the addresses block and the identifiers of a wallet block are coded;

C — the lowest part of the address checksum (the last 2 digits of the checksum written in decimal form);


Let's look at how each part is coded. As already mentioned, the first 4 characters of the address in the text representation encode the identifier of the group, but the letters and digits are transformed according to different rules. The letters (the first 2 characters) represent a number in the 26-digit number system (ie A-0, B-1, C-2, ..., Z-25). Numbers (ie the next 2 symbols) are considered in the 10th notation. Example of calculating the group number for different addresses ( AA10 - group number 1010 (in decimal notation) or 10102 (in binary system), BD56 - group number 295610 or 1011100011002):
The following 14 characters encode the identifiers of the address and wallet blocks in the block. These characters should be considered as a number in the decimal number system; this number simply needs to be converted to a binary system.

Calculation example:

AA100000001677722412

                   decimal       bin
AA10            =  10         =  1010
00000016777224  =  16777224   =  1000000000000000000001000


100 00000   00000001   010 00000   00000000   00000001   00000000   00000000   00001000
  0x80        0x01        0x40       0x00       0x01       0x00       0x00       0x08
The remaining 2 characters are the checksum calculated by the CRC32 algorithm from the entire address.

Example of calculating CRC32 from our PHP address:

In our case, the address checksum in the decimal system will be 69322041210. In the example for clarity, the same checksum is presented in hexadecimal notation.
The last two digits of the checksum written in the decimal system will be 12. These characters are written in our address as a checksum, the checksum converges, the address is converted correctly.
3.3. Conversion of a private address
In the case of private addresses, the conversion looks much simpler. The textual representation of a private address can be schematically expressed by the following scheme:

HHHHHHHHHHHHHHHHCC
С — The checksum (in hexadecimal form, ie, characters 0-9, A-F)

H — hexadecimal digits (characters 0-9, A-F)

In order to get a binary representation of the private address, you need to discard the last two symbols of the checksum (in the diagram they are marked with the letter C), the remaining symbols (scheme shows them marked with the letter H) are converted as a hexadecimal number, the top three bits of this number need to be presented as 101 - the indicator which shows that this is a private address.

Example calculation:

Address: 00000000FE00007DF0

00000000FE00007D - address itself
F0 - checksum

It's needed to change high bits of address to 101 (this is a private address) and convert it to hexadecimal:
A0000000FE00007D
An example of calculating a checksum in PHP:
The two last symbols of the checksum in the hexadecimal representation of F0 are exactly the same as written for the address in the text representation from our example.
4. Working with the API
General provisions
Work with the API is supported by http protocol (in the future it is also planned to support https) using GET or POST requests (for different APIs different type of requests). Thus, it is possible for you to send data to the server in one of the following ways: in the address bar as one of the URL components or as a GET parameter (ie /url/param1 or /url/?param1=123). If the API accessed using method of the POST request, then the data is encoded in the json format and placed in the body of the request. A combination of both transfer methods is also possible. For different API data is transmitted in different ways, and for each specific endpoint information on how to pass arguments will be given.

The result of the query is always placed in the body of the response from the server in json format. There are several mandatory fields that will always be present in the response when it comes to certain situations.
5. Accounts
To request information about the state of the wallet, use the following API:
Examples of requests (curl is used to execute http requests and the jq program for highlighting the json syntax):
Description of the fields of the info block:
Conversion of a public key into PEM format (usually this format is used for work with the openssl) can be performed as follows (example in php language):

function der2pem($der_data, $type='PUBLIC KEY') {
    $der_data = hex2bin('3036301006072a8648ce3d020106052b8104000a032200') . $der_data;
    $pem = chunk_split(base64_encode($der_data), 64, "\n");
    $pem = "-----BEGIN ".$type."-----\n".
        trim($pem) .
        "\n-----END ".$type."-----\n";
    return $pem;
}
An example of work. The program converts the public key of one of the wallets to PEM format, and also loads this key for further work with openssl. Execution of openssl_pkey_get_public fails due to the key problem. The resource (4) of type (OpenSSL key) row at the end says that there were no errors, the key was correctly converted and openssl accepted this key for further work.
It is also possible to obtain a public key in PEM format. To do this, you must pass the GET parameter pubkey=pem:
6. MsgPack
Specification of the message pack format can be found here: https://github.com/msgpack/msgpack/blob/master/spec.md

There are libraries written in the most common languages.
You can download libraries from the official site: https://msgpack.org/

The following table provides information on how different types of data are encoded in the message pack.
7. Transactions
Any changes you want to make in the state of the blockchain can be done using transactions. There are two main types of transactions: registration transaction and generic (financial) transaction (sending token from one wallet to another). In the future, more types of transactions will be added.
7.1. Transaction related API description
Example of sending a transaction using curl (the transaction body has been shortened):

curl http://127.0.0.1/api/tx/new -d '{"tx":"g6R0eXBlo … 2MjI4X8TfA5gc"}'

7.2. Dive into transaction format
In order to make a new transaction, you should send an HTTP POST request to the server. Request data should be in JSON format and contain the key 'tx' with base64-encoded transaction container.
The transaction container is a MessagePack fixmap (first byte 0x80 - 0x8f) with the following structure:

{
  "body": BinaryBody (binary),
  "sig": Array (array of binary),
  "ver": 2 (unsigned integer)
}
The keys of this fixmap should be encoded as a string.

The value of the 'body' is a MessagePack binary (0xc4 the first byte) with MessagePack encoded transaction payload (we referring it as a transaction body).

The transaction body is a MessagePack map (0xde, 0x80-0x8f) with one mandatory key 'k' which value indicates transaction kind and other keys depending on transaction purpose.

For the best extendability transaction kind number is unique for each kind with each transaction version. Headers with constants should be generated by scripts from supplied JSON file (priv/tx_const.json):

{
  "purpose": {
    "0": "transfer",
    "1": "srcfee",
    "2": "dstfee",
    "3": "gas"
  },
  "kind": {
    "16": ["generic", 2],
    "17": ["register", 2],
    "18": ["deploy", 2],
    "19": ["patch", 2],
    "20": ["block", 2]
  }
}
The value of the 'sig' key is MessagePack array (types 0x90-0x9f or 0xdc-0xdc). Each array item contains signature for one key. Signature format (BSig) described below. A transaction might have multiple signatures.

The value of the 'ver' key is an integer, which indicates a version of transaction format to specify which body decoder should be used. As for now it has to be 2 (0x02 in MessagePack).
7.3. Registration Transaction
For registration of a new wallet there is the 'register' transaction type. As we mentioned before, the transaction body is MessagePack map (or fixmap) type. The first byte of this type is the 0xDE or from a range 0x80-0x8F.
Here is an example of registration transaction body content (shown as json, binary data represented as base64-encoded strings):

{
  "k": 0x11,
  "t": 1530106891372,
  "nonce": "T1umkWY=",
  "h": "Y6dVG5CvZacwlbf21oybiIHh/4h+8d2EJwF7Qp/GpCA=",
  "e": {}
}
The value of the 'k' key should always be 0x11 for registration transactions (MessagePack positive fixint type, 0x11).

The value of the 't' key is a transaction creation timestamp (unixtime in milliseconds, MessagePack uint 64 type, 0xcf).

The value of the 'nonce' key can be any type and should be used to change the transaction hash (see comment about difficulty below).

The value of the 'h' key is sha256 hash of concatenated public keys sorted ascending (MessagePack binary type, 0xc4).

The value of the 'e' key is user defined extra data included into transaction (MessagePack map or fixmap type, 0xde, 0x80-0x8f).
7.4. Example of calculating the value of the 'h' key
Let's take 3 arbitrary public keys (shown as json array, binary data represented as hex string):

[
  "025348F9AD2BDC8E394B7C3C69FDD221F8C7F95B458D56AACD677C4C9ABF8E1AE7",
  "0234326DF0BDF60DA3E6D203B73C0D0C4DEE518BD60717C3B20C0D27812C7DADEB",
  "02266C9DAA52F9BB5AD73B77A703437E27A3344F36F1D4FF0C0267C3DEA2BC91D7"
]
Please note, keys should be represented as binary data (i.e. for string 02 you should take 0x02 byte of binary data).

After sorting the keys we'll get the following order:

[
  "02266C9DAA52F9BB5AD73B77A703437E27A3344F36F1D4FF0C0267C3DEA2BC91D7",
  "0234326DF0BDF60DA3E6D203B73C0D0C4DEE518BD60717C3B20C0D27812C7DADEB",
  "025348F9AD2BDC8E394B7C3C69FDD221F8C7F95B458D56AACD677C4C9ABF8E1AE7"
]
After concatenation step we'll get the following data:

02266C9DAA52F9BB5AD73B77A703437E27A3344F36F1D4FF0C0267C3DEA2BC91D70234326DF0BDF60DA3E6D203B73C0D0C4DEE518BD60717C3B20C0D27812C7DADEB025348F9AD2BDC8E394B7C3C69FDD221F8C7F95B458D56AACD677C4C9ABF8E1AE7
The next step is calculating the sha256 hash of this data. Please note, we should deal with binary data (i.e. string E7 in the example should be byte 0xE7 of binary data). We calculate the hash of binary data, NOT the string of ASCII symbols.

For the data in this example the sha256 hash is

CB32960606B0E3846D763B8DA8FE5EF7379D89A227C2B6DBDA499F4ECEA0B071
7.5. PoW difficulty of the registration transaction
In order to prevent mass wallets registration, we require a PoW calculation for every registration transaction. In our case, the PoW means you should change the transaction data to get a sha512 hash which meets special requirements. These requirements usually called difficulty.

You can get the current difficulty of the shard by API call (GET) /api/settings. By this API call you'll get a JSON object. The value of the key settings.current.register.diff is the difficulty of this shard.

For example, if difficulty was 16 you should get a sha265 hash of the transaction with 16 leading bits of 0 (i.e. two leading bytes should be equal to 0). You should change the value of the 'nonce' key of the registration transaction to get a hash with 16 leading 0 bits.

Please note, the hash of the transaction body doesn't put in the transaction itself. In order to check if transaction meets the difficulty requirements or not, server recalculates the sha512 hash of the transaction body. As mentioned before, you should change the value of the 'nonce' key to get the transaction data with sha512 hash containing 'difficulty' of leading bits equal to 0.

Let's take the following transaction body (shown as JSON, binary value of the 'h' key shown as hex-encoded string):

{
  "k":17,
  "t":1541067579755,
  "nonce":0,
  "h":"957216f45873f7d09466610b887f1634359b000820bc91119e0efea70d2de64d"
}
Here is the hex dump of the MessagePack-encoded transaction body:

84a16b11a174cf00000166cec9216ba56e6f6e636500a168c420957216f45873f7d09466610b887f1634359b000820bc91119e0efea70d2de64d
The sha512 hash of this transaction body is

3890c8e314282271d4050d049adf70722210e4147551b76edfc74e2fb9977bbf
5ef41f4cc83d38144adc6bc52c93d3d1fb30473b043bf2f3b91c05dfcb6835a0
The first byte of the hash is 0x38 or 00111000 in binary format. This means the difficulty of preparation for this transaction body is 2 (hash has 2 leading 0 bits).

In case we changed the value of the 'nonce' key the hash of the transaction body would change.

Here is the same transaction but we've changed the value of the 'nonce' key to 210 (shown as JSON, binary value of the 'h' key shown as hex-encoded string):

{
  "k":17,
  "t":1541067579755,
  "nonce":210,
  "h":"957216f45873f7d09466610b887f1634359b000820bc91119e0efea70d2de64d"
}
Here is the hex dump of the MessagePack-encoded transaction body:

84a16b11a174cf00000166cec9216ba56e6f6e6365ccd2a168c420957216f458
73f7d09466610b887f1634359b000820bc91119e0efea70d2de64d
The sha512 hash of this transaction body is

0014e384d970d49feb87c476720f52942dc09ee086a57e2505a32a00b1747135
1872ea751e6b323c5d319a0fb5eb2f28c1fb2f8cad4e7d1b6ff8debbc52eb78f
The binary representation of the first two bytes of that hash is

00000000  00010100
  0x00      0x14
As you can see, this hash has 11 leading 0 bits, so the difficulty of preparation for this transaction body is 11.
7.6. BSig container and signature format
The BSig container is a binary data of TLV format (Tag - Length - Value).
Each signature may contain additional data, which is signed with main payload (body, data for sign).

Here are predefined fields.
The public key is mandatory. Every BSig should contain the public key tag.

Let's look at the signing procedure by an example.

Let's pretend that we have the private key 0102030405060708090001020304050607080900010203040506070809000102 and we want to sign the string 'Hello, world!'.

First of all we need to calculate public key, for this private key it'd be 02B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D7548B81064CB.

Also, we put the current timestamp into container.

Here is the binary data we have at this step:

02 21 02B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D7548B81064CB
01 08 00000164B250D800

tag 0x02 (public key), length of data 0x21, public key data
tag 0x01 (timestamp), length of data 0x08, current unixtime as microseconds in unsigned int 64 format
The next step is appending of data for signing to binary from the previous step.

# tag 0x02 (public key), length of data 0x21, public key data
02 21 02B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D7548B81064CB

# tag 0x01 (timestamp), length of data 0x08, current unixtime as microseconds in unsigned int 64 format
01 08 00000164B250D800

# 'Hello, world!' string added to the end of BSig container
48656C6C6F2C20776F726C6421
Here is the resulting binary for sign (shown as hexdump):

022102B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D
7548B81064CB010800000164B250D80048656C6C6F2C20776F726C6421
The sha256 hash of this whole binary will be 60C3B88A5F32816F574C8FABFB45A35338A20D7C1678F20DABDBBD7F94568F15.

At the next step we calculate signature of the hash from the previous step. The signature is

304402205250D827749F285CE174137EC88B394092E43B9E6C6774045EE5E6ED502322520
2204D1628F019E57BF19C1A0FE37193355A059F22CF8203D85E112FF3B4873D46FE
Please note, we always deal with binary data. You should sign the binary data of hash (NOT it's ASCII characters representation).

At the next step, we should remove the payload which we appended to container and prepend the container with the signature tag.

FF 46 304402205250D827749F285CE174137EC88B394092E43B9E6C6774045EE5E6ED5023225202204D1628F019E57BF19C1A0FE37193355A059F22CF8203D85E112FF3B4873D46FE
02 21 02B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D7548B81064CB
01 08 00000164B250D800

tag 0xFF (signature), length of data 0x46, binary data of signature (NOT it's ASCII)
tag 0x02 (public key), length of data 0x21, binary data of public key (NOT it's ASCII)
tag 0x01 (timestamp), length of data 0x08, current unixtime as microseconds in unsigned int 64 format
7.7. Generic transactions
(token transfer and/or smart contract call)
Token transfer and smart contract calling transactions must contain the following mandatory keys:

  • 'f' (from) - source address, must be 8 byte binary (0xc4 MessagePack type),
  • 'to' (to) - destination address, must be 8 byte binary (0xc4),
  • 's' (seq) - tx nonce, must be positive integer (0x00 - 0x7f or 0xcc - 0xcf)
  • 't' (timestamp) - tx unixtime in milliseconds, positive integer (0x00 - 0x7f or 0xcc - 0xcf),
  • 'p' (payload) - array of amounts (see below, 0xdc or 0x90 - 0x9f)
Also, there is a couple of optional keys:

  • 'c' (call) - for transaction intended to call smartcontract method. This attribute should contain 2 element array (0x92), the first element is the method name (string), the second is an array of arguments (arbitrary types, but tx call with incorrect types will be dropped by smart contract).

  • 'e' (extradata) - map with arbitrary extra data which might be used by smart contract or wallet application. The key 'code' is reserved for 'deploy' method and should not be used for any other purposes (types 0x80 - 0x8f or 0xde - 0xdf). In order to place some text or comment to transaction it's recommended to use the key with the name 'msg'.

Attribute 'p' (payload) is an array of 3 element arrays (0x93).

Here is an example of payload (shown as JSON format):


[
  [ purpose, "currency name", amount ],
  [ purpose, "currency name", amount ],
  [ 0x00, "SK", 10 ],
  [ 0x01, "SK", 3 ]
]
The first element is purpose (positive fixint, 0x00 - 0x7f) from JSON shown before.

The second element is the currency name (binary, 0xc4). If the currency name contains only ASCII characters with codes 32-126 you also can use the string type (0xa0 - 0xbf).

The third element is amount (integer, 0x00 - 0x7f, 0xcc - 0xcf). This field MUST be only the integer type. You CAN NOT use here the float type or any other type.

In case this array contains more than 3 elements, all extra elements should be ignored (it might be array generated by software with a newer version of the protocol, for example).

Clients MUST NOT add extra fields to payload array when creating a transaction, because it might break compatibility with new versions.

Here is an example of whole transaction (218 bytes, shown as base64 encoded binary):

g6Rib2R5xFCHoWsQoWbECIAAIAACAAADonRvxAiAACAAAgAABaFzzwAFeYouTBkw
oXTPAAABZstPb6ShcJKTAKJTSxGTAaNGRUUDoWWBo21zZ6VoZWxsb6NzaWeRxHb/
RzBFAiBSpsU9BM3tcsK+7lAFUdgOiHsZlvw90gwM9mKIMtMVvQIhAM4K0Qn6jgm8
2czyso2LupaosplS6eJ7Su2jpxMujOj7AiECsZEvq6gPzs0qZMV0/v5CLGEQYAHs
WIrxvZ11SLgQZMsBCAAAAWbLT2+ko3ZlcgI=
The same transaction shown as hex dump:

# 83 = fixmap of 3 elements
83

# body
a4 626f6479 c45087a16b10a166c4088000200002000003a2746fc408800020
            0002000005a173cf0005798a2e4c1930a174cf00000166cb4f6f
            a4a170929300a2534b119301a346454503a16581a36d7367a568
            656c6c6f

# sig
a3 736967   91c476ff473045022052a6c53d04cded72c2beee500551d80e88
            7b1996fc3dd20c0cf6628832d315bd022100ce0ad109fa8e09bc
            d9ccf2b28d8bba96a8b29952e9e27b4aeda3a7132e8ce8fb0221
            02b1912faba80fcecd2a64c574fefe422c61106001ec588af1bd
            9d7548b81064cb010800000166cb4f6fa4a

# ver
37 66572    02
The transaction container is a MessagePack fixmap (shown as JSON-like format, binary data shown as hex dump):

{
  "body":
      c45087a16b10a166c4088000200002000003a2746fc4088000200002000005a1
      73cf0005798a2e4c1930a174cf00000166cb4f6fa4a170929300a2534b119301
      a346454503a16581a36d7367a568656c6c6f,

  "sig":
      ff473045022052a6c53d04cded72c2beee500551d80e887b1996fc3dd20c0cf6
      628832d315bd022100ce0ad109fa8e09bcd9ccf2b28d8bba96a8b29952e9e27b
      4aeda3a7132e8ce8fb022102b1912faba80fcecd2a64c574fefe422c61106001
      ec588af1bd9d7548b81064cb010800000166cb4f6fa4,

  "ver": 2
}
Here is the transaction body with comments:

c450   # binary, length 0x50 bytes
87     # fixmap of 7 elements

# a1 = fixstr of 1 symbol, 6b = 'k' (this is the map key name), the value is 0x10
a16b10

# a1 = fixstr of 1 symbol, 66 = 'f', c408 = binary of 8 bytes,
# the value is 8000200002000003 (encoded AA010000003355443516 wallet address)
a166c4088000200002000003

# a2 = fixstr of 2 symbols, 746f = 'to', c408 = binary of 8 bytes,
# the value is 8000200002000005 (encoded AA010000003355443737 wallet address)
a2746fc4088000200002000005

# a1 = fixstr of 1 symbol, 73 = 's', cf = uint64,
# 0005798a2e4c1930 = 1541009272740144 = 2018-10-31 18:07:52.740144
a173cf0005798a2e4c1930

# a1 = fixstr of 1 symbol, 74 = 't', cf = uint64,
# 00000166cb4f6fa4 = 1541009272740 = 2018-10-31 18:07:52.740
a174cf00000166cb4f6fa4

# a1 = fixstr of 1 symbol, 70 = 'p', 92 = fixarray of 2 elements
a17092

# 93 = fixarray of 3 elements, 00 = 0 (transfer), a2 = fixstr of 2 symbols,
# 534b = 'SK', 11 = 0x11 = 17 (amount)
9300a2534b11

# 93 = fixarray of 3 elements, 01 = 1 (srcfee), a3 = fixstr of 3 symbols,
# 464545 = 'FEE', 03 = 3 (amount)
9301a346454503

# a1 = fixstr of 1 symbol, 65 = 'e', 81 = fixmap of 1 element
a16581

# a3 = fixstr of 3 symbols, 6d7367 = 'msg'
a36d7367

# a5 = fixstr of 5 symbols, 68656c6c6f = 'hello'
a568656c6c6f
Here is the sig value with comments:

# 91 = fixarray of 1 element
91

# c476 = binary of 0x76 bytes
c476

# below this point goes bsig

# ff47 = signature, length 0x47 bytes ( = 71 in decimal)
ff47

# 71 bytes of signature
3045022052a6c53d04cded72c2beee500551d80e887b1996fc3dd20c0cf6628
832d315bd022100ce0ad109fa8e09bcd9ccf2b28d8bba96a8b29952e9e27b4a
eda3a7132e8ce8fb

# 0221 = public key, length 0x21 bytes ( = 33 in decimal)
0221

# 33 bytes of public key
02b1912faba80fcecd2a64c574fefe422c61106001ec588af1bd9d7548b81064cb

# 0108 = timestamp, length 8 bytes,
# 00000166cb4f6fa4 = 1541009272740 = 2018-10-31 18:07:52.740
010800000166cb4f6fa4
8. Transactions example
Here are examples how to encode registration transaction v2 and money transfer transaction v2.

<?php

// some code for data encoding to messagepack format was taken from https://github.com/rybakit/msgpack.php


// constants of binary signature container tags
const TAG_TIMESTAMP = 0x01;
const TAG_PUBLIC_KEY = 0x02;
const TAG_CREATE_DURATION = 0x03;
const TAG_OTHER = 0xF0;
const TAG_PURPOSE = 0xFE;
const TAG_SIGNATURE = 0xFF;

const PURPOSE_TRANSFER = 0x00;
const PURPOSE_SRCFEE = 0x01;
const PURPOSE_DSTFEE = 0x02;
const PURPOSE_GAS = 0x03;

const KIND_GENERIC = 0x10;
const KIND_REGISTER = 0x11;
const KIND_DEPLOY = 0x12;
const KIND_PATCH = 0x13;
const KIND_BLOCK = 0x14;

// non-repeating increasing numbers generator
function get_nonce()
{
    list($usec, $sec) = explode(" ", microtime());

    return intval($sec.substr($usec, 2, 6));
}

// current time in milliseconds
function now()
{
    list($usec, $sec) = explode(" ", microtime());

    return intval(($sec + $usec) * 1000);
}

// convert key from der format (used by API) to pem format (used by openssl)
function der2pem($der_data, $type = 'PUBLIC KEY')
{
    if ($type == 'EC PRIVATE KEY') {
        $der_data = hex2bin('302e0201010420').$der_data.hex2bin('a00706052b8104000a');
    } else {
        $der_data = hex2bin('3036301006072a8648ce3d020106052b8104000a032200').$der_data;
    }

    $pem = chunk_split(base64_encode($der_data), 64, "\n");
    $pem = "-----BEGIN ".$type."-----\n".
        trim($pem).
        "\n-----END ".$type."-----\n";

    return $pem;
}

// encode non negative int to messagepack format
function encode_uint($uint)
{
    if ($uint < 0) {
        throw new Exception("uint must be non negative integer");
    }

    if ($uint <= 0x7f) {
        return \chr($uint);
    }
    if ($uint <= 0xff) {
        return "\xcc".\chr($uint);
    }
    if ($uint <= 0xffff) {
        return "\xcd".\chr($uint >> 8).\chr($uint);
    }
    if ($uint <= 0xffffffff) {
        return \pack('CN', 0xce, $uint);
    }

    return \pack('CJ', 0xcf, $uint);
}

// encode string to messagepack format
function encode_str($str)
{
    $length = strlen($str);
    if ($length < 32) {
        return chr(0xa0 | $length).$str;
    }
    if ($length <= 0xff) {
        return "\xd9".chr($length).$str;
    }
    if ($length <= 0xffff) {
        return "\xda".chr($length >> 8).chr($length).$str;
    }

    return pack('CN', 0xdb, $length).$str;
}

// encode binary to messagepack format
function encode_bin($str)
{
    $length = strlen($str);

    if ($length <= 0xff) {
        return "\xc4".chr($length).$str;
    }
    if ($length <= 0xffff) {
        return "\xc5".chr($length >> 8).chr($length).$str;
    }

    return pack('CN', 0xc6, $length).$str;
}

// return messagepack header of array of $size elements
function encode_array_header($size)
{
    if ($size <= 0xf) {
        return chr(0x90 | $size);
    }
    if ($size <= 0xffff) {
        return "\xdc".chr($size >> 8).chr($size);
    }

    return pack('CN', 0xdd, $size);
}

// return messagepack header of map of $size elements
function encode_map_header($size)
{
    if ($size <= 0xf) {
        return \chr(0x80 | $size);
    }
    if ($size <= 0xffff) {
        return "\xde".\chr($size >> 8).\chr($size);
    }
    return \pack('CN', 0xdf, $size);
}

// encode array of binary to messagepack format
function encode_bin_array($arr)
{
    $data = encode_array_header(sizeof($arr));
    foreach ($arr as $element) {
        $data .= encode_bin($element);
    }

    return $data;
}

// generic encode uint, string or array to messagepack format
function encode_generic($val)
{
    if (is_string($val)) {
        return encode_str($val);
    }

    if (is_integer($val) && $val >= 0) {
        return encode_uint($val);
    }

    if (is_array($val)) {
        return encode_array($val);
    }

    throw new Exception("Unsupported type: " . gettype($val));
}

// encode generic array of uints or strings
function encode_array($arr)
{
    $data = encode_array_header(sizeof($arr));
    foreach ($arr as $element) {
        $data .= encode_generic($element);
    }

    return $data;
}


// compute hash of array of keys
function hash_keys_array($keys)
{
    if (!is_array($keys)) {
        throw new Exception("Keys have a wrong type. You have to pass array of keys");
    }

    sort($keys);

    return hash('sha256', implode("", $keys));
}

// encode timestamp to put it in binary signature container
function tlv_add_timestamp($timestamp)
{
    $len = 8;

    return pack('CCJ', TAG_TIMESTAMP, $len, $timestamp);
}


// encode public key to put it in binary signature container
function tlv_add_pub_key($pub_key)
{
    $len = strlen($pub_key);

    if ($len > 0xFF) {
        throw new Exception("pub_key is too long");
    }

    if ($len < 1) {
        throw new Exception("invalid pub_key");
    }

    return pack('CC', TAG_PUBLIC_KEY, $len).$pub_key;
}

// encode signature to put it in binary signature container
function tlv_add_sign($sign)
{
    $len = strlen($sign);

    if ($len > 0xFF) {
        throw new Exception("signature is too long");
    }

    if ($len < 1) {
        throw new Exception("invalid signature");
    }

    return pack('CC', TAG_SIGNATURE, $len).$sign;
}

// sign transaction body
function sign_data($data, $options)
{
    $mandatory_options = ['pub_key', 'priv_key'];
    foreach ($mandatory_options as $option_name) {
        if (empty($options[$option_name])) {
            throw new Exception($option_name." option is missing");
        }
    }

    $priv_pem = der2pem($options['priv_key'], 'EC PRIVATE KEY');
    $priv_key_handle = openssl_pkey_get_private($priv_pem);

    if ($priv_key_handle === false) {
        throw new Exception("Can't import private key. Openssl error");
    }

    $container = [];

    foreach ($options as $option_name => $option_data) {
        switch ($option_name) {
            case 'pub_key':
                array_push($container, tlv_add_pub_key($option_data));
                break;
            case 'timestamp':
                array_push($container, tlv_add_timestamp($option_data));
                break;
            default:
                break;
        }
    }

    $meta_info = implode("", $container);
    if (openssl_sign($meta_info.$data, $sign, $priv_key_handle, OPENSSL_ALGO_SHA256) === false) {
        throw new Exception("Can't sign data. Openssl error");
    }

    return tlv_add_sign($sign).$meta_info;
}

// encode transaction body map to messagepack format
function encode_map($body, $types)
{
    $data = encode_map_header(sizeof($body)); // fixmap of sizeof($body) elements

    foreach ($body as $key => $value) {
        $data .= encode_str($key);

        if (!isset($types[$key])) {
            throw new Exception("Unknown type of key " . $key);
        }

        switch ($types[$key]) {
            case 'uint':
                $data .= encode_uint($value);
                break;
            case 'binary':
                $data .= encode_bin($value);
                break;
            case 'bin_array':
                $data .= encode_bin_array($value);
                break;
            case 'array':
                $data .= encode_array($value);
                break;
            case 'auto':
                $data .= msgpack_pack($value); // use external msgpack library to encode this type
                break;
            default:
                throw new Exception($types[$key]." is unsupported type of key ".$key);
                break;
        }
    }

    return $data;
}

// check difficulty for registration transaction
function is_difficulty_not_enough($data, $difficulty)
{
    if ($difficulty == 0) {
        return false; // false = difficulty is enough
    }

    $hash = hash('sha512', $data);
    $nibbles = intval($difficulty/4);

    for ($i=0; $i<$nibbles; $i++) {
        if ($hash[$i] != '0') {
            return true; // true = difficulty is not enough
        }
    }

    $last_nibble = unpack("C", pack("h",$hash[$nibbles]))[1];
    $bits_of_last_byte =  $difficulty - $nibbles*4;

    for($i=0; $i<$bits_of_last_byte; $i++) {
        if (($last_nibble >> (3-$i)) & 0x01 != 0) {
            return true; // true = difficulty is not enough
        }
    }

    return false; // false = difficulty is enough
}

// get data for registration transaction body in msgpack format
function registration_tx_body($public_keys, $difficulty)
{
    if (!is_array($public_keys)) {
        throw new Exception("You chose wrong type for 'keys'. You must pass array of public keys.");
    }

    $current_nonce = 0;

    $body = [
        "k" => KIND_REGISTER,
        "t" => now(),
        "nonce" => $current_nonce,
        "h" => hex2bin(hash_keys_array($public_keys)),
    ];

    $types = [
        "k" => "uint",
        "t" => "uint",
        "nonce" => "uint",
        "h" => "binary"
    ];

    $body_bin = encode_map($body, $types);

    while ( is_difficulty_not_enough($body_bin, $difficulty) ) {
        $current_nonce++;
        $body['nonce'] = $current_nonce;
        $body_bin = encode_map($body, $types);
    }


    return $body_bin;
}
// get data for generic money transfer transaction body in msgpack format
function money_transfer_tx_body($options)
{
    $mandatory_options = ['from', 'to', 'money'];
    foreach ($mandatory_options as $option_name) {
        if (empty($options[$option_name])) {
            throw new Exception($option_name." option is missing");
        }
    }

    $body = [
        'k' => KIND_GENERIC,
        'f' => $options['from'],
        'to' => $options['to'],
        's' => get_nonce(),
        't' => now(),
        'p' => $options['money'],
        'e' => [ 'msg' => 'hello']
    ];

    $types = [
        'k' => 'uint',
        'f' => 'binary',
        'to' => 'binary',
        's' => 'uint',
        't' => 'uint',
        'p' => 'array',
        'e' => 'auto'
    ];

    return encode_map($body, $types);
}

// pack and sign transaction
function pack_tx($packed_body, $keys)
{
    if (!is_array($keys)) {
        throw new Exception("You must pass array of keys.");
    }

    $sigs = [];

    foreach ($keys as $pub_key => $priv_key) {
        $options = [
            'pub_key' => $pub_key,
            'priv_key' => $priv_key,
            'timestamp' => now(),
        ];

        $sigs[] = sign_data($packed_body, $options);
    }

    $body = [
        'body' => $packed_body,
        'sig' => $sigs,
        'ver' => 2
    ];

    $types = [
        'body' => 'binary',
        'sig' => 'bin_array',
        'ver' => 'uint'
    ];

    return encode_map($body, $types);
}

// endpoint settings used in curlify_transaction
function get_endpoint_settings()
{
    return [
        'url' => 'http://127.0.0.1:49841',
        'new_tx' => 'tx/new'
    ];

}

// prints curl command with all nessesary parameter
function curlify_transaction($transaction)
{
    $data = json_encode(
        [
            "tx" => base64_encode($transaction),
        ]
    );

    $settings = get_endpoint_settings();
    printf("playground:\n");
    printf(
        "curl -s %s/api/playground/tx/validate -d '%s' | jq .\n\n",
        $settings['url'],
        $data
    );

    printf("apply transaction:\n");
    printf(
        "curl -s %s/api/%s -d '%s' | jq .\n\n",
        $settings['url'],
        $settings['new_tx'],
        $data
    );

}

// private key in der format
$priv_key = hex2bin('0102030405060708090001020304050607080900010203040506070809000102');

// public key in der format (as stored in blockchain)
$pub_key = hex2bin('02B1912FABA80FCECD2A64C574FEFE422C61106001EC588AF1BD9D7548B81064CB');


printf("## registration transaction:\n");

curlify_transaction(
    pack_tx(
        registration_tx_body([$pub_key], 10),
        [$pub_key => $priv_key]
    )
);

printf("\n\n");


$from = hex2bin("8000200002000003"); // AA010000003355443516
$to = hex2bin("8000200002000005");   // AA010000003355443737

$money = [
    [PURPOSE_TRANSFER, "SK", 17],
    [PURPOSE_SRCFEE, "FEE", 3],
];


printf("## money transfer transaction:\n");

curlify_transaction(
    pack_tx(
        money_transfer_tx_body([
            'from' => $from,
            'to' => $to,
            'money' => $money
        ]),
        [$pub_key => $priv_key]
    )
);
9. Block operations
Response

<pre>
{
    "block":
    {
        "bals": {...},
        "hash": "...",
        "child": "...",
        "header": {...},
        "outbound": [...],
        "settings": [...],
        "sign": [...],
        "txs": {...},
    },
    "result": "ok"
}
</pre>
Assignment of response fields:

  • "block" — An object containing information about a block
  • "bals" — An object containing information about the balance of the wallets affected by the transactions in the block;
  • "hash" — hash of the block;
  • "child" — hash of the next block in the blockchain. It may be absent if the current block is the newest in its own unit;
  • "header" — an object containing the block header;
  • "outbound" — Transactions to be transferred to other chains;
  • "settings" — patches on the configuration of the chain;
  • "sign" — array of signatures of the block;
  • "txs" — An object containing information about the transactions in the block.
Object "bals":
Response

    {
        "8001400002000001":
        {
            "amount": {...},
            "lastblk": "...",
            "seq": Х,
            "t": Х
        }
    }
"8001400002000001" - address of the wallet in the binary representation in the form of hex;

"amount" - an object that contains information about the balance of the wallet. The object fields are currency designations, and their values are the balanced in each wallet currency;

"lastblk" - hash of the last block, showing operations with this wallet;

"seq" is the last non-repeated sequential number of the outgoing transactions;

"t" is the timestamp in milliseconds.

The object containing the block header has the following structure:
Response

    { "balroot":"...",

    {
        "balroot":"...",
        "chain":Х,
        "height":Х,
        "ledger_hash":"...",
        "settings_hash":"...",
        "parent":"...",
        "txroot":"..."
    }
"balroot" - merkle tree root of wallet snapshots in the block (absent in the fields with no ledger);

"chain" - the number of the subchains;

"height" - block height;

"ledger_hash" is the root of the merkle tree ledger, which should be obtained AFTER deriving the transactions from the block (absent in the cells without ledger);

"settings_hash" is the merkle tree ledger root, which should be obtained AFTER applying patches to the configuration of the cell from the block (may be absent);

"parent" - the hash of the previous block in the blockchain;

"txroot" is the root of merkle tree transactions in the block;

Object "txs":
Response

    {
        "15190FBE2E428790-XUkvyU3JvUoMPyHEhkCKnsbD7jT-03":
            {
                "amount":Х,
                "cur":"...",
                "extradata":"{...}",
                "from":"...",
                "seq":Х,
                "sig": {...},
                "sigverify":
                    {
                        "invalid":Х,
                        "valid":Х
                    },
                "timestamp":Х,
                "to":"...",
                "type":"tx"
"15190FBE2E428790-XUkvyU3JvUoMPyHEhkCKnsbD7jT-03" - example of transaction identifier

"amount" - transaction sum;

"cur" - transaction currency;

"extradata" - arbitrary additional information added to the transaction;

"from" - address of the wallet of the sender for transaction;

"seq" is a non-repeating sequence number of the transaction originating from its sender;

"sig" is an object in which the public key of the wallet that created the transaction is used as the field title and the signature of this transaction as the field value;

"sigverify" - an object containing the number of invalid signatures in the invalid fields, and the number of valid signatures in valid fields;

"timestamp" - time-stamp for creating a transaction in milliseconds;

"to" - address of the wallet of the recipient of the transaction;

"type": "tx" is a transaction characteristic.

The array of signatures of the block contains objects with the following structure:

Response

    { "binextra": "...",
        "extra": {
          "pubkey": "...",
          "timestamp": Х,
          "createduration": Х
      },
    "nodeid": "...",
    "signature": "..."
    }
"extra" - additional information of the signing node (for example timestamp);

"binextra" - the same additional information in the original binary form (for verifying the signature);

"nodeid" - the identifier of the node that issued the signature (it is computed from pubkey);

"signature" - a signature.
10. API reference
"extra" - additional information of the signing node (for example timestamp);

"binextra" - the same additional information in the original binary form (for verifying the signature);

"nodeid" - the identifier of the node that issued the signature (it is computed from pubkey);

"signature" - a signature.
/status
Purpose: through this API you can find out your ip address. Request type: GET Response: client (string): ip client address Example of use:

% curl http://127.0.0.1:49841/api/status -s |jq
{
"client": "127.0.0.1",
"ok": true
}
/node/status
Purpose: the current status of the addressed node Request type: GET Response: status (object): An object with a report on the current work of the node Fields of the object status: blockchain (object): nodeid (string): node identifier public_key (string): public node key sync_peers (array of strings): identifiers of neighboring nodes with which communication is established ver (string): node software version

Example of use:

% curl http://127.0.0.1:49841/api/node/status -s |jq .
{
"result": "ok",
"status": {
"blockchain": {
"chain": 4,
"hash": "W91YU1ES85Z82j5zz2Hj9cXtfR0ckyhMW5gBpP№v45k=",
"header": {
"balroot": "NxwuY3kb2kIYtiqbjjXujgKPQsScdgONaqkAaPHF170=”, "chain": 4,
"height": 134,
"ledger_hash": "HRVRerlRWYM3rk9L4RA7KZX2YHWIN15dbyOp0FmMsxs=", "parent": "/lmFP73bpwU79UVUGYGnlDfW:v8qGK9j3oCGOPN0YX8=", "setroot": "x74U0qmRSg+kLQASxuxjx+9P+xx/vXgM9ThG9LIIN]g=", "txroot": "Ii/0ubdnnLMkVk724EGkd5n3YXnC3FaPNS5qmPxmHqk="
>
b
"nodeid": "287nRpYVitpiYzHbjyt7YefngcoC",
"public_key": ”AganOY4DcSMZ078U9tR9+p0PkwDzwnoKZH2SW17Io9Xb", "sync_peers": [
"28AFpshz4W4YD7tbLjliu4ytpPzQ",
"3NBx74EdmT2PyYexBSrg7xcht998"
],
"tpic_peers": [
{
"auth": "ok",
"node": "28AFpshz4W4YD7tbLjliu4ytpPzQ",
"state": "working"
{
"auth": "ok",
"node": "3NBx74EdmT2PyYexBSrg7xcht998",
"state": "working"
>
],
"ver": "v0.5.3-l-g3ff2986",
"xchaininbound": {},
"xchainoutbound": {}
"ok": true
>
/where/{address}
Purpose: the definition of chain belonging to address {address} (string): the address of the wallet in a textual or binary representation in the form of hex. Response: chain (integer): the number of the wallet related chain address (string): the address converted to a binary representation txtaddress (string): the address converted to a text representation Example of use:

% curl http://127.0.0.1:49841/api/where/0x8001400004000041 -s |jq
{
"chain": 4,
"result": "found",
"address": "0x8001400004000041",
"ok": true,
"txtaddress": "AA100000006710892962"
}
/address/{address}
Purpose: information about a wallet with a given address Request type: GET Input parameters: {address} (string): the address of the wallet in a text or binary representation in the form of hex. Response: info (object): An object with information about the current state of the wallet. address (string): the address converted to a binary representation txtaddress (string): the address converted to a text representation Fields of the info: amount (object): an object with the balances of this wallet in different currencies. If no operations have been performed, it may be empty lastblk (string): the hash of the block in which the last transaction made changes in this wallet, i.e. this is a link to its' last change preblk (string): hash of the previous block there the transaction that changed this wallet happened, ie. this is a link to the penultimate change of this wallet pubkey (string): public wallet key in DER format seq (integer): seq of the last successful transaction. In a new transaction, seq must be strictly greater than this number t (integer): the time of the last transaction that made changes to this wallet (the time of the last transaction with the purse). Time in microseconds.

Example of use:

% curl http://121.0.0.1:49841/api/address/0x8001400004000011 -s |jq .
{
"info": {
"amount": {
"FTT": 61306,
"SK": l
},
"lastblk": "550C89CAF76B6D075A5B1948F8D6D77C45C27E7E50BF885CD0AD77A5EC253EDD", 
"preblk": "17836B6466E7FB0D3BB3C9977D10CF4DEDE1981C35AB2E2D18B4834DB952D801", 
"pubkey": "036A21F068BE92697268B60D96C4CA93052EC104E49E003AE2C404F916864372F4", 
"seq": 1,
"t": 1528979142839,
"usk": 1
},
"result": "ok",
"address": "0x8001400004000011",
"ok": true,
"txtaddress": "AA100000006710888182"
}
/blockinfo/{hash}
Purpose: information about the block without transactions Request type: GET Input parameters: {hash} (string): the hash of the block for which display information is needed or the word last (last block) Response: Information about the assignment of fields is presented in the chapter "Operations with blocks" Example of use:

% curl http://127.0.0.1:49841/api/blockinfo/last -s |jq .
{
  "block": {
    "extdata": {
      "prevnodes": [
        "node_287nRpYV",
        "node_28AFpshz"
      ]
    },
    "hash": "5BD958525112F3967CDA3E73CF61E3F5C5ED7D139C93284C5B9801A4F366E399",
    "header": {
      "balroot": "371C2E63791BDA4218B62A9B8E35EE8E028F42C49C76038D6AA90068F1C597BD",
      "chain": 4,
      "height": 134,
      "ledger_hash": "1D15517ABD51598337AE4F4BE1103B2995F6607588375E5D6F23A9D0598CB31B",
      "parent": "FE59853FBDDBA7053BF545541981A7D437D47EFF2A18AF6326808638F374617F",
      "setroot": "C7BE143AA9914A0FA42D0012C6EC63C7EF4FFB1C7FBD780CF53846F4B2083498",
      "txroot": "222FCEB9B7679CB324564EF6E041A47799C96179C2DC568F352E6A98FC661EA9"
    },
    "outbound": [],
    "settings": {
      "aalloc": {
        "patch": [
          {
            "P": [
              "current",
              "allocblock",
              "last"
            ],
            "t": "set",
            "v": 65
          }
        ],
        "sig": []
      }
    },
    "sign": [
      {
        "_nodeid": "28AFpshz4W4YD7tbLjliu4ytpPzQ",
        "_nodename": "node_28AFpshz",
        "blnextra": "022102E8C7DB1B129CE0952799AD572ECC40F7027CD1049CA8215F43FD57E13E55FA",
        "extra": {
          "pubkey": "02E8C7DB1B129CE0952799AD572ECC40F7027CD1049CA8215F43FD57E13E55FA3F",
          "timestamp": 1530007642203,
          "createduration": 2690705
        },
        "signature": "3046022100C73B5838078D6C15B3726E36E328C3BB474BDD8C479C68932D4855598D074C70022100DF8DCF91D1E6DBA5F1769A6F4E15C05945956A588F4CB2CB8BF6B8D8A2B68167"
      },
      {
        "_nodeid": "287nRpWitpiYzHbjyt7YefngcoC",
        "_nodename": "node_287nRpYV",
        "extra": {
          "pubkey": "0206A7398E03712319D3BF14F6D47DFA9D0F9300F3C27A0A647D925A5EC8A3D5DB",
          "timestamp": 1530007642203,
          "createduration": 4786972
        },
        "signature": "3046022100DB94193056C30E8913B75C221CA5198698994D4E44894FABCFC6CBF33DC945FD022100C5976316966494BCC0CB8E40BA5A236FEA99B42AED784844F1BAEF75074C4753"
      }
    ],
    "txs_count": 1
  },
  "result": "ok",
  "ok": true
}
%|
/block/{hash}
Purpose: information about the block Request type: GET Input parameters: {hash} (string): the hash of the block for which display information is needed or the word last (last block) Response: Information about the assignment of fields is presented in the chapter "Operations with blocks"

Example of use:

% curl http://127.0.0.1:49841/api/blockinfo/last -s |jq .
{
"block": {
"bals": {
"8001400004000041": {
"amount": {},
"pubkey": "036A21F068BE92697268B60D96C4CA93052EC104E49E003AE2C404F916864372F4"
},
"A000000000000000": {
"amount": {
"FTT": 0,
"SK": 0
},
"lastblk": "FE59853FBDDBA7053BF545541981A7D437D47EFF2A18AF6326808638F374617F"
},
"extdata": {
"prevnodes": [
" node_287nRpW",
"node 28AFpshz"
],
"hash": "5BD958525112F3967CDA3E73CF61E3F5C5ED7D139C93284C5B9801A4F366E399",
"header": {
"balroot": "371C2E63791BDA4218B62A9B8E35EE8E028F42C49C76038D6AA90068F1C597BD",
"chain": 4,
"height": 134,
"ledgerjiash": "1D15517ABDS1598337AE4F4BE1103B2995F6607588375E5D6F23A9D0598CB31B",
"parent": "FE59853FBDDBA7053BF545541981A7D437D47EFF2A18AF6326808638F374617F",
"setroot": "C7BE143AA9914A0FA42D0012C6EC63C7EF4FFB1C7FBD780CF53846F4B2083498",
"txroot": "222FCEB9B7679CB324564EF6E041A47799C96179C2DC568F352E6A98FC661EA9"
},
"outbound": [],
"settings": {
"aalloc": {
  "patch": [
  {
    "p": [
      "current",
      "allocblock",
      "last"
      ],
    "t": "set",
    "v": 65
  }
  ],
  "sig": []
},

"sign": [
{
"_nodeid": "28AFpshz4W4YD7tbLjliu4ytpPzQ",
"_nodename": "node_28AFpshz",
"binextra": "022102E8C7DB1B129CE0952799AD572ECC40F7027CD1049CA8215F43FD57E13E55FA3F0108000001643B8FE05B03080000000000290E91",
"extra": {
"pubkey": "02E8C7DB1B129CE0952799AD572ECC40F7027CD1049CA8215F43FD57E13E55FA3F",
"timestamp": 1530007642203,
"createduration": 2690705
},
"signature": "3046022100C73B5838078D6C15B3726E36E328C3BB474BDD8C479C68932D4855598D074C70022100DF8DCF91D1E6DBA5F1769A6F4E15C05945956A5 88F4CB2CB8BF6B8D8A2B68167"
},
{
"_nodeid": "287nRpYVitpiYzHbjyt7YefngcoC",
"_nodename": "node_287nRpYV",
"binextra": "02210206A7398E03712319D3BF14F6D47DFA9D0F9300F3C27A0A647D925A5EC8A3D5DB0108000001643B8FE05B03080000000000490B1C",
"extra": {
"pubkey": "0206A7398E03712319D3BF14F6D47DFA9D0F9300F3C27A0A647D925A5EC8A3D5DB",
"timestamp": 1530007642203,
"createduration": 4786972
},
"signature": "3046022100DB94193056C30E8913B75C221CA5198698994D4E44894FABCFC6CBF33DC945FD022100C5976316966494BCC0CB8E40BA5A236FEA99B42AED784844F1BAEF75074C4753"
},
"txs": {
  "153BADD7D908919C-287nRpYVitpiYzHbjyt7YefngcoC-72": {
  "address": "8001400004000041",
  "extdata": {
    "origin": "node_287nRpYV"
  },
"pow": "54455354352031353330303037363430203533",
"register": "036A21F068BE92697268B60D96C4CA93052EC104E49E003AE2C404F916864372F4",
"timestamp": 1530007640,
"type": "register"
}
}
},
"result": "ok",
"ok": true
}
%|
/settings
Purpose: parameters of the current chain Request type:
GET Response: Information about the structure and purpose of the fields will change
4th generation
of DLT systems
We revolutionized the world of distributed registry platforms by creating the world's first three-tier blockchain with unlimited scalability without loss of data processing speed
Join to distributed world