openapi: 3.1.0
info:
  title: Mo Chain Explorer API
  version: 0.1.0
  description: |
    Public REST + JSON-RPC endpoints for the **Mo Chain testnet** (Chain ID 6688 / MO).

    - **Blockscout v2 REST API** — blocks, transactions, addresses, tokens, contracts, stats.
    - **JSON-RPC** — standard Ethereum methods (subset) on the public RPC node.
    - **Archive trace** — `debug_*` / `trace_*` on the archive node (heavy responses).

    Servers below are the production hyphenated subdomains. When this spec is served by the
    bundled `api-docs` container, the deploy script rewrites the server URLs to the actual
    host so "Try it out" works against the deployed network.
  contact:
    name: Mo Chain
    url: https://mo.fit
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

# Public read API — no authentication required.
security: []

servers:
  - url: https://scan-testnet.mo.fit/api
    description: Blockscout REST (v2)
  - url: https://rpc-testnet.mo.fit
    description: JSON-RPC (public RPC node)
  - url: https://rpc-testnet.mo.fit
    description: JSON-RPC (archive — trace methods)

tags:
  - name: Blocks
    description: Block listing and lookup (Blockscout REST v2).
  - name: Transactions
    description: Transaction listing, lookup, token-transfers and logs.
  - name: Addresses
    description: Address info, transactions, token transfers and balances.
  - name: Tokens
    description: Token metadata, holders and transfers.
  - name: Smart Contracts
    description: Verified contract source, ABI and metadata.
  - name: Stats & Search
    description: Network statistics, charts and unified search.
  - name: JSON-RPC
    description: Standard Ethereum JSON-RPC plus archive trace methods.

