VeChain Rosetta Data API

March 11, 2026 ยท View on GitHub

Implementing Rosetta Data API of VeChainThor BlockChain

Installation

Getting the source

  • Clone the repo
    git clone https://github.com/vechain/rosetta.git
    cd rosetta

Docker Compose

The project uses a multi-stage Docker build process for optimal deployment. This configuration:

  • Builds the Thor binary and Node.js application in separate stages
  • Mounts a local data directory for persistence
  • Exposes all necessary ports for the Rosetta API and Thor node
  • Sets up environment variables for network type and run mode

To use docker-compose:

# Build and start the container
docker-compose up -d

# View logs
docker-compose logs -f rosetta-server

# Stop the container
docker-compose down

The configuration can be customized by modifying the docker-compose.yml file:

  • Change the data directory path in the volumes section
  • Modify the exposed ports if needed
  • Adjust environment variables (NETWORK and MODE)
  • Update the build context if needed

Example docker-compose.yml

version: '3.8'
services:
  rosetta-server:
    build:
      context: .
    volumes:
      - ./data:/data # Points to your local directory
    ports:
      - "8080:8080"  # Rosetta API
      - "8669:8669"  # Thor node
      - "11235:11235"  # P2P
      - "11235:11235/udp"  # P2P UDP
    environment:
      - NETWORK=main
      - MODE=online
    restart: unless-stopped

Development & Testing

Running Tests Locally

The project includes end-to-end tests that verify the Rosetta API implementation:

# Install dependencies
npm ci

# Prepare data directory
mkdir -p rosetta_data
chmod -R 777 rosetta_data

# Run e2e tests
npm run test:e2e:custom

The tests will automatically:

  1. Build Docker images with the default Thor version
  2. Start a fresh solo node from genesis
  3. Run all test suites
  4. Clean up containers and volumes

Testing Against a Custom Thor Branch

To test Rosetta against a specific Thor branch or version, use the THOR_REPO and THOR_VERSION build arguments:

# Test against a specific Thor branch
THOR_REPO=https://github.com/vechain/thor.git \
THOR_VERSION=your-branch-name \
docker compose build --no-cache

# Then run tests
npm run test:e2e:custom

Note: Build arguments (THOR_REPO, THOR_VERSION) must be set during docker compose build, not when starting containers. They determine which Thor version gets compiled into the image.

Quick Commands

# Start services with default Thor
npm run start:custom

# Stop services
npm run stop

# View logs
docker compose logs -f rosetta-server

