Skip to content

Transaction Workflow Using CLI

  1. Run the node server and ensure the node is synced to the latest block.

  2. Start the HTTP Foreign Listener by using the command

    ./epic-wallet -p <user's wallet password> listen
    

    The above command gives this output:

    listenerResponse.png

  3. Use the below command to send Epic Cash to other wallets.

    ./epic-wallet -p <user's wallet password> send -d <receiver's address> <amount>
    

The above command will look like the following when used with a real address and amount.

    ./epic-wallet -p <user's wallet password> send -d https://h11a-49-805-39-262.ngrok-free.app 2
  1. For additional help and options use the following command:

    ./epic-wallet -p <user's wallet password> send -h
    
  2. Both the sender's and receiver's wallets should be actively listening, and their node servers must be fully synced. If both wallets' nodes are operational at the same time ,the transaction will be completed within two hours.

Transaction Workflow Using JavaScript

  1. Run the node server and ensure the node is synced to the latest block.

  2. Start the HTTP Owner Listener by using the command:

    ./epic-wallet -p <user's wallet password> owner_api
    

    The above command gives this output:

    ownerResponse.png

  3. Code Examples for JavaScript and Python to send Epic Cash to other wallets are given below.

    For the JavaScript code example:

    • In the line number 125, update value of the dest key with the receiver wallet's ngrok address.

    • In the line number 114, multiply the amount of Epic Cash you want to send with 10^8 and update value of the amount key with it. For example, we are sending 0.1 Epic Cash here, but the value of the amount key is 10000000.

    For the Python code example:

    • In the line number 225, update value of the dest key with the receiver wallet's ngrok address.

    • In the line number 214, multiply the amount of Epic Cash you want to send with 10^8 and update value of the amount key with it. For example, we are sending 0.1 Epic Cash here, but the value of the amount key is 10000000.

NodeJS and NPM package manager is required

npm i jayson
Sending Epic Cash code example
send_tx_example.js
/* Sample Code for connecting to the V3 Secure API via Node
 *
 * With thanks to xiaojay of Niffler Wallet:
 * https://github.com/epicfans/Niffler/blob/gw3/src/shared/walletv3.js
 *
 */

let password = ""; // your wallet pass
let port = "3420"; // :13420 = default floonet port, :3420 default mainnet port
let api_secret = ""; //`cat ~/.epic/main/.owner_api_secret` or `cat ~/.epic/floo/.owner_api_secret`

const jayson = require('jayson/promise');
const crypto = require('crypto');



const client = jayson.client.http('http://epic:'+ api_secret +'@127.0.0.1:' + port + '/v3/owner');

// Demo implementation of using `aes-256-gcm` with node.js's `crypto` lib.
const aes256gcm = (shared_secret) => {
    const ALGO = 'aes-256-gcm';

    // encrypt returns base64-encoded ciphertext
    const encrypt = (str, nonce) => {
        let key = Buffer.from(shared_secret, 'hex')
        const cipher = crypto.createCipheriv(ALGO, key, nonce)
        const enc = Buffer.concat([cipher.update(str, 'utf8'), cipher.final()])
        const tag = cipher.getAuthTag()
        return Buffer.concat([enc, tag]).toString('base64')
    };

    // decrypt decodes base64-encoded ciphertext into a utf8-encoded string
    const decrypt = (enc, nonce) => {
        //key,nonce is all buffer type; data is base64-encoded string
        let key = Buffer.from(shared_secret, 'hex')
        const data_ = Buffer.from(enc, 'base64')
        const decipher = crypto.createDecipheriv(ALGO, key, nonce)
        const len = data_.length
        const tag = data_.slice(len-16, len)
        const text = data_.slice(0, len-16)
        decipher.setAuthTag(tag)
        const dec = decipher.update(text, 'binary', 'utf8') + decipher.final('utf8');
        return dec
    };

    return {
        encrypt,
        decrypt,
    };
};

class JSONRequestEncrypted {
    constructor(id, method, params) {
        this.jsonrpc = '2.0'
        this.method = method
        this.id = id
        this.params = params
    }

