``` {.yaml}
type: google.api.Service
config_version: 3

http:
  rules:
    - selector: bdware.bdledger.api.Node.ClientVersion
      get: /v0/node/version
    - selector: bdware.bdledger.api.Ledger.CreateLedger
      post: /v0/ledgers
      body: "*"
    - selector: bdware.bdledger.api.Ledger.GetLedgers
      get: /v0/ledgers
    - selector: bdware.bdledger.api.Ledger.SendTransaction
      post: /v0/ledgers/{ledger}/transactions
      body: "*"
    - selector: bdware.bdledger.api.Query.GetBlockByHash
      get: /v0/ledgers/{ledger}/block
    - selector: bdware.bdledger.api.Query.GetBlocks
      post: /v0/ledgers/{ledger}/blocks/query
      body: "*"
    - selector: bdware.bdledger.api.Query.CountBlocks
      post: /v0/ledgers/{ledger}/blocks/count
      body: "*"
    - selector: bdware.bdledger.api.Query.GetRecentBlocks
      get: /v0/ledgers/{ledger}/blocks/recent
    - selector: bdware.bdledger.api.Query.GetTransactionByHash
      get: /v0/ledgers/{ledger}/transaction
    - selector: bdware.bdledger.api.Query.GetTransactionByBlockHashAndIndex
      get: /v0/ledgers/{ledger}/block/transaction
    - selector: bdware.bdledger.api.Query.GetTransactions
      post: /v0/ledgers/{ledger}/transactions/query
      body: "*"
    - selector: bdware.bdledger.api.Query.CountTransactions
      post: /v0/ledgers/{ledger}/transactions/count
      body: "*"
```

