Skip to main content

Getting and Sending Transactions with Celestia Node

In this tutorial, we will cover how to use the Celestia Node API to submit and retrieve messages from the Data Availability Layer by their namespace ID.

This tutorial was assumes you are working in a Linux environment.

To view a video tutorial for setting up a Celestia Light Node, click here

Hardware Requirements

The following minimum hardware requirements are recommended for running a light node:

  • Memory: 2 GB RAM
  • CPU: Single Core
  • Disk: 5 GB SSD Storage
  • Bandwidth: 56 Kbps for Download/56 Kbps for Upload

Setting Up Dependencies

First, make sure to update and upgrade the OS:

sudo apt update && sudo apt upgrade -y

These are essential packages that are necessary to execute many tasks like downloading files, compiling, and monitoring the node:

sudo apt install curl tar wget clang pkg-config libssl-dev jq build-essential git make ncdu -y

Install Golang

Celestia-app and celestia-node are written in Golang so we must install Golang to build and run them.

ver="1.19.1"
cd $HOME
wget "https://golang.org/dl/go$ver.linux-amd64.tar.gz"
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf "go$ver.linux-amd64.tar.gz"
rm "go$ver.linux-amd64.tar.gz"

Now we need to add the /usr/local/go/bin directory to $PATH:

echo "export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin" >> $HOME/.bash_profile
source $HOME/.bash_profile

To check if Go was installed correctly run:

go version

The output should be the version installed:

go version go1.19.1 linux/amd64

Celestia Node

Install Celestia Node

Installing celestia-node for Arabica Devnet means installing a specific version to be compatible with the network.

Install the celestia-node binary by running the following commands:

cd $HOME
rm -rf celestia-node
git clone https://github.com/celestiaorg/celestia-node.git
cd celestia-node/
git checkout tags/v0.5.0-rc5
make install
make cel-key

Verify that the binary is working and check the version with the celestia version command:

celestia version
Semantic version: v0.5.0-rc5
Commit: 039facd94104c741f8fa995e80f1321776ae4ad3
Build Date: Tue Nov 15 16:23:30 EST 2022
System version: amd64/linux
Golang version: go1.19.1

Instantiate Celestia Light Node

Now, let's instantiate a Celestia Light node:

Note: RPC Endpoints are exposed in all Celestia Node types such as Light, Bridge and Full Nodes.

celestia light init

Connect To A Public Core Endpoint

Let's now run the Celestia Light node with a GRPC connection to an example public Core Endpoint.

Note: You are also encouraged to find a community-run API endpoint and there are several in the Discord. This one is used for demonstration purposes. You can find a list of RPC endpoints here

celestia light start --core.ip <ip-address> --core.grpc.port <port> --gateway --gateway.addr <ip-address> --gateway.port <port>

NOTE: The --core.grpc.port defaults to 9090, so if you do not specify it in the command line, it will default to that port. You can use the flag to specify another port if you prefer.

For example, your command along with an RPC endpoint might look like this:

celestia light start --core.ip https://limani.celestia-devops.dev --core.grpc.port 9090 --gateway --gateway.addr localhost --gateway.port 26659

Keys and wallets

You can create your key for your node by running the following command:

./cel-key add <key_name> --keyring-backend test --node.type light

You can start your light node with the key created above by running the following command:

celestia light start --core.ip <ip-address> --core.grpc.port <port> --keyring.accname <key_name> --gateway --gateway.addr localhost --gateway.port 26659

Once you start the Light Node, a wallet key will be generated for you. You will need to fund that address with Arabica Devnet tokens to pay for PayForData transactions.

You can find the address by running the following command in the celestia-node directory:

./cel-key list --node.type light --keyring-backend test

If you would like to fund your wallet with testnet tokens, head over to the Celestia Discord channel #arabica-faucet.

You can request funds to your wallet address using the following command in Discord:

$request <Wallet-Address>

Where <Wallet-Address> is the celestia1****** address generated when you created the wallet.

With your wallet funded, you can move on to the next step.

Node API Calls

Open up another terminal window in order to begin querying the API. celestia-node exposes its REST gateway on port 26659 by default.

Balance

Now, let's query our node for the balance of its default account (which is the account associated with the developer key we generated earlier):

curl -X GET http://127.0.0.1:26659/balance

It will output the following:

{
"denom":"utia",
"amount":"999995000000000"
}

This shows you the balance in that wallet.

Get Block Header

Now, let's get the block header information.

Here we will get the header from Block 1:

curl -X GET http://127.0.0.1:26659/header/1

It will output something like this:

