Skip to main content

Run XPLA Blockchain Locally (Private)

In the XPLA blockchain, there's a Public Network open for anyone to join. It's called the Mainnet(dimension_37-1) and the Testnet(cube_47-5). However, exclusively developing on the Public Network has its limitations. Obtaining a significant amount of $XPLA for transaction fees can be challenging, and there might be times when you don't want to generate transactions publicly.

That's why we'll delve into running the XPLA blockchain on a Local (Private) Network. You can become a Single Validator yourself, operating a blockchain node and managing the total supply of $XPLA in the network. Through the Local Network, you can develop your very own Web3 game within the XPLA blockchain.

Index

We will explore Local Network in the following steps.

  1. Prerequisite

  2. Setting Up the Local Network

  3. Using xplad on the Local Network

  4. Making Use of the RPC Network

  5. Exploring with Swagger

  6. Creating Transactions on the Local Network with Javascript

Prerequisite

In the examples, Docker is used to simplify the setup of your development environment and assist in faster development. Please install Docker according to your operating system.

In this step, the key focus is on working with the Local Network, so you don't need an in-depth understanding of Docker. By following the steps below and entering the provided code, you can easily set up the Local Network.

Setting Up the Local Network

  1. Create a file named Dockerfile.

  2. Copy and paste the following code into the Dockerfile and save it. This Dockerfile streamlines the process of installing xplad. For more detailed information about xplad, refer to the Docs or Github.

    ########
    FROM golang:1.19 as builder

    RUN git clone https://github.com/xpladev/xpla.git ~/xpla

    RUN cd ~/xpla && \
    git checkout v1.2.0 && \
    make install && \
    mv /go/bin/xplad /usr/local/bin/xplad

    RUN cp /go/pkg/mod/github.com/!cosm!wasm/wasmvm@v1.0.0/api/libwasmvm.x86_64.so /usr/local/lib && \
    ldconfig

    ########
    FROM ubuntu:22.04 AS runner

    RUN apt-get update && \
    apt-get install -y tzdata && \
    ln -fs /usr/share/zoneinfo/Asia/Seoul /etc/localtime && \
    dpkg-reconfigure --frontend noninteractive tzdata

    RUN apt-get update && \
    apt-get install -y vim bash-completion wget sysstat dstat net-tools curl tmux jq dnsutils liblz4-tool pv git

    RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - && \
    apt-get install -y nodejs

    COPY --from=builder /usr/local/bin/xplad /usr/local/bin/
    COPY --from=builder /usr/local/lib/libwasmvm.x86_64.so /usr/local/lib/
    RUN ldconfig

  1. Building the Dockerfile will create a container image, and this might take some time to build.

    docker build -t my-xpla-node .

    Enter the docker image ls command to check whether the container image was successfully created.


  1. Create a docker container using the generated container image.

    docker run -it -d --name myXPLANode -p 26657:26657 -p 1317:1317 my-xpla-node

    While building the Local Network, we will also use the LCDClient and RPC networks. Since the LCDClient environment uses 1317 Port and the RPC network uses 26657 Port, each port was also opened. Afterwards, enter the docker ps -a command to check if the docker container was created successfully.


  1. Access the docker container via bash.

    docker exec -it myXPLANode bash
    tip

    To exit the bash in the connected container, simply type exit. If you want to access the container again, use the command docker exec -it myXPLANode bash. If the container isn't running, try docker start myXPLANode && docker exec -it myXPLANode bash.

    If you happen to miss a step while following the example, there's an option to reset by deleting and recreating the container. You can remove the container using the command docker stop myXPLANode && docker rm myXPLANode and then proceed again from Step 4.


  1. In the docker container's bash environment, input the following command. Similar to Mainnet's chain-id being dimension_37-1, in the example's Local Network, the chain-id is set to localnet_1-1. The variable yourMonikerName refers to the name of the node you're operating. Please input the desired name.

    xplad init --chain-id=localnet_1-1 yourMonikerName

    Upon inputting the above command, a .xpla folder will be created in the home directory (~), initializing the Genesis file.

    The structure of the ~/.xpla folder is as follows.

    .                                           # ~/.xpla
    |- data # Contains the databases used by the node.
    └- config/
    │-- app.toml # xplad configuration file
    │-- client.toml # configurations for the cli wallet (ex xplacli)
    │-- config.toml # Tendermint configuration file
    │-- genesis.json # genesis transactions
    │-- node_key.json # private key used for node authentication in the p2p protocol (its corresponding public key is the nodeid)
    └-- priv_validator_key.json # key used by the validator on the node to sign blocks
    What is a Genesis File?

    In the world of blockchain, the very first block that's created is called the Genesis block. The Genesis file is the record where all the data for this first block is stored. Every node participating in the same blockchain network needs to start block generation with the same Genesis file. As a result, right from the first block, they all share the same data, and the block hash values among nodes match.

    Both Mainnet and Testnet have their own Genesis files, and you can find them on Github. If you use the same Genesis file as the Mainnet, you can operate a Mainnet Full Node (a node storing all information of the blockchain). For detailed instructions on running Full Nodes for both Mainnet and Testnet, refer to the Docs.

    In this example, we're not dealing with Mainnet or Testnet but instead operating a Local Network. This is why we'll create a Genesis file directly.


  1. Generate a wallet to use as a Validator in the Local Network blockchain. Similar to the previous step, you're creating a wallet with the same command.

    xplad keys add yourAccount

    Make sure to enter the Passphrase correctly and store it along with your mnemonic. You'll need to input the Passphrase each time you use your wallet information.


  1. Record the information that the created wallet will receive 100000000000000000000axpla (100 XPLA) in the ~/.xpla/config/genesis.json file.

    xplad add-genesis-account $(xplad keys show yourAccount -a) 100000000000000000000axpla

    In the following Step 11, we'll set the inflation value to 0. This means that if we allocate 100 XPLA to one wallet in the Genesis block, the total supply of $XPLA in the Local Network will remain fixed at 100 XPLA. You're free to adjust the value of 100000000000000000000axpla to increase the amount of $XPLA available for use.


  1. Register the created wallet as a Validator. The initial 10000000000000000000axpla (10 XPLA) is the amount you'll Self-Delegate when registering as a Validator.

    xplad gentx yourAccount 10000000000000000000axpla --chain-id=localnet_1-1
    xplad collect-gentxs

    When you enter the first command, a gentx folder will be created in ~/.xpla/config. Entering the second command will apply the contents of the gentx folder to the genesis.json file

    What is a Delegate?

    The act of entrusting a certain amount of XPLA to a validator is called Delegate, and the person who entrusted it is called Delegator. In the Proof of State (PoS) type of XPLA blockchain, validators earn fees through block creation. Delegators can earn the fees that validators earn from block creation equal to the percentage of XPLA they each delegated.

    How often validators will create blocks is determined by the total amount of XPLA delegated to them. The higher the weight, the higher the block creation rate. For more details, see Docs.


  1. Currently, the genesis.json file has a non-zero inflation value. We'll change it to 0 to keep the total supply fixed without inflation. The actual XPLA blockchain Mainnet also has an inflation value of 0. You can find related information in the genesis file and Explorer. Details about the genesis file parameters can be found in the Cosmos documentation.

    sed -i "291s/0.130000000000000000/0.000000000000000000/g" ~/.xpla/config/genesis.json
    sed -i "296s/0.130000000000000000/0.000000000000000000/g" ~/.xpla/config/genesis.json
    sed -i "297s/0.200000000000000000/0.000000000000000000/g" ~/.xpla/config/genesis.json
    sed -i "298s/0.070000000000000000/0.000000000000000000/g" ~/.xpla/config/genesis.json

  1. Presently, the coin denomination in the genesis.json file is set as "stake". Since the XPLA blockchain uses "axpla" as its coin denomination, we'll adjust it.

    sed -i "s/"stake"/"axpla"/g" ~/.xpla/config/genesis.json

  1. Modify the app.toml and config.toml files to configure the LCDClient environment and RPC network connection.

    sed -i "112s/.*/enable = true/g" ~/.xpla/config/app.toml
    sed -i "115s/.*/swagger = true/g" ~/.xpla/config/app.toml
    sed -i "91s/127.0.0.1/0.0.0.0/g" ~/.xpla/config/config.toml

  1. Initialize the blockchain database according to the state set in the Genesis file.

    xplad tendermint unsafe-reset-all

  1. Use the command below to run the XPLA blockchain Local Network as a background process.

    xplad start &>/dev/null &

    If you'd like to check whether the background process is functioning properly, input ps -A.

    If you'd rather observe the process instead of running it in the background, omit &>/dev/null & and input xplad start only.


  1. Local Network setup is now complete! Use the command below to inspect the information of the running Local Network.

    xplad status

    If it's running well, you should roughly see an output similar to the following.

    {
    "NodeInfo": {
    "protocol_version": {
    "p2p": "8",
    "block": "11",
    "app": "0"
    },
    "id": "a6c8fcd8951c4697c893976ebd9a456e1dbd4faa",
    "listen_addr": "tcp://0.0.0.0:26656",
    "network": "localnet_1-1",
    "version": "v0.34.21",
    "channels": "40202122233038606100",
    "moniker": "yourMonikerName",
    "other": {
    "tx_index": "on",
    "rpc_address": "tcp://0.0.0.0:26657"
    }
    },
    "SyncInfo": {
    "latest_block_hash": "92A29DB190CF19A193E7009CFFD2A97CF450A3304D87C85C916B895515113602",
    "latest_app_hash": "D7E013D16B47901104F3DFFCE05861E291DB98C31617155C7BCBEB8F7E2D1D02",
    "latest_block_height": "43441",
    "latest_block_time": "2023-08-07T02:39:05.4921575Z",
    "earliest_block_hash": "E3118D0BE4CD0D437843A03EB86B5B6A1B8BC0749392BB44ED32B113BAFE20F7",
    "earliest_app_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
    "earliest_block_height": "1",
    "earliest_block_time": "2023-08-04T10:16:10.850891Z",
    "catching_up": false
    },
    "ValidatorInfo": {
    "Address": "BAE5CC7C2FB6467D0FA66BCEB01C6C8F470B0E8A",
    "PubKey": {
    "type": "tendermint/PubKeyEd25519",
    "value": "LyDR9u73BNZ+338l5L02FLi40HZ6cvqHhf5skPWVfHo="
    },
    "VotingPower": "10"
    }
    }

    The SyncInfo.latest_block_height value indicates the height of the latest block. This value will increase each time you execute the xplad status command. This suggests that blocks are successfully being added to the blockchain.