> **Note**
>
> Request/Response data of **bytes** type should/will be encoded with
> [Base64](https://tools.ietf.org/html/rfc4648#section-4).

> **Note**
>
> When using hash strings in URL, they need to be encoded with
> [encodeURIComponent](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent).

Request Examples {#_request_examples}
================

Node.ClientVersion {#_node_clientversion}
------------------

Get BDLedger node version

    GET http://{{IP}}:{{PORT}}/v0/node/version

**Response.**

``` {.json}
{
  "version": "dev-210119.a88bf4eb"
}
```

Ledger.CreateLedger {#_ledger_createledger}
-------------------

Create a new ledger

    POST http://{{IP}}:{{PORT}}/v0/ledgers

**Request body.**

``` {.json}
{
  "name": "test"
}
```

**Response.**

``` {.json}
{
  "ok": true
}
```

Ledger.GetLedgers {#_ledger_getledgers}
-----------------

Get all ledgers

    GET http://{{IP}}:{{PORT}}/v0/ledgers

**Response.**

``` {.json}
{
  "ledgers": [
    "default",
    "test"
  ]
}
```

Ledger.SendTransaction {#_ledger_sendtransaction}
----------------------

Send a new transaction

    POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions

**Request body.**

``` {.json}
{
  "transaction": {
    "type": 0,
    "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
    "nonce": 52,
    "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
  }
}
```

**Response.**

``` {.json}
{
  "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE="
}
```

Query.GetBlockByHash {#_query_getblockbyhash}
--------------------

Get a block identified by its hash

    GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block?hash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D

**hash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)

**Response.**

``` {.json}
{
  "block": {
    "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
    "creator": "",
    "nonce": "0",
    "parentHashes": [
      "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
      "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
      "3XkwkuMBearq8uavN76Te7Zdpl8="
    ],
    "witnesses": [],
    "timestamp": "1611038043",
    "size": "0",
    "transactionCount": 1,
    "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
    "transactions": [
      {
        "blockHash": "",
        "blockTimestamp": "0",
        "index": 0,
        "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
        "type": "RECORD",
        "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
        "nonce": "0",
        "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
        "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
      }
    ],
    "transactionHashes": [
      "VQBeA5Ee0Y5hqEileoQuYMHbOSE="
    ]
  }
}
```

Query.GetBlocks {#_query_getblocks}
---------------

Get blocks in a timestamp range

    POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/query

``` {.protobuf}
enum IncludeTransactions {
  NONE = 0; // Don't include transaction data
  HASH = 1; // Include transactions hashes
  FULL = 2; // Include full transactions
}
```

Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\]

If only **end\_timestamp** is not specified, or
asciimath:\[\"end\_timestamp\"-\"start\_timestamp\"\>\"query.maxDuration\"\],
then **end\_timestamp** will be set to
asciimath:\[\"start\_timestamp\"+\"query.maxDuration\"\].

If only **start\_timestamp** is not specified, then **start\_timestamp**
will be set to asciimath:\[\"end\_timestamp\"-\"query.maxDuration\"\].

In all cases, **start\_timestamp** will never be earlier than the
genesis block's timestamp, and **end\_timestamp** will never be later
than the current timestamp when the node process the query request.

**Request body 1.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000,
  "include_transactions": 0
}
```

**Response 1.**

``` {.json}
{
  "blocks": [
    {
      "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
      "creator": "",
      "nonce": "0",
      "parentHashes": [
        "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
        "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
        "3XkwkuMBearq8uavN76Te7Zdpl8="
      ],
      "witnesses": [],
      "timestamp": "1611038043",
      "size": "0",
      "transactionCount": 1,
      "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
      "transactions": [],
      "transactionHashes": []
    }
  ],
  "startTimestamp": "1611038043",
  "endTimestamp": "1611038043"
}
```

**Request body 2.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000,
  "include_transactions": 1
}
```

**Response 2.**

``` {.json}
{
  "blocks": [
    {
      "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
      "creator": "",
      "nonce": "0",
      "parentHashes": [
        "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
        "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
        "3XkwkuMBearq8uavN76Te7Zdpl8="
      ],
      "witnesses": [],
      "timestamp": "1611038043",
      "size": "0",
      "transactionCount": 1,
      "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
      "transactions": [],
      "transactionHashes": [
        "VQBeA5Ee0Y5hqEileoQuYMHbOSE="
      ]
    }
  ],
  "startTimestamp": "1611038043",
  "endTimestamp": "1611038043"
}
```

**Request body 3.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000,
  "include_transactions": 2
}
```

**Response 3.**

``` {.json}
{
  "blocks": [
    {
      "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
      "creator": "",
      "nonce": "0",
      "parentHashes": [
        "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
        "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
        "3XkwkuMBearq8uavN76Te7Zdpl8="
      ],
      "witnesses": [],
      "timestamp": "1611038043",
      "size": "0",
      "transactionCount": 1,
      "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
      "transactions": [
        {
          "blockHash": "",
          "blockTimestamp": "0",
          "index": 0,
          "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
          "type": "RECORD",
          "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
          "nonce": "0",
          "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
          "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
        }
      ],
      "transactionHashes": [
        "VQBeA5Ee0Y5hqEileoQuYMHbOSE="
      ]
    }
  ],
  "startTimestamp": "1611038043",
  "endTimestamp": "1611038043"
}
```

Query.CountBlocks {#_query_countblocks}
-----------------

Count all blocks in a ledger, or blocks in a timestamp range

    POST http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/count

Requirement: asciimath:\[\"start\_timestamp\"⇐\"end\_timestamp\"\]

If neither **start\_timestamp** nor **end\_timestamp** is specified,
then count all blocks in the specified ledger.

If only **end\_timestamp** is not specified, then count all blocks with
timestamps later than **start\_timestamp**.

If only **start\_timestamp** is not specified, then count all blocks
with timestamps earlier than **end\_timestamp**.

In all cases, **start\_timestamp** will never be earlier than the
genesis block's timestamp, and **end\_timestamp** will never be later
than the current timestamp when the node process the query request.

**Request body 1.**

``` {.json}
{}
```

**Response 1.**

``` {.json}
{
  "count": "5",
  "startTimestamp": "0",
  "endTimestamp": "1611039957"
}
```

**Request body 2.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000
}
```

**Response 2.**

``` {.json}
{
  "count": "1",
  "startTimestamp": "1611038000",
  "endTimestamp": "1611039000"
}
```

Query.GetRecentBlocks {#_query_getrecentblocks}
---------------------

Get recent **count** blocks (Only support IncludeTransactions=NONE for
now)

    GET http://{{IP}}:{{PORT}}/v0/ledgers/test/blocks/recent?count=2

**Response.**

``` {.json}
{
  "blocks": [
    {
      "hash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
      "creator": "",
      "nonce": "0",
      "parentHashes": [
        "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
        "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
        "3XkwkuMBearq8uavN76Te7Zdpl8="
      ],
      "witnesses": [],
      "timestamp": "1611038043",
      "size": "0",
      "transactionCount": 1,
      "transactionsRoot": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
      "transactions": [],
      "transactionHashes": []
    },
    {
      "hash": "rk0DWMaUpRG82yVX+cFhbfhPFdw=",
      "creator": "",
      "nonce": "0",
      "parentHashes": [
        "fLX5pMY8M1qSAGZdKT1rWBkdEMo=",
        "3XkwkuMBearq8uavN76Te7Zdpl8=",
        "8pZPR74OALIbps5XFb4dL/s0j0M="
      ],
      "witnesses": [],
      "timestamp": "1610968019",
      "size": "0",
      "transactionCount": 1,
      "transactionsRoot": "LuxttCm/pSHVMOKF0sJExk+DJXc=",
      "transactions": [],
      "transactionHashes": []
    }
  ],
  "startTimestamp": "1610968019",
  "endTimestamp": "1611038043"
}
```

Query.GetTransactionByHash {#_query_gettransactionbyhash}
--------------------------

Get a transaction identified by its hash

    GET http://{{IP}}:{{PORT}}/v0/ledgers/test/transaction?hash=VQBeA5Ee0Y5hqEileoQuYMHbOSE%3D

**hash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)

**Response.**

``` {.json}
{
  "transaction": {
    "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
    "blockTimestamp": "1611038043",
    "index": 0,
    "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
    "type": "RECORD",
    "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
    "nonce": "0",
    "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
    "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
  }
}
```

Query.GetTransactionByBlockHashAndIndex {#_query_gettransactionbyblockhashandindex}
---------------------------------------

Get a transaction identified by hash of the block it belongs to and its
index inside the block

    GET http://{{IP}}:{{PORT}}/v0/ledgers/test/block/transaction?blockHash=LSKr%2BK079Ax%2BrKdlyYN5ze2YGzo%3D&index=0

**blockHash** has to be encoded with
[encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)

**Response.**

``` {.json}
{
  "transaction": {
    "blockHash": "LSKr+K079Ax+rKdlyYN5ze2YGzo=",
    "blockTimestamp": "1611038043",
    "index": 0,
    "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
    "type": "RECORD",
    "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
    "nonce": "0",
    "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
    "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
  }
}
```

Query.GetTransactions {#_query_gettransactions}
---------------------

Get transactions in a timestamp range

    POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/query

**start\_timestamp** and **end\_timestamp** follow the same requirements
and rules as in [???](#Query.GetBlocks).

**Request body.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000
}
```

**Response.**

``` {.json}
{
  "transactions": [
    {
      "blockHash": "",
      "blockTimestamp": "0",
      "index": 0,
      "hash": "VQBeA5Ee0Y5hqEileoQuYMHbOSE=",
      "type": "RECORD",
      "from": "8A3K/vANyv7wDcr+8A3K/vANyv4=",
      "nonce": "0",
      "to": "AAAAAAAAAAAAAAAAAAAAAAAAAAA=",
      "data": "lQItWZKS5hlUn6V/DMKKwvZXxvM="
    }
  ],
  "startTimestamp": "1611038043",
  "endTimestamp": "1611038043"
}
```

Query.CountTransactions {#_query_counttransactions}
-----------------------

Count all transactions in a ledger, or transactions in a timestamp range

    POST http://{{IP}}:{{PORT}}/v0/ledgers/test/transactions/count

**start\_timestamp** and **end\_timestamp** follow the same requirements
and rules as in [???](#Query.CountBlocks).

**Request body 1.**

``` {.json}
{}
```

**Response 1.**

``` {.json}
{
  "count": "4",
  "startTimestamp": "0",
  "endTimestamp": "1611039957"
}
```

**Request body 2.**

``` {.json}
{
  "start_timestamp": 1611038000,
  "end_timestamp": 1611039000
}
```

**Response 2.**

``` {.json}
{
  "count": "1",
  "startTimestamp": "1611038000",
  "endTimestamp": "1611039000"
}
```
