Skip to content

Ergo Platform Blockchain Integration Guide#

This guide aims to provide developers with the necessary information to integrate with the Ergo Blockchain Platform. For any suggestions to improve this guide, feel free to reach out to us at [email protected] or join our #development channel on Discord.

Getting Started#

Let's start with a quick rundown of Ergo's key features:

  • Ergo's transactions, akin to Bitcoin, consist of multiple inputs and outputs. Unspent outputs, known as single-use entities, are used once. Although Ergo is built from the ground up, its scripts and transaction formats are distinct from Bitcoin's. For an in-depth understanding, refer to the Ergo 'Box' model.
  • Ergo incorporates standard scripts, associated with P2PK addresses, much like Bitcoin. Explore more about the address scheme here.
  • An Ergo UTXO box utilizes registers to store arbitrary values, such as its native tokens, rather than a single amount (like BTC). Consequently, each box holds an ERG amount and may also include {tokenid, token amount} pairs, adhering to the UTXO model.
  • Ergo's inbuilt wallet API caters to most use cases. The API employs a Swagger interface and operates on by default in the mainnet (9052 on the testnet).
  • Comprehensive guides on node setup and a dedicated troubleshooting page are readily available for your convenience.



We recommend running your own node for optimal performance. However, if you prefer to use a public node, one is available at If you require redundancy, don't hesitate to contact us at [email protected] or join our group chat. You can also find a dynamic list of public nodes at

If you choose to run a public node, the web interface can be accessed at Please note that the port changes to 9052 when operating on the testnet.

To get started on the testnet, please refer to this page.

Exchange Specific Node Settings#

If you are operating an exchange node, consider implementing the following non-default wallet settings:

  • Set ergo.wallet.dustLimit = 1000000. This setting causes the node wallet to disregard incoming payments (such as airdrops) of 0.001 ERG or less. This value can be adjusted as per your needs. The default value is null, which means the wallet accounts for all incoming payments.
  • Set ergo.wallet.profile to exchange. This setting enables the wallet to use larger Bloom filters, leading to more efficient scanning when the wallet has a large number of addresses.
  • Set ergo.wallet.tokensWhitelist to a non-null value to automatically burn airdrop tokens and similar. An example of this can be seen in the code block below.