{
"header":{
"version":{
"block":11
},
"chain_id":"devnet-2",
"height":1,
"time":"2021-11-23T02:24:05.965728875Z",
"last_block_id":{
"hash":"",
"parts":{
"total":0,
"hash":""
}
},
"last_commit_hash":"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"data_hash":"7B578B351B1B0BBD70BB350019EBC964C44A140A37EF715B552A7F8F315ACD19",
"validators_hash":"7F4EA93A134DEDBDA6A1FDD30D05760DD98A2B5FBA95DB3EFFFE7FCE4B361855",
"next_validators_hash":"7F4EA93A134DEDBDA6A1FDD30D05760DD98A2B5FBA95DB3EFFFE7FCE4B361855",
"consensus_hash":"048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F",
"app_hash":"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"last_results_hash":"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"evidence_hash":"E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"proposer_address":"04881EB0A0A4C1DB414C708249CEEC2FCF348F3E"
},
"commit":{
"height":1,
"round":1,
"block_id":{
"hash":"4632277C441CA6155C4374AC56048CF4CFE3CBB2476E07A548644435980D5E17",
"parts":{
"total":1,
"hash":"BE1B789969938DB061B7723BE45C8A7B4B27192339A8E0A4E216775B2CB58D97"
}
},
"signatures":[
{
"block_id_flag":2,
"validator_address":"03F1044A6DF782189C7061FF89146B3D33608F17",
"timestamp":"2021-11-23T11:53:56.123958759Z",
"signature":"q/XF7Nc2ThcQgWfqi6LYOUEqLcU+sgVPY1nB2CLWdjRo80WwI6xy6QaYx1B0lmcKAkWR0YMxbc7vJzKF70qwBA=="
},
{
"block_id_flag":2,
"validator_address":"04881EB0A0A4C1DB414C708249CEEC2FCF348F3E",
"timestamp":"2021-11-23T11:53:56.036027188Z",
"signature":"0bbxeviCvgLlyIF47JoY1CMN2e/MhHtFzhdgV0zCM+P3qeO/rkh+0TSxoRVUB1MDvMCoA8hyffCw3amxympMAA=="
},
{
"block_id_flag":2,
"validator_address":"31711F367349D1BD619BD0A39568A69614B8A048",
"timestamp":"2021-11-23T11:53:56.135943844Z",
"signature":"gT23rZ8+XcG5rQ9QS+uh+Wn5eAiJDVy8bh23Fb8hevnHsuO1er2892MXAohaLRF6TTWs/C6dItYph4B/k3b6DQ=="
},
{
"block_id_flag":2,
"validator_address":"5A253EC2A9AB20AFD48C7BED2AFCA53F5C80BCA6",
"timestamp":"2021-11-23T11:53:56.081698742Z",
"signature":"nMngIlJ7PPPtu0N20YwKhWt/H3/JrEKJC3rnS5KG/8J3IppTacuwjGDUqIuHpRlrD0MmWa1mlY+6+ulbytt2AA=="
},
{
"block_id_flag":2,
"validator_address":"79BEB39F4B396F9278DA03F1C97F9BE3B10B12D3",
"timestamp":"2021-11-23T11:53:56.037896319Z",
"signature":"wPAL/sK4YXSU7iRXl00GDLvi4IItVlkY2zRkxIUeV9VA3Tq8Tke6wGE0N6pXKmtMcKUMoyjm03RWHv4mrtj1BA=="
},
{
"block_id_flag":1,
"validator_address":"",
"timestamp":"0001-01-01T00:00:00Z",
"signature":null
},
{
"block_id_flag":1,
"validator_address":"",
"timestamp":"0001-01-01T00:00:00Z",
"signature":null
},
{
"block_id_flag":2,
"validator_address":"D345D62BBD18C301B843DF7C65F10E57AB17BD98",
"timestamp":"2021-11-23T11:53:56.123499237Z",
"signature":"puj5Epw3yPGjSsJk6aQI74S2prgL7+cuiEpCxXYzQxOi0kNIqh8UMZLYf+AVHDQNJXehSmrAK6+VsIt9NF0DDg=="
},
{
"block_id_flag":2,
"validator_address":"DEC2642E786A941511A401090D21621E7F08A36D",
"timestamp":"2021-11-23T11:53:56.123136439Z",
"signature":"J/lnFqARXj42Lfx5MGY0FO/wug+AyQRxTnQp1u1HyczvV+0hXXuk06Uosi61jQKgJG6JBJF2VidqA41/uKMEDw=="
}
]
},
"validator_set":{
"validators":[
{
"address":"03F1044A6DF782189C7061FF89146B3D33608F17",
"pub_key":"sMcFgSIzlD77eZYgV7H4akyxoHCPc2oIQW05qWEB6b4=",
"voting_power":5000,
"proposer_priority":-40000
},
{
"address":"04881EB0A0A4C1DB414C708249CEEC2FCF348F3E",
"pub_key":"WdqZ8hoyc1HxZCJfQrAGKm2fFJZFg7PngPNGkA1RWXc=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"31711F367349D1BD619BD0A39568A69614B8A048",
"pub_key":"pvwSRksq3ekXIiYK7IzjQJ870BxLqEma8zRr9n9VnXI=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"5A253EC2A9AB20AFD48C7BED2AFCA53F5C80BCA6",
"pub_key":"RnmnTlKoKxNoh2TpohBDP3cKlx4ATiPOCvQFk/6xpUU=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"79BEB39F4B396F9278DA03F1C97F9BE3B10B12D3",
"pub_key":"oh/N+GOIennBOAa/gPNCso1mDlqaHQNn7Op/X8opbeY=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"7F1105B7B219481810C49730AECB1A83036BCA3A",
"pub_key":"Ow/AHP/Q3guPGymUKpvhnwae+QoCOpGztpVnP179IG8=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"87265CC17922E01497F40B701EC9F05373B83467",
"pub_key":"MNi0Z+uNF5X1Bxj988IDXVl0BKUcLs7LItoMnX6dbg4=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"D345D62BBD18C301B843DF7C65F10E57AB17BD98",
"pub_key":"4g3hhdyU4IIgWW/4sR0nax8bsC/M/fDbt1N8s/QanF8=",
"voting_power":5000,
"proposer_priority":5000
},
{
"address":"DEC2642E786A941511A401090D21621E7F08A36D",
"pub_key":"b+Vv6Lcp0bhIjOQncr+OYBHixCvU5+k34y4RqyvpluE=",
"voting_power":5000,
"proposer_priority":5000
}
],
"proposer":{
"address":"03F1044A6DF782189C7061FF89146B3D33608F17",
"pub_key":"sMcFgSIzlD77eZYgV7H4akyxoHCPc2oIQW05qWEB6b4=",
"voting_power":5000,
"proposer_priority":-40000
}
},
"dah":{
"row_roots":[
"//////////7//////////uyLCVMJmAItYqbOqgHXm3OwHsq1xQiAX1kZV2Tgcobm",
"/////////////////////ykyWNfDJZfigziZC5BN5L00KKuoyDPduwynDywauskL"
],
"column_roots":[
"//////////7//////////uyLCVMJmAItYqbOqgHXm3OwHsq1xQiAX1kZV2Tgcobm",
"/////////////////////ykyWNfDJZfigziZC5BN5L00KKuoyDPduwynDywauskL"
]
}
}