    async send(key){
        const aesCipher = aes256gcm(key);
        const nonce = new Buffer.from(crypto.randomBytes(12));
        let enc = aesCipher.encrypt(JSON.stringify(this), nonce);
        //console.log("Encrypted: " + enc)
        let params = {
            'nonce': nonce.toString('hex'),
            'body_enc': enc,
        }
        let response = await client.request('encrypted_request_v3', params);

        if (response.err) {
            throw response.err
        }

        const nonce2 = Buffer.from(response.result.Ok.nonce, 'hex');
        const data = Buffer.from(response.result.Ok.body_enc, 'base64');

        let dec = aesCipher.decrypt(data, nonce2)
        return dec
    }
}

async function initSecure() {
    let ecdh = crypto.createECDH('secp256k1')
    ecdh.generateKeys()
    let publicKey = ecdh.getPublicKey('hex', 'compressed')
    const params = {
        'ecdh_pubkey': publicKey
    }
    let response = await client.request('init_secure_api', params);
    if (response.err) {
        throw response.err
    }

    return ecdh.computeSecret(response.result.Ok, 'hex', 'hex')
}

async function main() {
    let shared_key = await initSecure();

    let response = await new JSONRequestEncrypted(1, 'open_wallet', {
        "name": null,
        "password": password,
    }).send(shared_key);


    let token = JSON.parse(response).result.Ok;

    let sendtx_response = await new JSONRequestEncrypted(1, 'init_send_tx', {

        "token": token,
        "args": {
            "src_acct_name": null,
            "amount": "10000000",
            "minimum_confirmations": 3,
            "max_outputs": 500,
            "num_change_outputs": 1,
            "selection_strategy_is_use_all": true,
            "message": "my message - test",
            "target_slate_version": null,
            "payment_proof_recipient_address": null,
            "ttl_blocks": null,
            "send_args": {
                "method": "http",
                "dest": "https://1038-41-285-93-201.ngrok-free.app",
                "finalize": true,
                "post_tx": true,
                "fluff": false
              }
        }
    }

    ).send(shared_key);

    console.log(sendtx_response)  // Prints the response of init_send_tx method  

}

main();

If the transaction is successful, you will see a response similar to the following in your terminal.