These settings can be combined to create a configuration section as shown below:

  ergo {
    wallet {

      # boxes with value smaller than dustLimit are disregarded in wallet scan logic
      dustLimit = 1000000

      # Whitelisted tokens, if non-null, the wallet will automatically burn non-whitelisted tokens from
      # inputs when doing transactions.
      # If tokensWhitelist = [], all the tokens will be burnt,
      # tokensWhitelist = ["example"] means that all the tokens except of "example" will be burnt
      # tokensWhitelist = null means no tokens burnt automatically
      tokensWhitelist = [
        # SigUSD
        # SigRSV

      # Wallet profile allows to say wallet what kind of load it should expect,
      # and so spend memory on caches and Bloom filters accordingly.
      # There are three options: user, exchange, appServer
      # User profile is about ordinary planned usage.
      # Exchange consumes ~20 MB of RAM for high-load ready Bloom filters
      # AppServer is in between
      profile = "exchange"

Node Wallet#


Ergo node also offers a REST API that can be accessed via HTTP. The complete API specification, presented in OpenAPI format, can be found here. When the node is operational, a user-friendly Swagger UI is accessible at You can also experiment with it here. Furthermore, an optional indexed node API is available.

The major wallet functionalities include:

  • Wallet creation (/wallet/init) and mnemonic generation
  • Wallet restoration (/wallet/restore) from mnemonic
  • Wallet unlock (/wallet/unlock) for transaction signing
  • Wallet lock (/wallet/lock)
  • Sending a simple payment (/wallet/payment/send)
  • Checking wallet status (/wallet/status)
  • Deriving a new key according to EIP-3 (BIP 44 implementation for Ergo) (/wallet/deriveNextKey)
  • Checking wallet balance (/wallet/balances) for all addresses
  • Retrieving wallet transactions (/wallet/transactions) for all addresses


The public explorer is available at Community-hosted alternatives can be found at and

To install the Explorer backend independently, you can utilize ergo-bootstrap.

For additional details, mirrors, and resources, refer to the dedicated Explorer section.


GraphQL queries provide a flexible approach to data fetching, minimizing both over-fetching and under-fetching. The GraphQL server, built on top of the Ergo Platform's explorer database schema, is accessible at

The most reliable instance currently is

Creating an External Wallet#

You can develop your wallet logic externally using one of the available libraries and the block explorer.

Please ensure to take into consideration mempool transactions to avoid double-spending.

Available libraries include:

Offline Signing#

Address generation#

A demo for secret seed and derived addresses generation using ergo-wallet and Java is provided in

You can use the /wallet/deriveNextKey API to generate new addresses in the same wallet.

curl -X GET "http://localhost:9053/wallet/deriveNextKey" -H  "accept: application/json" -H  "api_key: hello"

Address validation#

For an exchange, you can restrict people to only withdraw to P2PK addresses and invalidate any other address. Supporting other types is not recommended. See [] for more information on the types of addresses.

ergo-simple-addresses contains a few zero-dependencies Java-friendly utils for working with addresses.

Composing transactions outside the node#

To get unspent UTXOs for some address, please use the transactions/boxes/byAddress/unspent Explorer API method: 

It would be best if you excluded UTXOs spent in the mempool. Use the/transactions/unconfirmed/byAddress Explorer API method for that:

Broadcasting transactions#

To broadcast a transaction made outside the node, the easiest way is to serialize it into JSON; in Java, it could be like this:

Json json = JsonCodecsWrapper.ergoLikeTransactionEncoder().apply(tx);

And then send this JSON via a POST request to the public Explorer.*

your private Explorer or a node with open API (POST to http://{node_ip}:9053/transactions )


Dust Collection#

Please collect dust from miners' deposits periodically (which creates many small UTXOs).

Ergo is based on the extended-UTXO model. A side-effect of UTXOs is a term coined dust. Dust refers to fractional values of ERG and is usually below the protocol fee; miner wallets are prone to becoming dusty with the stream of rewards coming into their wallet. All these excess UTXOs can cause a slowdown and ultimately impact your node functionality. This is important to set up for big exchanges that will receive a lot of mining traffic. You must collect dust aggressively; new dust arrives all the time for miners

There are some node specific settings

To solve

  • Get utxos from /wallet/boxes/unspent with min number of confirmations
  • Get their ids and total sum
  • Get their binary representations of utxos via /utxo/byIdBinary/{boxId}

Finally, construct the payment transaction like this:

  "requests": [
      "address": "3WwbzW6u8hKWBcL1W7kNVMr25s2UHfSBnYtwSHvrRQt7DdPuoXrt",
      "value": 10000000000
  "fee": 1000000,
  "inputsRaw": [
    "utxo1", "utxo2"
  "dataInputsRaw": [

And post to /wallet/transaction/send.

Set value and fee accordingly, value + fee = total sum of utxos

You can query with specific parameters like this,

curl -X GET "" -H  "accept: application/json" -H  "api_key: hello"

Another (and simple) way to collect is to set

ergo {
 wallet {
   maxInputs = 300 
   optimalInputs = 100

And send 1 ERG to the change address; however, the node will attach 100 dust inputs (so send any large amounts of change to the change address as well)

Failed to sign boxes#

This error can occur due to too many inputs collected in a transaction for dusty wallets.

Failed to sign boxes due to Estimated execution cost 1001580 exceeds the limit 1000000: Vector(ErgoBox(0275eb3a125bc02fe997cb98c0de8131bd9b2e4617110d

Native Assets#

In the case of large airdrops, many users mistakenly end up putting exchange addresses to receive native assets. An auto-burn method will be in future versions of the node to reduce the manual component of this task. See this Issue for more information.

Send the following request via /wallet/payment/send, replacing the tokenId with the IDs from the tokens spamming your wallets.

    "address": "4MQyMKvMbnCJG3aJ",
    "value": 100000000,
    "assets": [

There is no central database where tokens are registered currently, your best bet is to use community resources like supported tokens in the ergotipper bot and spectrum-finance/ergo-token-list.

Frequently Asked Questions#

Can P2S and P2SH be two address formats for the same script?

Yes, it is possible to create both a P2S and a P2SH address from the same script. In the case of P2S, the script is serialized directly into the address. Conversely, for P2SH, the address contains only a hash of the serialized script.

Are there any issues with supporting address types other than P2PK?

Supporting other address types doesn't pose a problem as long as the user is aware of what they are doing. However, it's worth noting that this is often not the case and it can introduce additional complexity. This is particularly true for P2S addresses, as you cannot validate the input size in your form.

How are ergoTree and address related in terms of conversions?

When using the appkit, the Address.create() function accepts an address string as an argument. You can then obtain the ergoTree from the object that this function returns.

Why do some transactions appear not to pay fees?

While fees are not a mandatory part of the core protocol, transactions without them will not be propagated around the network by default.

What algorithm is used to generate a boxid?

The boxid is generated by hashing the contents of the box.

Refer to the code in AppKit for more details

The bytes of a box are unique because they contain: - The id of the parent transaction, - The output position in the transaction, - A unique transaction id.