Submit a PFD Transaction

In this example, we will be submitting a PayForData transaction to the node's /submit_pfd endpoint.

Some things to consider:

  • PFD is a PayForData Message.
  • The endpoint also takes in a namespace_id and data values.
  • Namespace ID should be 8 bytes.
  • Data is in hex-encoded bytes of the raw message.
  • gas_limit is the limit of gas to use for the transaction

We use the following namespace_id of 0000010000000100 and the data value of f1f20ca8007e910a3bf8b2e61da0f26bca07ef78717a6ea54165f5.

You can generate your own namespace_id and data values using this useful Golang Playground we created here.

We run the following:

curl -X POST -d '{"namespace_id": "0c204d39600fddd3",
"data": "f1f20ca8007e910a3bf8b2e61da0f26bca07ef78717a6ea54165f5",
"gas_limit": 70000}' http://localhost:26659/submit_pfd

We get the following output:

{
"height":2452,
"txhash":"04A79AF9DA62FDB41ACD7D82EB0B9004AE4E4ED603B280A65816560B4F38A999",
"data":"12200A1E2F7061796D656E742E4D7367506179466F7244617461526573706F6E7365",
"raw_log":"[{\"msg_index\":0,\"events\":[{\"type\":\"message\",\"attributes\":[{\"key\":\"action\",\"value\":\"/payment.MsgPayForData\"}]},{\"type\":\"payfordata\",\"attributes\":[{\"key\":\"signer\",\"value\":\"celestia1vdjkcetnw35kzvtgxvmxwmnwwaaxuet4xp3hxut6dce8wctsdq6hjwfcxd5xvvmyddsh5mnvvaaq6776xw\"},{\"key\":\"size\",\"value\":\"27\"}]}]}]",
"logs":[
{
"msg_index":0,
"events":[
{
"type":"message",
"attributes":[
{
"key":"action",
"value":"/payment.MsgPayForData"
}
]
},
{
"type":"payfordata",
"attributes":[
{
"key":"signer",
"value":"celestia1vdjkcetnw35kzvtgxvmxwmnwwaaxuet4xp3hxut6dce8wctsdq6hjwfcxd5xvvmyddsh5mnvvaaq6776xw"
},
{
"key":"size",
"value":"27"
}
]
}
]
}
],
"events":[
{
"type":"coin_spent",
"attributes":[
{
"key":"spender",
"value":"celestia10jhckjxxymsufflglvypxscnmggetwh0gfasws",
"index":true
},
{
"key":"amount",
"value":"1utia",
"index":true
}
]
},
{
"type":"coin_received",
"attributes":[
{
"key":"receiver",
"value":"celestia17xpfvakm2amg962yls6f84z3kell8c5lpnjs3s",
"index":true
},
{
"key":"amount",
"value":"1utia",
"index":true
}
]
},
{
"type":"transfer",
"attributes":[
{
"key":"recipient",
"value":"celestia17xpfvakm2amg962yls6f84z3kell8c5lpnjs3s",
"index":true
},
{
"key":"sender",
"value":"celestia10jhckjxxymsufflglvypxscnmggetwh0gfasws",
"index":true
},
{
"key":"amount",
"value":"1utia",
"index":true
}
]
},
{
"type":"message",
"attributes":[
{
"key":"sender",
"value":"celestia10jhckjxxymsufflglvypxscnmggetwh0gfasws",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"fee",
"value":"1utia",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"acc_seq",
"value":"celestia10jhckjxxymsufflglvypxscnmggetwh0gfasws/267",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"signature",
"value":"JMNihnKS/MtYJDprqEFGJuXh16tVADsDDxXaFFpvv2te57btl4LbiRzwRRiN2rvwkJ2zlAApu2ImT22MZBi5+A==",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"fee",
"value":"",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"acc_seq",
"value":"celestia13zx48t96zauht0kpcn0kcfykc9wn8fehzcp9wq/1024",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"signature",
"value":"mIZIjbzN0/RQAlQN7TDWzqtey3vVBPe7IO3+IIDhJstIH8QU9vsHfl0Rql9qWMZQG4dM+77w9WmUcnCeS7edfw==",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"fee",
"value":"",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"acc_seq",
"value":"celestia1h36gnnwzneu0csqzn2waph5y983hf3dkaznlgz/0",
"index":true
}
]
},
{
"type":"tx",
"attributes":[
{
"key":"signature",
"value":"sfy+XyP7iWU+V9q3zEIOWxbGihvhzUKRLNVeXP+a+5oRefIA/Pyqfm13A5NU9I27hhfvpqo9vhXW1waRgcI9OA==",
"index":true
}
]
},
{
"type":"message",
"attributes":[
{
"key":"action",
"value":"/payment.MsgPayForData",
"index":true
}
]
},
{
"type":"payfordata",
"attributes":[
{
"key":"signer",
"value":"celestia1vdjkcetnw35kzvtgxvmxwmnwwaaxuet4xp3hxut6dce8wctsdq6hjwfcxd5xvvmyddsh5mnvvaaq6776xw",
"index":true
},
{
"key":"size",
"value":"27",
"index":true
}
]
}
]
}

