Skip to content
LogoLogo

Getting started: from Mocha to Mainnet Beta

Start on Mocha, the test network. Move to Mainnet Beta when your integration works on Mocha.

1. Choose how to integrate

OptionMax blob sizeUse it when
celestia-node JSON-RPC (fibre.Submit, fibre.Download)Just under 12 MiBYou already run a light or bridge node and use JSON-RPC
celestia-node Go client (client.New in api/client)128 MiB minus 5 bytesYou write Go and want node-style APIs without running a node
celestia-app Go package (fibre)128 MiB minus 5 bytesYou need full control over upload and settlement

The JSON-RPC limit is lower because the node caps each request body at 16 MiB, including base64 and JSON overhead. See Larger blobs and the native client.

All three options use the same Fibre client underneath. A light or bridge node checks validator sets against headers it has verified itself. The Go options trust the core endpoint you connect to.

2. Set up a key

  • The key that signs payment promises owns the escrow. Payments are taken from that key's escrow account.
  • The key must be a secp256k1 key in a Cosmos SDK keyring.
  • The same key normally signs the MsgPayForFibre transaction. With the node API, you choose it with key_name or signer_address in the transaction options.
  • Back up the recovery phrase. Losing the key means losing access to the escrow funds.

3. Fund the wallet and the escrow

You need two balances:

BalancePays forHow to fund it
WalletGas for deposits and MsgPayForFibre transactionsA normal transfer. On Mocha, use the faucet.
EscrowFibre storage chargesA deposit from the wallet

Deposit with the node API (fibre.Deposit), as shown in Query and deposit escrow, or with celestia-appd:

celestia-appd tx fibre deposit-to-escrow <amount>utia --from <key_name>

Check the escrow:

celestia-appd query fibre escrow-account <account_address>

The response has two balances:

  • balance is the total held in escrow.
  • available_balance is what remains after pending withdrawals.

Uploads are checked against available_balance. 1 TIA is 1,000,000 utia.

The native Go client can top up escrow automatically (Escrow.AutoFund). This is off by default and only works with fibre.Put.

4. Estimate the cost

Each blob is charged:

charge (utia) = 650,000 + 45,000 × ceil(upload_size / 262,144)

upload_size is the padded size, not your file size. Work it out like this:

  1. row_size = ceil((data_length + 5) / 4096), rounded up to a multiple of 64.
  2. upload_size = row_size × 4096.

The smallest possible upload_size is 262,144 bytes (256 KiB). So every blob costs at least 695,000 utia.

Payloadupload_sizeCharge
14 bytes262,144 B0.695 TIA
10 MiB10,747,904 B2.495 TIA
128 MiB minus 5 bytes134,217,728 B23.69 TIA

These match the verified Mocha results. The settlement transaction's gas is paid separately from the wallet.

The charge is a fixed formula in utia. It does not depend on gas prices. The formula's numbers are constants in celestia-app, not governance parameters. They are the same on Mainnet Beta and Mocha, and change only with a network upgrade.

5. Upload and download

With the node JSON-RPC API

Follow the tested walkthrough: Submit and retrieve a Fibre blob on Mocha. It covers node setup, auth tokens, escrow, submitting, and checking the downloaded bytes.

The core calls are:

MethodWhat it does
fibre.SubmitUploads, collects signatures, settles on chain, and waits for confirmation. Use this first.
fibre.UploadUploads and collects signatures, then settles in the background. Settlement errors only appear in node logs.
fibre.DownloadDownloads a blob by blob ID
fibre.QueryEscrowAccount, fibre.Deposit, fibre.Withdraw, fibre.PendingWithdrawalsEscrow management

With the celestia-app Go package

This is the quickstart from the package README. Put uploads, settles and waits for confirmation in one call.

cfg := fibre.DefaultClientConfig()
cfg.StateAddress = "<core_grpc_address>"
cfg.DefaultKeyName = "<key_name>"
 
client, err := fibre.NewClient(kr, cfg)
if err != nil { return err }
if err := client.Start(ctx); err != nil { return err }
defer client.Stop(ctx)
 
// The tx client signs and broadcasts MsgPayForFibre.
txClient, err := user.SetupTxClient(ctx, kr, grpcConn, encCfg, user.WithDefaultAccount("<key_name>"))
if err != nil { return err }
 
ns := share.MustNewV0Namespace([]byte("example"))
result, err := fibre.Put(ctx, client, txClient, ns, data)
if err != nil { return err }
// Save result.BlobID, result.TxHash and result.Height.
 
blob, err := client.Download(ctx, result.BlobID)
if err != nil { return err }
defer blob.Free()
_ = blob.Data()

See the full example with imports in the Fibre package README.

For production, prefer Client.Upload followed by your own transaction submission. Put only returns the transaction hash after confirmation. If confirmation fails, you don't get the hash, which makes it harder to check whether the blob was paid for.

6. Save a receipt for every blob

Store these for every blob you submit:

FieldWhy you need it
blob_idTo download the blob
tx_hashTo check settlement
heightTo find the settlement on chain
Payment promise hash (native Go: PaymentPromise.Hash())To check settlement with is-payment-processed
Your own copy of the data, optionally with its hashTo recover after retention ends, and to check downloads

The JSON-RPC API returns blob_id as base64. The Go client's BlobID.String() returns hex. They are the same ID.