# Clean everything and rebuild
docker compose down -v
rm -rf ./rosetta_data/*
docker compose build --no-cache

Endpoints

This implementation is meant to cover this reference.

Account

MethodEndpointImplementedDescriptionMode
POST/account/balanceYesGet an Account Balanceonline
POST/account/coinsNo

Block

MethodEndpointImplementedDescriptionMode
POST/blockYesGet a Blockonline
POST/block/transactionYesGet a Block Transactiononline

Call

MethodEndpointImplementedDescriptionMode
POST/callNoMake a Network-Specific Procedure Call

Construction

MethodEndpointImplementedDescriptionMode
POST/construction/combineYesCreate Network Transaction from Signaturesonline & offline
POST/construction/deriveYesDerive an AccountIdentifier from a PublicKeyonline & offline
POST/construction/hashYesGet the Hash of a Signed Transactiononline & offline
POST/construction/metadataYesGet Metadata for Transaction Constructiononline
POST/construction/parseYesParse a Transactiononline & offline
POST/construction/payloadsYesGenerate an Unsigned Transaction and Signing Payloadsonline & offline
POST/construction/preprocessYesCreate a Request to Fetch Metadataonline & offline
POST/construction/submitYesSubmit a Signed Transactiononline

Events

MethodEndpointImplementedDescriptionMode
POST/events/blocksYes[INDEXER] Get a range of BlockEventsonline

Mempool

MethodEndpointImplementedDescriptionMode
POST/mempoolYesGet All Pool Transactions from the Node
POST/mempool/transactionYesGet a Pool Transaction from the Node

Network

MethodEndpointImplementedDescriptionMode
POST/network/listYesGet List of Available Networksonline & offline
POST/network/optionsYesGet Network Optionsonline & offline
POST/network/statusYesGet Network Statusonline
MethodEndpointImplementedDescriptionMode
POST/search/transactionsYes[INDEXER] Search for Transactionsonline

About Fee Delegation (VIP191)

  • VeChain Rosetta implement support Fee Delegation (VIP-191).

Why exchanges need VIP191

  • The exchange will transfer currencies from hot wallet to the safe cold wallet from time to time. When there's not enough VTHO in the hot wallet or want to transfer all currencies includ VTHO, the exchange can use VIP191 function to pay the transaction fee.

How to use it

  • Step 1: Create a VIP191 payload

Create a VIP191 payload, add FeeDelegation operation to operations, account is fee delegator address, amount.value default 0.

    {
    "network_identifier": {
        "blockchain": "vechainthor",
        "network": "test"
    },
    "operations": [
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 0
            },
            "type": "Transfer",
            "status": "None",
            "account": {
                "address": "0x16277a1ff38678291c41d1820957c78bb5da59ce"
            },
            "amount": {
                "value": "10000",
                "currency": {
                    "symbol": "VET",
                    "decimals": 18
                },
                "metadata": {}
            }
        },
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 1
            },
            "type": "Transfer",
            "status": "None",
            "account": {
                "address": "0xc05c334533c673582616ac2bf404b6c55efa1087"
            },
            "amount": {
                "value": "-10000",
                "currency": {
                    "symbol": "VET",
                    "decimals": 18
                },
                "metadata": {}
            }
        },
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 2
            },
            "type": "FeeDelegation",
            "status": "None",
            "account": {
                "address": "0x4251630dc820e90a5a6d14d79cac7acb93917983"
            },
            "amount": {
                "value": "-210000000000000000",
                "currency": {
                    "symbol": "VTHO",
                    "decimals": 18,
                    "metadata": {
                        "contractAddress": "0x0000000000000000000000000000456E65726779"
                    }
                },
                "metadata": {}
            }
        }
    ]
}
  • Step 2: Call /construction/preprocess

When calling /construction/preprocess use VIP191 payloads, the api will return options and two required_public_keys, the first is transaction origin's public key,the second is fee delegation payer's public key.

  {
    "options": {
        "clauses": [
            {
                "to": "0x16277a1ff38678291c41d1820957c78bb5da59ce",
                "value": "10000",
                "data": "0x00"
            }
        ]
    },
    "required_public_keys": [
        {
            "address": "0xc05c334533c673582616ac2bf404b6c55efa1087"
        },
        {
            "address": "0x4251630dc820e90a5a6d14d79cac7acb93917983"
        }
    ]
}
  • Step 3: Call /construction/metadata

Use step 2 return value to call /construction/metadata, the api will calculate the gas online, return metadata and suggested_fee.

{
    "metadata": {
        "blockRef": "0x00d88b4ab127a39e",
        "chainTag": 39,
        "gas": 25200
    },
    "suggested_fee": [
        {
            "value": "2520000000",
            "currency": {
                "symbol": "VTHO",
                "decimals": 18,
                "metadata": {
                    "contractAddress": "0x0000000000000000000000000000456E65726779"
                }
            }
        }
    ]
}
  • Step 4: Call /construction/payloads
{
    "network_identifier": {
        "blockchain": "vechainthor",
        "network": "test"
    },
    "operations": [
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 0
            },
            "type": "Transfer",
            "status": "None",
            "account": {
                "address": "0x16277a1ff38678291c41d1820957c78bb5da59ce"
            },
            "amount": {
                "value": "10000",
                "currency": {
                    "symbol": "VET",
                    "decimals": 18
                },
                "metadata": {}
            }
        },
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 1
            },
            "type": "Transfer",
            "status": "None",
            "account": {
                "address": "0xc05c334533c673582616ac2bf404b6c55efa1087"
            },
            "amount": {
                "value": "-10000",
                "currency": {
                    "symbol": "VET",
                    "decimals": 18
                },
                "metadata": {}
            }
        },
        {
            "operation_identifier": {
                "index": 0,
                "network_index": 2
            },
            "type": "FeeDelegation",
            "status": "None",
            "account": {
                "address": "0x4251630dc820e90a5a6d14d79cac7acb93917983"
            },
            "amount": {
                "value": "-210000000000000000",
                "currency": {
                    "symbol": "VTHO",
                    "decimals": 18,
                    "metadata": {
                        "contractAddress": "0x0000000000000000000000000000456E65726779"
                    }
                },
                "metadata": {}
            }
        }
    ],
    "metadata": {
        "blockRef": "0x00d88b4ab127a39e",
        "chainTag": 39,
        "gas": 25200
    },
    "public_keys": [
        {
            "hex_bytes": "02d992bd203d2bf888389089db13d2d0807c1697091de377998efe6cf60d66fbb3",
            "curve_type": "secp256k1"
        },
        {
            "hex_bytes": "03a7e5b27bf35f3b1a863851a02b4d722927cd12f92bfb21f69c81c22fc4a1c6d3",
            "curve_type": "secp256k1"
        }
    ]
}

The api will return unsigned_transaction and payloads.

{
    "unsigned_transaction": "0xf85d278800d88b4ab127a39e81b4dad99416277a1ff38678291c41d1820957c78bb5da59ce822710808262708827c7571b85f5271594c05c334533c673582616ac2bf404b6c55efa1087944251630dc820e90a5a6d14d79cac7acb93917983",
    "payloads": [
        {
            "address": "0xc05c334533c673582616ac2bf404b6c55efa1087",
            "hex_bytes": "3fec5f2cfdd172e1372879992644513578a9917355488e23d5abf846990c1fe2",
            "signature_type": "ecdsa_recovery"
        },
        {
            "address": "0x4251630dc820e90a5a6d14d79cac7acb93917983",
            "hex_bytes": "16ff81dd942a6e42c6a352dbcf5615693c3659feb35cdc177d27a2851b73ee40",
            "signature_type": "ecdsa_recovery"
        }
    ]
}
  • Step 5: Sign with transaction orgin and fee delegation payer private keys and call /construction/combine
{
    "network_identifier": {
        "blockchain": "vechainthor",
        "network": "test"
    },
    "unsigned_transaction": "0xf85d278800d852ba843f1d4181b4dad99416277a1ff38678291c41d1820957c78bb5da59ce8227108082627088556581012357229594c05c334533c673582616ac2bf404b6c55efa1087944251630dc820e90a5a6d14d79cac7acb93917983",
    "signatures": [
        {
            "signing_payload": {
                "address": "0xc05c334533c673582616ac2bf404b6c55efa1087",
                "hex_bytes": "3fec5f2cfdd172e1372879992644513578a9917355488e23d5abf846990c1fe2",
                "signature_type": "ecdsa_recovery"
            },
            "public_key": {
                "hex_bytes": "02d992bd203d2bf888389089db13d2d0807c1697091de377998efe6cf60d66fbb3",
                "curve_type": "secp256k1"
            },
            "signature_type": "ecdsa_recovery",
            "hex_bytes": "4ad82781abf5866020c9bf6a7b07f94ba4bb9e95ac1ca3c858ded24c08b6856213589bac265f656a87da255b855cfab9a96020d450593df2481015188ae7927000"
        },
        {
            "signing_payload": {
                "address": "0x4251630dc820e90a5a6d14d79cac7acb93917983",
                "hex_bytes": "16ff81dd942a6e42c6a352dbcf5615693c3659feb35cdc177d27a2851b73ee40",
                "signature_type": "ecdsa_recovery"
            },
            "public_key": {
                "hex_bytes": "036aafc0aa461c6b2de2ca8a254ebc6685946a08dd7656dbb935ce4ce5cfac355b",
                "curve_type": "secp256k1"
            },
            "signature_type": "ecdsa_recovery",
            "hex_bytes": "7d6df64de2c4084b7809bdeba85784c6d031dd943e96271ac1cd22f3da9b5c3f2e610ec2d50e576583cff2d386fd6f7069b2883ca023b6000575ec0fcf4ddc9800"
        }
    ]
}