If you notice from the above output, it returns a height of 2452 which we will use for the next command.

Note: To learn more about status response codes, please navigate to cosmos code explanation

Troubleshooting

If you encounter an error like:

$ curl -X POST -d '{"namespace_id": "c14da9d459dc57f5", "data": "4f7a3f1aadd83255b8410fef4860c0cd2eba82e24a", "gas_limit": 60000}'  localhost:26659/submit_pfd
"rpc error: code = NotFound desc = account celestia1krkle0n547u0znz3unnln8paft2dq4z3rznv86 not found"

It is possible that the account you are trying to submit a PayForData from doesn't have testnet tokens yet. Ensure the testnet faucet has funded your account with tokens and then try again.

Get Namespaced Shares by Block Height

After submitting your PFD transaction, upon success, the node will return the block height for which the PFD transaction was included. You can then use that block height and the namespace ID with which you submitted your PFD transaction to get your message shares returned to you. In this example, the block height we got was 2452 which we will use for the following command.

curl -X GET \
http://localhost:26659/namespaced_shares/0c204d39600fddd3/height/2452

Will generate the following output:

{
"shares":[
"DCBNOWAP3dMb8fIMqAB+kQo7+LLmHaDya8oH73hxem6lQWX1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
],
"height":2452
}

The output here is base64-encoded.