Using xplad on the Local Network

Let's try using xplad in the container's bash environment.

  1. Check Balance

    The XPLA blockchain is up and running on the Local Network. Let's start by checking the balance of the wallet created for the Validator.

    xplad query bank balances $(xplad keys show yourAccount -a)

    When you input the above command, you'll see results like the following.

    Enter keyring passphrase:
    balances:
    - amount: "90000000000000000000"
    denom: axpla
    pagination:
    next_key: null
    total: "0"

    100 XPLA were initially supplied in the Genesis block, and 10 XPLA were self-delegated when registering as a Validator. Therefore, having 90 XPLA left is normal.


  1. Check Delegated Amount

    When registering as a Validator, 10 XPLA were self-delegated. Let's check this using xplad.

    xplad query staking delegations $(xplad keys show yourAccount -a)

    You'll get results similar to the following. 10 XPLA were self-delegated.

    Enter keyring passphrase:
    delegation_responses:
    - balance:
    amount: "10000000000000000000"
    denom: axpla
    delegation:
    delegator_address: xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz
    shares: "10000000000000000000.000000000000000000"
    validator_address: xplavaloper1mcvhqcnjwry046rcys68hrvvefq7zvyvghggpl
    pagination:
    next_key: null
    total: "0"

  1. Create a Transfer Transaction

    Let's generate the first transaction on the Local Network. In this example, we'll create a transaction where a Validator wallet sends 1axpla to itself. You can try creating transactions transferring to other wallets you create.

    xplad tx bank send $(xplad keys show yourAccount -a) $(xplad keys show yourAccount -a) 1axpla --chain-id=localnet_1-1

    You'll get results like this. The transaction hash is F8B522E28918C6616136C1B1C70D3B5972F06CA8E80D9BD60B6B19704BC85E5C.

    Enter keyring passphrase:
    Enter keyring passphrase:
    Enter keyring passphrase:
    {"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz","to_address":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz","amount":[{"denom":"axpla","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}

    confirm transaction before signing and broadcasting [y/N]: y
    code: 0
    codespace: ""
    data: ""
    events: []
    gas_used: "0"
    gas_wanted: "0"
    height: "0"
    info: ""
    logs: []
    raw_log: '[]'
    timestamp: ""
    tx: null
    txhash: F8B522E28918C6616136C1B1C70D3B5972F06CA8E80D9BD60B6B19704BC85E5C

  1. Send a Transaction Query

    Let's send a query to the blockchain using xplad to retrieve the data of the transaction we created earlier. Replace the transaction hash with the one you generated. For example, the command for the example transaction would be xplad query tx F8B522E28918C6616136C1B1C70D3B5972F06CA8E80D9BD60B6B19704BC85E5C.

    xplad query tx <txhash>