paths:
  # ----------------------------------------------------------------- Blocks
  /v2/blocks:
    get:
      tags: [Blocks]
      summary: List blocks
      operationId: listBlocks
      parameters:
        - { name: type, in: query, required: false, schema: { type: string, enum: [block, uncle, reorg], example: block } }
      responses:
        '200':
          description: OK
          content:
            application/json:
              example: { items: [{ height: 2850000, hash: "0xabc...", timestamp: "2026-06-08T07:00:00Z", tx_count: 12 }], next_page_params: null }
  /v2/blocks/{block_number_or_hash}:
    get:
      tags: [Blocks]
      summary: Get block by number or hash
      operationId: getBlock
      parameters:
        - { name: block_number_or_hash, in: path, required: true, schema: { type: string, example: "2850000" } }
      responses:
        '200':
          description: OK
          content:
            application/json:
              example: { height: 2850000, hash: "0xabc...", timestamp: "2026-06-08T07:00:00Z", gas_used: "21000", tx_count: 12, miner: { hash: "0x..." } }
        '404':
          description: Not found
          content: { application/json: { example: { message: "Not found" } } }

  # ----------------------------------------------------------- Transactions
  /v2/transactions:
    get:
      tags: [Transactions]
      summary: List transactions
      operationId: listTransactions
      parameters:
        - { name: filter, in: query, required: false, schema: { type: string, enum: [pending, validated], example: validated } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ hash: "0x...", from: { hash: "0x..." }, to: { hash: "0x..." }, value: "1000000000000000000", status: "ok" }], next_page_params: null } } } }
  /v2/transactions/{transaction_hash}:
    get:
      tags: [Transactions]
      summary: Get transaction by hash
      operationId: getTransaction
      parameters:
        - { name: transaction_hash, in: path, required: true, schema: { $ref: '#/components/schemas/Hash' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { hash: "0x...", status: "ok", block: 2850000, gas_used: "21000", from: { hash: "0x..." }, to: { hash: "0x..." }, value: "1000000000000000000" } } } }
        '404': { description: Not found, content: { application/json: { example: { message: "Not found" } } } }
  /v2/transactions/{transaction_hash}/token-transfers:
    get:
      tags: [Transactions]
      summary: Token transfers of a transaction
      operationId: getTransactionTokenTransfers
      parameters:
        - { name: transaction_hash, in: path, required: true, schema: { $ref: '#/components/schemas/Hash' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ token: { address: "0x...", symbol: "tUSDT" }, total: { value: "100000000", decimals: "6" } }] } } } }
  /v2/transactions/{transaction_hash}/logs:
    get:
      tags: [Transactions]
      summary: Logs of a transaction
      operationId: getTransactionLogs
      parameters:
        - { name: transaction_hash, in: path, required: true, schema: { $ref: '#/components/schemas/Hash' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ address: { hash: "0x..." }, topics: ["0xddf2..."], data: "0x..." }] } } } }

  # -------------------------------------------------------------- Addresses
  /v2/addresses/{address}:
    get:
      tags: [Addresses]
      summary: Get address info
      operationId: getAddress
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { hash: "0x...", coin_balance: "1000000000000000000", is_contract: false, is_verified: false } } } }
  /v2/addresses/{address}/transactions:
    get:
      tags: [Addresses]
      summary: List transactions of an address
      operationId: getAddressTransactions
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
        - { name: filter, in: query, required: false, schema: { type: string, enum: [to, from], example: from } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ hash: "0x...", value: "1000000000000000000" }], next_page_params: null } } } }
  /v2/addresses/{address}/token-transfers:
    get:
      tags: [Addresses]
      summary: List token transfers of an address
      operationId: getAddressTokenTransfers
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ token: { symbol: "tUSDC" }, total: { value: "5000000", decimals: "6" } }] } } } }
  /v2/addresses/{address}/tokens:
    get:
      tags: [Addresses]
      summary: List token balances of an address
      operationId: getAddressTokens
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ token: { symbol: "tUSDT", decimals: "6" }, value: "100000000" }] } } } }
  /v2/addresses/{address}/logs:
    get:
      tags: [Addresses]
      summary: List logs emitted by an address
      operationId: getAddressLogs
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ topics: ["0x..."], data: "0x..." }] } } } }

  # ----------------------------------------------------------------- Tokens
  /v2/tokens:
    get:
      tags: [Tokens]
      summary: List tokens
      operationId: listTokens
      parameters:
        - { name: q, in: query, required: false, schema: { type: string, example: USDT } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ address: "0x67c8...", symbol: "tUSDT", decimals: "6", type: "ERC-20" }] } } } }
  /v2/tokens/{address}:
    get:
      tags: [Tokens]
      summary: Get token by contract address
      operationId: getToken
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { address: "0x67c8...", symbol: "tUSDT", name: "Test USDT", decimals: "6", total_supply: "100000000000000" } } } }
  /v2/tokens/{address}/holders:
    get:
      tags: [Tokens]
      summary: List token holders
      operationId: getTokenHolders
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ address: { hash: "0x..." }, value: "100000000" }] } } } }
  /v2/tokens/{address}/transfers:
    get:
      tags: [Tokens]
      summary: List token transfers
      operationId: getTokenTransfers
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ from: { hash: "0x..." }, to: { hash: "0x..." }, total: { value: "100000000", decimals: "6" } }] } } } }

  # ------------------------------------------------------- Smart Contracts
  /v2/smart-contracts:
    get:
      tags: [Smart Contracts]
      summary: List verified smart contracts
      operationId: listSmartContracts
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ address: "0x884f...", name: "WMO", compiler_version: "v0.8.20+commit..." }] } } } }
  /v2/smart-contracts/{address}:
    get:
      tags: [Smart Contracts]
      summary: Get verified contract source & ABI
      operationId: getSmartContract
      parameters:
        - { name: address, in: path, required: true, schema: { $ref: '#/components/schemas/Address' } }
      responses:
        '200': { description: OK, content: { application/json: { example: { name: "WMO", is_verified: true, compiler_version: "v0.8.20+commit...", abi: [], source_code: "// SPDX-License-Identifier: MIT ..." } } } }

  # -------------------------------------------------------- Stats & Search
  /v2/stats:
    get:
      tags: [Stats & Search]
      summary: Network stats
      operationId: getStats
      responses:
        '200': { description: OK, content: { application/json: { example: { total_blocks: "2850000", total_transactions: "12500000", total_addresses: "45000", average_block_time: 304 } } } }
  /v2/stats/charts/transactions:
    get:
      tags: [Stats & Search]
      summary: Daily transaction count chart
      operationId: getTransactionChart
      responses:
        '200': { description: OK, content: { application/json: { example: { chart_data: [{ date: "2026-06-08", tx_count: 120000 }] } } } }
  /v2/search:
    get:
      tags: [Stats & Search]
      summary: Search blocks / txs / addresses / tokens
      operationId: search
      parameters:
        - { name: q, in: query, required: true, schema: { type: string, example: "0x884fc1de69BC20620339136789c6C6cD2C0fEdbd" } }
      responses:
        '200': { description: OK, content: { application/json: { example: { items: [{ type: "token", address: "0x884f...", symbol: "WMO" }] } } } }

  # ---------------------------------------------------------------- JSON-RPC
  /:
    post:
      tags: [JSON-RPC]
      summary: JSON-RPC (eth_* + archive trace)
      description: |
        Standard Ethereum JSON-RPC. Pick a method via the **request examples** dropdown.

        Public RPC node: `eth_chainId`, `eth_blockNumber`, `eth_getBalance`,
        `eth_getTransactionByHash`, `eth_getTransactionReceipt`, `eth_call`,
        `eth_estimateGas`, `eth_sendRawTransaction`.

        Archive node only (heavy responses, use small ranges): `debug_traceTransaction`,
        `debug_traceCall`, `trace_block`, `trace_replayTransaction`.
      operationId: jsonRpc
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/JsonRpcRequest' }
            examples:
              eth_chainId:
                value: { jsonrpc: "2.0", id: 1, method: "eth_chainId", params: [] }
              eth_blockNumber:
                value: { jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }
              eth_getBalance:
                value: { jsonrpc: "2.0", id: 1, method: "eth_getBalance", params: ["0x0000000000000000000000000000000000000000", "latest"] }
              eth_getTransactionByHash:
                value: { jsonrpc: "2.0", id: 1, method: "eth_getTransactionByHash", params: ["0x0000000000000000000000000000000000000000000000000000000000000000"] }
              eth_getTransactionReceipt:
                value: { jsonrpc: "2.0", id: 1, method: "eth_getTransactionReceipt", params: ["0x0000000000000000000000000000000000000000000000000000000000000000"] }
              eth_call:
                value: { jsonrpc: "2.0", id: 1, method: "eth_call", params: [{ to: "0xcA11bde05977b3631167028862bE2a173976CA11", data: "0x0f28c97d" }, "latest"] }
              eth_estimateGas:
                value: { jsonrpc: "2.0", id: 1, method: "eth_estimateGas", params: [{ to: "0x0000000000000000000000000000000000000000", value: "0x1" }] }
              eth_sendRawTransaction:
                value: { jsonrpc: "2.0", id: 1, method: "eth_sendRawTransaction", params: ["0x02f8..."] }
              debug_traceTransaction:
                value: { jsonrpc: "2.0", id: 1, method: "debug_traceTransaction", params: ["0x0000000000000000000000000000000000000000000000000000000000000000", { tracer: "callTracer" }] }
              debug_traceCall:
                value: { jsonrpc: "2.0", id: 1, method: "debug_traceCall", params: [{ to: "0x0000000000000000000000000000000000000000", data: "0x" }, "latest", { tracer: "callTracer" }] }
              trace_block:
                value: { jsonrpc: "2.0", id: 1, method: "trace_block", params: ["latest"] }
              trace_replayTransaction:
                value: { jsonrpc: "2.0", id: 1, method: "trace_replayTransaction", params: ["0x0000000000000000000000000000000000000000000000000000000000000000", ["trace"]] }
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema: { $ref: '#/components/schemas/JsonRpcResponse' }
              example: { jsonrpc: "2.0", id: 1, result: "0x2290" }

components:
  schemas:
    Address:
      type: string
      pattern: "^0x[a-fA-F0-9]{40}$"
      example: "0x884fc1de69BC20620339136789c6C6cD2C0fEdbd"
    Hash:
      type: string
      pattern: "^0x[a-fA-F0-9]{64}$"
      example: "0x0000000000000000000000000000000000000000000000000000000000000000"
    JsonRpcRequest:
      type: object
      required: [jsonrpc, method, id]
      properties:
        jsonrpc: { type: string, const: "2.0" }
        id: { type: integer, example: 1 }
        method: { type: string, example: "eth_chainId" }
        params: { type: array, items: {} }
    JsonRpcResponse:
      type: object
      properties:
        jsonrpc: { type: string, example: "2.0" }
        id: { type: integer, example: 1 }
        result: {}
        error:
          type: object
          properties:
            code: { type: integer, example: -32601 }
            message: { type: string, example: "the method does not exist/is not available" }