Sending Epic Cash response example
send_tx_response_js.json
{
    "id": 1,
    "jsonrpc": "2.0",
    "result": {
        "Ok": {
            "amount": "10000000",
            "fee": "800000",
            "height": "1974026",
            "id": "dacaf05e-5c67-477a-a290-0919c78d4af5",
            "lock_height": "0",
            "num_participants": 2,
            "participant_data": [
                {
                    "id": "0",
                    "message": "my message - test",
                    "message_sig": "f869a73fb9dd14d496f073af3a9890adf0f4010e8be8567e843676f0712d7f1f0fe8c1d96d51d400088161bcd951686ebd179e019b43b321858ef93ceabe725a",
                    "part_sig": "60d5d49c224c973acecdd8d1689aec3f3c848069fff4439fc5125d5683be0055909e8c9311fc9fc2672a33a1f4b2312ccef39fa0e5c4194727797cf9d02a7e2f",
                    "public_blind_excess": "025378ff1e64e72f69a4fb9a35e0c9d36647d5255e4a9d45d85d3b6f712b91477a",
                    "public_nonce": "025500be83565d12c59f43f4ff6980843c3fec9a68d1d8cdce3a974c229cd4d560"
                },
                {
                    "id": "1",
                    "message": null,
                    "message_sig": null,
                    "part_sig": "1ba695ec3f16d669d52a14fa6a6eed196f826acaf9ce46037e6722cc45545c719d6e47bddb3d732010293f9c3d79083d2209aca55b0b8e53c00c52a5077fd74a",
                    "public_blind_excess": "035f8ab054e30fd642da9638c690613ca61cde8b6c7cc84b386fe4d2604fb39873",
                    "public_nonce": "02715c5445cc22677e0346cef9ca6a826f19ed6e6afa142ad569d6163fec95a61b"
                }
            ],
            "payment_proof": null,
            "ttl_cutoff_height": null,
            "tx": {
                "body": {
                    "inputs": [
                        {
                            "commit": "0854f3647921d5fd74e3c81859033ebbec96fc3e101169f3ade73edbcf49706ee6",
                            "features": "Plain"
                        }
                    ],
                    "kernels": [
                        {
                            "excess": "09a26f08543fa55afc15201165892c844236415d0541b35980d177f7264e7a2a5d",
                            "excess_sig": "add904cb9f103f2c9eab4480cd5391c0e91dac5c91ad6ea04318af3bb8c7e1952d0dd450ed3913e37753723d322c3a69f0fc4b4641d0a79ae785ce9ed8a9557a",
                            "features": "Plain",
                            "fee": "800000",
                            "lock_height": "0"
                        }
                    ],
                    "outputs": [
                        {
                            "commit": "091517a40cef5ebc3c4cffe19092f5d184584f89c66c779e3847323984bfdfe878",
                            "features": "Plain",
                            "proof": "9a4c842629020f2fae09b102b866b0580f85b25f2a55a067909b496b00761151105a00d931490bfc8476b700d07121ad1c81699cf120fb4d04b50a88bf889da6010aff4c58eec4f02df701ede19e28b6507548bb29d23bf8e0d47fec5659743297d39ce33b8e8f47de2ee08c90cea2db54a8649af8e470acccc9be1172fb3d187df4a80c10969ed7211c681d234963464511385c6cc8811b272e8d6f51403001b6896a24c330a4ec3baf2032f1d5a8b6b26d9d4f48e911c161d14feca95e5044b41959c32a83c1abd6f9bc71bd386b681766d59566aaeb068406af9aea6f6f7e456fb926d46e2a7fe84e87efab51bb10c93e1bb45803e97610fee4930f2c5692fbd9069569d8490d4ec111e567c3a0446ec082f5043bc86efa2be43b7ebe231991bda3417979098010092322e76cc6aa538cd2a631d36a4c34bf4b1bd861646e28836ea0d5a82347478781ec4abba29dd59b4cedb01c99cfdc7931b6929af3bb721e0333fff551309c5ee7291e46984fbe89245e8c3df4098ed9cf703202c555ed710be613e5d70d75ac25b900aeabbca2adc598335e1be03ecde650a248e73892f0630bd9a25f8a9796bbabeb7bae13712e90ffba7dbbe8d94dea11dbacd287482e9d89a82168c498d79e481cd563d51c907ed58b8aa4c4c6d0ee0adcadca0f9207e82aeaecaf1d34c4457caad8dada473fb2b37d572c35496ebc720747a4c252be36559fccc073da6ec0fbcf8f3d5ca47e63197cb90d9e73a6df74842ff2e2808db94076f38b5acb745dff20cb7629b84056cfa139ee12526108a3b0d8600ac2e29ab264a2fe4de36600251e00ead350bceec149f6195f1540eeade752b1ca5b4a92d4bfce8cdf3635180b045a3630ceb40eeaf7f8841a2d3dde714042658e96025d017f4d997b4a2a2263ae367ebf2d7e37fbf52a74109b868d6e96b0f9729ee5ce"
                        },
                        {
                            "commit": "09c1406847fee2aca2103b0438253b43bcfc628360928a1617cb7d43d192e601b6",
                            "features": "Plain",
                            "proof": "d1b14a845a61174646d33bbee43bdc672411e9b83854d28e64de31e7297a9eb66e11003885ac1bd7943e89e39fc143e07d2963e3b83feb0ee8e8c1df009cf99e0bbd29ef29b7e4755731595c29997301e22acca2096ac72b649a8379c37c12985d624add95d8c80eba6bd2c957d10c7c828a6617f26446123c5688396cda4c0f0e6ba87d55fd1cca30a666338882afe886f6f96a012fbed529789071654408dce115d68ab4a4bc254e16372e4a30c588317ef0f0c21b796424ebe5903c665433feecfa4623c1af118392a130b042e8675b90baedaa7c8f3b9e382d003242b50bc5794d56bc15c04a086d8dd5e74a172f0eb72141d073f2b3d8bd996ebe23bd24090e88be00bc50448c25891adc0efcc2cb38c3eb1474a956340b2878895d3efcbd029b27f8b38ee3e1a3bba0447e7443026d934fd596f8463a996b2b7d4755c1f9390ecb0505f1a44f1a5a4ff4ef0eb7835203e35fa1bef086d16b52c7aa527b706e02957853a4a4468feaba40848db1ab02d86409773239631f06d97c012938823ba5f3cd0bf785687290231cc8200078d2c2ca5f31ac5c62d407317d8a08e99f7dc1526c9f1077a874f4ec22161daaff93f4e857b55a164c2b2967532bf4e3a218a4c6d308fd50846bc486b5910c247bdcebb422453ee5dede4607afe3371b531468ddba77042894f0140142842f6032ce49a23f7857ca7b434707bbff60b6921ab029e911dd5b8160e8a1545e0b337af1d88144d7a7d8aef8a53cc933330aedabfc97ee211129c0ab8c4c91e54ecfaf60d4195d6bb6f4aec11f171ae9c2cb860124810419a76ad4987d4443209084941491f58cbe9522b2555033e3876a2d8a353f8245068236ccc013b28e3de4ae6ee25e8e17989be0ec372cbb7909f3827002472c02284058f8935245f914eacd6380261f3953b98eb8589472dd8fde8e9301ed"
                        }
                    ]
                },
                "offset": "e5f6e5ebb7bd83d41eed511764bbe27a4927f194d9f28da5d77b7e2dd3ac39d0"
            },
            "version_info": {
                "block_header_version": 6,
                "orig_version": 3,
                "version": 3
            }
        }
    }
} 