By utilizing xplad, we've confirmed that the Local Network blockchain is functioning properly. For more xplad commands, refer to the Docs or try xplad -h command.

Making Use of the RPC Network

While setting up the Local Network, editing the ~/.xpla/config/config.toml file granted you the access to the RPC network. If you visit http://localhost:26657/, you'll see a list of APIs you can interact with through the RPC network. Clicking on //localhost:26657/genesis? will display a JSON result identical to the content of the ~/.xpla/config/genesis.json file you configured in the example.

Furthermore, you can also access the RPC network using WebSocket. Create a JavaScript file (.js), input the code below, and run it!

const { WebSocketClient } = require('@xpla/xpla.js');

const wsclient = new WebSocketClient('ws://localhost:26657/websocket');

wsclient.subscribe('Tx', {}, data => {
console.log('Send occured!');
console.log(data.value);
wsclient.destroy();
});


wsclient.start();

Running the JavaScript file alone won't yield any results yet. Go back to the docker container's bash environment and generate a transfer transaction. Once a transaction is created on the blockchain, you'll see the following log in the console where you ran the JavaScript file.

Send occured!
{
TxResult: {
height: '547',
tx: 'CokBCoYBChwvY29zbW9zLmJhbmsudjFiZXRhMS5Nc2dTZW5kEmYKK3hwbGExbWN2aHFjbmp3cnkwNDZyY3lzNjhocnZ2ZWZxN3p2eXZlMnRqd3oSK3hwbGExbWN2aHFjbmp3cnkwNDZyY3lzNjhocnZ2ZWZxN3p2eXZlMnRqd3oaCgoFYXhwbGESATESYQpZCk8KKC9ldGhlcm1pbnQuY3J5cHRvLnYxLmV0aHNlY3AyNTZrMS5QdWJLZXkSIwohA/hySCvp+biiZ4d7QMI0t9kyk46nCIMwjxGYk/OiIFA/EgQKAggBGAISBBDAmgwaQbdO3umo6oa0e4J3NKtNg+cZmzaC7ljFkxsER9/T7DB5NEsP1hj0pqQjbCy0fsQt/ej+N9Mu74uj2B7ggC2HX0wB',
result: {
data: 'Ch4KHC9jb3Ntb3MuYmFuay52MWJldGExLk1zZ1NlbmQ=',
log: '[{"events":[{"type":"coin_received","attributes":[{"key":"receiver","value":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz"},{"key":"amount","value":"1axpla"}]},{"type":"coin_spent","attributes":[{"key":"spender","value":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz"},{"key":"amount","value":"1axpla"}]},{"type":"message","attributes":[{"key":"action","value":"/cosmos.bank.v1beta1.MsgSend"},{"key":"sender","value":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz"},{"key":"module","value":"bank"}]},{"type":"transfer","attributes":[{"key":"recipient","value":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz"},{"key":"sender","value":"xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz"},{"key":"amount","value":"1axpla"}]}]}]',
gas_wanted: '200000',
gas_used: '82168',
events: [Array]
}
}
}

This demonstrates using WebSocket to access the RPC network and detecting the creation of a transaction on the blockchain. Check the Docs and Github for more diverse actions you can perform using WebSocket.

Exploring with Swagger

While setting up the Local Network, editing the ~/.xpla/config/config.toml file granted you the access to Swagger API.

Open your browser and go to the address http://localhost:1317/swagger/#/Query/AllBalances.

Click the Try it out button on the top right corner, and you can directly send a query. Input your created Validator wallet address in the "address" field and press the "Execute" button.

http://localhost:1317/swagger/#/Query/AllBalances
vaultimgcard

As shown in the example, you'll receive a response result.

{
"balances": [
{
"denom": "axpla",
"amount": "90000000000000000000"
}
],
"pagination": {
"next_key": null,
"total": "1"
}
}

Just like you confirmed with xplad, the Swagger API works well, showing that there's 90 XPLA in the Validator wallet.

Creating Transactions on the Local Network with Javascript

Lastly, let's create a transaction on the Local Network using JavaScript. Create a JavaScript file (.js), paste the code below, and give it a try.

const { LCDClient, MsgSend, MnemonicKey } = require("@xpla/xpla.js");

const lcd = new LCDClient({
chainID: 'localnet_1-1',
URL: 'http://localhost:1317'
});

async function main() {
const mk = new MnemonicKey({
mnemonic: 'sunny apology silly butter asset win own common margin festival write bullet coast envelope front affair depart struggle taste title liquid search deliver critic',
})

const from = lcd.wallet(mk).key.accAddress;
const to = "xpla1mcvhqcnjwry046rcys68hrvvefq7zvyve2tjwz";
const token = { axpla: 25 };

const signedTx = await lcd.wallet(mk).createAndSignTx({
msgs: [new MsgSend(from, to, token)],
});

const txResult = await lcd.tx.broadcastSync(signedTx);
console.log("Your Transaction Hash: " + txResult.txhash);
}
main()

After you get the resulting transaction hash, use xplad to search for it. You'll be able to retrieve the transaction data successfully.

The code above isn't significantly different from the code used to create transfer transactions on the testnet in the previous step. The main change is in the LCDClient's initial values. Only the chainID and URL values have been adjusted to match the Local Network. As a result, all the JavaScript code you've used so far can be seamlessly applied to the Local Network by just modifying the LCDClient's initial values.

Wrapping Up

So far, we've explored how to set up the XPLA blockchain Local Network. Now, with the Local Network at your disposal, you can experiment with various approaches within the XPLA blockchain and even dive into developing your own Web3 games.