Requires Python 3.10+ and following packages:

python3 -m pip install coincurve pycryptodome requests
Sending Epic Cash code example
send_tx_example.py
from typing import Union
import base64
import json
import os

from coincurve import PublicKey, PrivateKey
from Crypto.Cipher import AES
import requests


# DEFAULT VALUES
api_url = f"http://127.0.0.1:3420/v3/owner"
auth_user = 'epic'
owner_api_secret_path = f"{os.environ['HOME']}/.epic/main/.owner_api_secret"
wallet_password = ""

with open(owner_api_secret_path, 'r') as f:
    owner_api_secret = f.read()

basic_auth = (auth_user, owner_api_secret)


def parse_api_response(response: Union[dict, requests.Response]):
    """
    Parse EPIC API responses, handle different errors
    and extract the data from different response formats.
    """
    if isinstance(response, requests.Response):
        if response.status_code not in [200, 201]:
            if response.status_code == 401:
                raise SystemExit("Unauthorized to access API")
            else:
                raise SystemExit(f"Error: {response.status_code}, {response.reason}")
        try:
            response = response.json()
        except ValueError as e:
            raise SystemExit(f"Error while reading api response: '{str(e)}'\n"
                             f"Make sure your auth credentials are valid.")

    if "error" in response:
        raise SystemExit(f'{response["error"]}')

    elif "Err" in response:
        raise SystemExit(f'{response["result"]}')

    elif 'Ok' in response['result']:
        return response['result']['Ok']

    else:
        return response


def init_secure_api() -> str:
    """
    This is the first step in epic-wallet Secure API workflow
    Initialize process of computing encryption_key to encrypt payloads
    :return: encryption key
    """

    # Randomly created encryption key valid during the session
    secret_key = PrivateKey(os.urandom(32))

    # Prepare payload for the API call
    payload = {
        'jsonrpc': '2.0',
        'id': 1,
        'method': "init_secure_api",
        'params': {'ecdh_pubkey': secret_key.public_key.format().hex()}
        }

    # POST your secret_key.public_key and receive new api_public_key
    response = requests.post(api_url, json=payload, auth=basic_auth)
    api_public_key_hex = parse_api_response(response)

    # Parse received api_public_key from hex to bytes
    api_public_key_bytes = PublicKey(bytes.fromhex(api_public_key_hex)).format()

    # Compute new encryption_key used for further encryption every api_call in this session
    encryption_key_ = PublicKey(api_public_key_bytes).multiply(secret_key.secret)

    # Format to hex and remove first 2 bits
    encryption_key_ = encryption_key_.format().hex()[2:]
    print(f"✅  Encryption key successfully generated")

    return encryption_key_


def encrypt(key: str, payload: dict) -> dict:
    """
    :param key: 32bit `secp256k1` ecdh encryption key computed via init_secure_api() func
    :param payload: json payload to encrypt
    :return: dict with base64 encoded AES-256-GMC encrypted payload and nonce as hex string

    Encrypt api_call JSON payload with:
     - encryption_key
     - 12bit nonce,
     - 16bit tag
    """
    nonce = os.urandom(12)
    message = json.dumps(payload).encode()
    aes_cipher = AES.new(bytes.fromhex(key), AES.MODE_GCM, nonce=nonce)
    ciphertext, tag = aes_cipher.encrypt_and_digest(message)
    encrypted_params = {'nonce': nonce.hex(), 'body_enc': base64.b64encode(ciphertext + tag).decode()}

    return encrypted_params


def decrypt(key: str, data: dict, nonce: bytes) -> str:
    """ Decrypt base64 encoded string
    :param key: 32bit `secp256k1` ecdh encryption key computed via init_secure_api() func
    :param data: encrypted message
    :param nonce: 12bit nonce as hex string
    :return: decoded string with JSON response
    """
    data = base64.b64decode(data)
    ciphertext = data[:-16]
    aesCipher = AES.new(bytes.fromhex(key), AES.MODE_GCM, nonce=nonce)
    plaintext = aesCipher.decrypt(ciphertext)

    return plaintext.decode()


def secure_api_call(key: str, method: str, params: dict):
    """
    Execute secure `owner_api` call, payload is encrypted
    :param key: 32bit secp256k1 ecdh encryption key computed via init_secure_api() func
    :param method: api call method name
    :param params: dict with api_call params
    :return: dict with decrypted data
    """

    payload = {
        'jsonrpc': '2.0',
        'id': 1,
        'method': method,
        'params': params
        }

    # Encrypt payload with computed encryption key
    encrypted_payload = encrypt(key, payload)

    # Execute owner_api call with encrypted payload
    payload = {
        'jsonrpc': '2.0',
        'id': 1,
        'method': 'encrypted_request_v3',
        'params': encrypted_payload
        }

    encrypted_response = requests.post(
        url=api_url,
        json=payload,
        auth=basic_auth
        )

    encrypted_response = parse_api_response(encrypted_response)

    # Decrypt response and return dict with response data
    nonce = bytes.fromhex(encrypted_response['nonce'])
    encrypted_response = encrypted_response['body_enc']

    decrypted_response = decrypt(
        encryption_key,
        encrypted_response,
        nonce
        )

    return parse_api_response(json.loads(decrypted_response))


def open_wallet(password, key) -> str:
    """
    This is the second step in epic-wallet API workflow
    Make an `open_wallet` API call, get authentication token and use it
    in all calls for this wallet instance during this session.
    """

    open_wallet_params = {
        'name': 'default',
        'password': password,
        }

    response = secure_api_call(
        key=key,
        method='open_wallet',
        params=open_wallet_params
        )

    print(f"✅  Secure token successfully generated")
    return response


"""
In the example below we will use defined functions to generate secure token 
and retrieve wallet balance. Different API endpoint will use different params
but the workflow will be the same.
"""

# Call `init_secure_api` API endpoint to initialize Secure API workflow,
# and generate encryption_key used to encrypt data payload
encryption_key = init_secure_api()

# Call `open_wallet` API endpoint to generate authentication token
token = open_wallet(
    password=wallet_password,
    key=encryption_key
    )

# Prepare `retrieve_summary_info` API call params
info_params = {
    "token": token,
        "args": {
        "src_acct_name": None,
        "amount": "10000000",
        "minimum_confirmations": 3,
        "max_outputs": 500,
        "num_change_outputs": 1,
        "selection_strategy_is_use_all": True,
        "message": "my message",
        "target_slate_version": None,
        "payment_proof_recipient_address": None,
        "ttl_blocks": None,
        "send_args": {
            "method": "http",
            "dest": "https://7f88-49-002-32-25.ngrok-free.app",
            "finalize": True,
            "post_tx": True,
            "fluff": False
        }
    }
}    

# Call `retrieve_summary_info` endpoint and print the result
send_tx_response = secure_api_call(
    key=encryption_key,
    method='init_send_tx',
    params=info_params)

print(json.dumps(send_tx_response))

If the transaction is successful, you will see a response similar to the following in your terminal.

Sending Epic Cash response example
send_tx_response_py.json
{
    "amount": "10000000",
    "fee": "800000",
    "height": "1979603",
    "id": "01740886-bbff-4b7b-9796-41cf2cb74df0",
    "lock_height": "0",
    "num_participants": 2,
    "participant_data": [
        {
            "id": "0",
            "message": "my message",
            "message_sig": "4e2482734ed9d43ea092c02412078f98e10fb1382ae6682bed7311017a3065b7bcab3faca231a775576831ebb97c8d21c421924c31dd332697311ceb8ba81ff8",
            "part_sig": "958ddf5a2c0becedb75480d18301238f7006bd88902623fa889a8dce611825ddddb4b8232f6e70a7d07f53aaa1c62512a97f65fb622459b1eb532796eacd85e3",
            "public_blind_excess": "03fbe1484b37bf395a396ade6e4f6ac3cff98b1601db7983e2a723b71109f61956",
            "public_nonce": "02dd251861ce8d9a88fa23269088bd06708f230183d18054b7edec0b2c5adf8d95"
        },
        {
            "id": "1",
            "message": null,
            "message_sig": null,
            "part_sig": "fd46c43ccc42c96ed4d1b85e3482e89a215b77f25f4db4ab74046daee2a19dc3ed4157b335bce8ccb8023a3484c28c65589c2963d7b50f6bca0c6f6586a7125b",
            "public_blind_excess": "03ca9a42982b82692c672be27876482f22cc5a471377751aa79addaeb585db1cd6",
            "public_nonce": "02c39da1e2ae6d0474abb44d5ff2775b219ae882345eb8d1d46ec942cc3cc446fd"
        }
    ],
    "payment_proof": null,
    "ttl_cutoff_height": null,
    "tx": {
        "body": {
            "inputs": [
                {
                    "commit": "094026bd2ffbb32ca84b41e0a4b19607c69fbdb4d4d9ef667d19c92c084ff0d721",
                    "features": "Plain"
                }
            ],
            "kernels": [
                {
                    "excess": "09e8653eb45df78084cfe4ba868f3e7aba0c5f5a9e1ee624ad69e5aeefdc66c459",
                    "excess_sig": "24444dbd104749709ce29f8de620b78f8da693c8c937d411db86b7f7e81ea2e389b5d906d8cb86b44de2442f3fac03bd021c8f5e3ada681cb66096fb7075983e",
                    "features": "Plain",
                    "fee": "800000",
                    "lock_height": "0"
                }
            ],
            "outputs": [
                {
                    "commit": "09d658336c5403a07670682511b6e72fc8a32c1f3717aff2264eafdd11d6985179",
                    "features": "Plain",
                    "proof": "e5cd651b8889e747bd255e456ce4db5cb319323794aee208c38ac9407468927fee50a6a3cba132a65df1e7674bedc2abe776708028c771159cfbf52daf9cb7d10de1e171c2e3abfaad5c599903a0f05640f6664757c18ee132a1130a3b5f2293fd5e0ee5c9b772bf542e2c00fd300bdab26cbcbf6bb91534b36e32e6be1f8e43b59a88c18cbe5062c7c344c2aaccbd4ca7350cd17ee37fdee860dd090fc547eea376fd0a6609bca7bc4bb6ddd044f79dfb9df45a44f709853666b878785aaec29b634440a1de28c09976310e30a11bf4701a5cddafad254f0129c0499684d595840ac126d6e6f252f611219beb9d5cbc22f3ab5b3e39ead8698585ce73721d7b890e5bd8ad8df71eb49b64130eb29f854534caa48bfc62e9d2c5682e9ed287015e10b0da9da34eb1aaa2c7a81b61ce921d13c105a700dad08eb8a17f782aafdcacf0050ce4e9e01aaab2d38108d09c78b25522a88afab8286accf1acafb8266276fc015fec7bf8b2e68d48cc3f449795b640a396dea7a248855d23e709cc23948d16472090d9a2c08135176538bb199ac620abff1749dbfabf0f726ad83a8c4ab84cedf42a8a781681b3fb2b3231992236227c7bc4c3d0125bafe096b6ebd2544e3b362fd4af7ea4050e7ccec1c6d5eab136cc622ab888967935bdb795a060750f4e26ae80b5dbca28a6e4d7847abea01a76c2d457e18891787ff13f8c8053f316db4c41a4734442d57792d06041976fadc2d24e66680816aaef07a5c30e82da8d9aa9b95bd78ce61d1b23950c446f46e941b16e9761e391ac9a996d19e7e3b001eca29a0eff712fda54f8b803226097cdc04e4879bbc9d4f25ac2368320c084b0ad4657552b4750e0b63c2f9a312669013ef16906ad41f762f22c871443f07587d9d64bcac372d5b535e961cff07be24616e089abdb3cb82eaa1dc7c2324a657acb71"
                },
                {
                    "commit": "09611534a8a7157292fc3b6a87402b7af935783784805820430812428f4174eecf",
                    "features": "Plain",
                    "proof": "ff15aa11d280cdb11fd3d5e603ca9d78100d85385af5e39b78a880e1d06f7462b8b2f58dddf4cc32aa3b557e62d7ea296f7d49fa2e2f3ccfd61f03092e8ae4430907990de86bcba9913f5393839ad433aa29a3be21248f7e0e6df6b42bc1c70b2e159cb95733d383cfe986853f8fbf37838bc538610eb2c46c320450004593a8a0624f6b07bf6211cace8656a66197c4aacba33c79650177802e82309ad17098e0f6125535e214f77ec307da1832b47b1ff84c0824706e5462389fcc2cdb2c91b31b5545c5443ac4d7df6d7cd9bc55a555e3936e0fd94df040b823ad5e43b60fd72f52c9e88590fc4f6d765b19bb15c811a262685a6d62cb5af0b6607d8d0a45c2c997684e20b976c753a41b24658fd963de925868ebeb94e640ab3e328167b04cab361af689f6a806911f6343c68ba50c3c07e592b4b7ab6140da096692ecde0e4db03afbdb8fc4786fbdc30cf929141fca81c49f1df05dcd4df6099c5f1cf57bb3031604c048344c7a485170116a038a6dd97f12304c2904d67586dd574f35ab63aa2f0f06fa4310139c60b3a24b93856a982611af461c19572f7397b42fe6e46ad1859dee7c6b9a829db395385df60835db81dd331f27b635f201da337f0da532935a4a940f0d986b00fe87f3390cfb86bef546e4af2c5cbc7a9dfb8617074d9cf8cc725ad5dd52b0f1f045520292503740e62e863072298f55f06274e7d4a201cb8c50759b73ae1d30a3cd89bfb4613e029495cf42838d3eebbbcc5fc821f6964e561765158a1e8ea824cdcfbbea1947fb988bc8230e198964ff3636a15b6e148ffe94838fb99f06d8294ab631278e7644d59b9e6676d4ea2c8da8845b921e493f8dba3ebfa7777a48bb383ac1f1381858aac7bd94155457793bb983f1d5dea432683179f81386628864376e72173c2ab965cb490121f43f92f2e8458fbf8041e1"
                }
            ]
        },
        "offset": "9bd9865b92fe4392906b8326c1083ce72ab3ae1fdd0b6f8e298e178eacada903"
    },
    "version_info": {
        "block_header_version": 6,
        "orig_version": 3,
        "version": 3
    }
}