diff --git a/.circleci/config.yml b/.circleci/config.yml index a7349b64..5e2d3a8a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -98,6 +98,20 @@ jobs: docker tag build/search-api cybernode/engine-api-chains:$CIRCLE_TAG docker push cybernode/engine-api-chains:$CIRCLE_TAG + deploy_engine_api_chains_docs_image: + <<: *defaults + steps: + - checkout + - setup_remote_docker: + version: 17.11.0-ce + - run: + name: Chains Search Api Documentation Image + command: | + docker build -t build/search-api-docs -f ./docs/Dockerfile ./ + docker login -u $DOCKER_USER -p $DOCKER_PASS + docker tag build/search-api-docs cybernode/engine-api-chains-docs:$CIRCLE_TAG + docker push cybernode/engine-api-chains-docs:$CIRCLE_TAG + workflows: version: 2 @@ -120,6 +134,10 @@ workflows: requires: - build_project - deploy_engine_api_chains_image: + <<: *release_filter + requires: + - build_project + - deploy_engine_api_chains_docs_image: <<: *release_filter requires: - build_project \ No newline at end of file diff --git a/devops/api/.dockerignore b/devops/api/.dockerignore deleted file mode 100644 index f057ab68..00000000 --- a/devops/api/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -# decrease size of build context -/.git -/.gradle -/.idea -**/build \ No newline at end of file diff --git a/devops/api/api-docs b/devops/api/api-docs deleted file mode 100644 index 5ce40023..00000000 --- a/devops/api/api-docs +++ /dev/null @@ -1,4 +0,0 @@ -FROM swaggerapi/swagger-ui:v3.5.0 - -COPY docs/api.v1.json /docs/api.v1.json -ENV SWAGGER_JSON=/docs/api.v1.json diff --git a/docs/Dockerfile b/docs/Dockerfile new file mode 100644 index 00000000..8f9acbe7 --- /dev/null +++ b/docs/Dockerfile @@ -0,0 +1,12 @@ +FROM swaggerapi/swagger-ui:v3.12.1 + +COPY docs/common.v1.yaml /usr/share/nginx/html/ +COPY docs/search.v1.yaml /usr/share/nginx/html/ +COPY docs/bitcoin.v1.yaml /usr/share/nginx/html/ +COPY docs/ethereum.v1.yaml /usr/share/nginx/html/ + +ENV API_URLS='[ \ + {name:"Search API", url:"search.v1.yaml"}, \ + {name:"Ethereum API", url:"ethereum.v1.yaml"} \ +]' + diff --git a/docs/README.md b/docs/README.md index 16f35503..869ca0d8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,4 @@ -# How to edit api file - -//todo update readme +## Build and Run locally +```bash +docker build -t build/raw-api -f ./docs/Dockerfile ./ && docker run -p 8080:8080 build/raw-api +``` diff --git a/docs/api.v1.json b/docs/api.v1.json deleted file mode 100644 index 815fa540..00000000 --- a/docs/api.v1.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "openapi": "3.0.0", - "servers": [ - { - "url": "http://search.cyber.fund/api" - } - ], - "info": { - "description": "Empty description", - "version": "1.0.0", - "title": "Cyber.Search API" - }, - "tags": [ - { - "name": "search", - "description": "Search operations" - }, - { - "name": "bitcoin", - "description": "Access to Bitcoin chain entites" - } - ], - "paths": { - "/search": { - "get": { - "tags": [ - "search" - ], - "summary": "Multichain search", - "description": "", - "operationId": "search", - "parameters": [ - { - "name": "query", - "in": "query", - "description": "Search query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Result set page number (starts from 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "default": 0 - } - }, - { - "name": "pageSize", - "in": "query", - "description": "Size of the page", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "default": 10 - } - } - ], - "responses": { - "400": { - "description": "Invalid query, page or pageSize parameters supplied" - } - } - } - }, - "/bitcoin/block/{blockNumber}": { - "get": { - "tags": [ - "bitcoin" - ], - "summary": "Find bitcoin block by number", - "description": "Returns a block", - "operationId": "getBlockByNumber", - "parameters": [ - { - "name": "blockNumber", - "in": "path", - "description": "Number of the block", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BitcoinBlock" - } - } - } - }, - "400": { - "description": "Invalid block number supplied" - }, - "404": { - "description": "Block not found" - } - } - } - } - }, - "components": { - "schemas": { - "BitcoinBlock": { - "type": "object", - "properties": { - "hash": { - "type": "string" - }, - "height": { - "type": "integer", - "format": "int64" - }, - "time": { - "type": "string", - "format": "date-time" - } - } - } - } - } -} \ No newline at end of file diff --git a/docs/api.v1.yaml b/docs/bitcoin.v1.yaml similarity index 61% rename from docs/api.v1.yaml rename to docs/bitcoin.v1.yaml index 65965b8c..cd0f7bcc 100644 --- a/docs/api.v1.yaml +++ b/docs/bitcoin.v1.yaml @@ -1,94 +1,15 @@ -openapi: 3.0.0 +openapi: 3.0.1 servers: - - description: SwaggerHub API Auto Mocking - url: https://virtserver.swaggerhub.com/cybernode/Cyber.Search/1.0.7 - - url: 'http://search.cyber.fund/api' + - url: 'http://staging.cyber.fund:32901' info: description: Empty description - version: 1.0.7 - title: Cyber.Search API + version: 1.0.0 + title: Cyber.Search Bitcoin API tags: - - name: general - - name: search - description: Search operations - name: bitcoin description: Access to Bitcoin chain entites paths: - /ping: - get: - tags: - - general - summary: Ping command - description: 'Server health status command' - operationId: ping - responses: - '200': - description: 'Successful ping' - - /search: - get: - tags: - - search - summary: Multichain search - description: 'General endpoint to search chains entities' - operationId: search - parameters: - - name: query - in: query - description: Search query - required: true - schema: - type: string - - name: page - in: query - description: Result set page number (starts from 0) - required: false - schema: - type: integer - format: int32 - minimum: 0 - default: 0 - - name: pageSize - in: query - description: Size of the page - required: false - schema: - type: integer - format: int32 - minimum: 0 - default: 10 - - name: chains - in: query - description: Chains to lookup (Leave empty for all) - required: false - schema: - type: "array" - items: - $ref: "#/components/schemas/Chain" - style: form - explode: false - - name: entities - in: query - description: Entities to lookup (Leave empty for all) - required: false - schema: - type: "array" - items: - $ref: "#/components/schemas/ChainEntity" - style: form - explode: false - responses: - '200': - description: 'Successful search' - content: - application/json: - schema: - $ref: '#/components/schemas/SearchResponse' - '400': - description: 'Invalid query, page or pageSize parameters supplied' - - '/bitcoin/block/{blockNumber}': get: tags: @@ -143,7 +64,7 @@ paths: default: 50 - name: offset in: query - description: 'Transaction index offset in block' + description: 'Tx index offset in block' required: false schema: type: integer @@ -156,7 +77,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/BitcoinBlockTransaction' + $ref: '#/components/schemas/BitcoinBlockTx' '400': description: "Invalid 'blockNumber', 'count' or 'offset' parameters" '404': @@ -188,7 +109,7 @@ paths: default: 20 - name: offset in: query - description: 'Transaction offset in address list (sorted by time, most recent first)' + description: 'Tx offset in address list (sorted by time, most recent first)' required: false schema: type: integer @@ -201,7 +122,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/BitcoinAddressTransaction' + $ref: '#/components/schemas/BitcoinAddressTx' '400': description: "Invalid 'address', 'count' or 'offset' parameters" '404': @@ -211,71 +132,55 @@ paths: components: schemas: - Chain: - type: string - enum: - - BITCOIN - - BITCOIN_CASH - - ETHEREUM - - ETHEREUM_CLASSIC - - ChainEntity: - type: string - enum: - - BLOCK - - TRANSACTION - - ADDRESS - - ItemPreview: - type: object - properties: - chain: - $ref: "#/components/schemas/Chain" - entity: - $ref: "#/components/schemas/ChainEntity" - data: - type: object - anyOf: - - $ref: "#/components/schemas/BitcoinBlockPreview" +# Search Previews - SearchResponse: + BitcoinBlockPreview: type: object properties: - query: + hash: type: string - page: - type: integer - format: int32 - pageSize: - type: integer - format: int32 - totalHits: + height: type: integer format: int64 - searchTime: + time: + type: string + format: date-time + tx_number: type: integer - format: int64 - items: + format: int32 + total_outputs_value: + type: string + + BitcoinTxPreviewIO: + type: object + properties: + addresses: type: array items: - $ref: "#/components/schemas/ItemPreview" + type: string + amount: + type: string - BitcoinBlockPreview: + + BitcoinTxPreview: type: object properties: - hash: + txid: type: string - height: + block_hash: + type: string + block_number: type: integer format: int64 - time: + block_time: type: string format: date-time - tx_number: - type: integer - format: int32 - total_outputs_value: + fee: type: string + total_output: + type: string + +# Raw API Entities BitcoinBlock: allOf: @@ -316,9 +221,9 @@ components: transactionPreviews: type: array items: - $ref: "#/components/schemas/BitcoinBlockTransaction" + $ref: "#/components/schemas/BitcoinBlockTx" - BitcoinBlockTransaction: + BitcoinBlockTx: type: object properties: hash: @@ -331,44 +236,16 @@ components: ins: type: array items: - $ref: "#/components/schemas/BitcoinTransactionPreviewIO" + $ref: "#/components/schemas/BitcoinTxPreviewIO" outs: type: array items: - $ref: "#/components/schemas/BitcoinTransactionPreviewIO" + $ref: "#/components/schemas/BitcoinTxPreviewIO" - BitcoinTransactionPreviewIO: - type: object - properties: - addresses: - type: array - items: - type: string - amount: - type: string - - - BitcoinTransactionPreview: - type: object - properties: - txid: - type: string - block_hash: - type: string - block_number: - type: integer - format: int64 - block_time: - type: string - format: date-time - fee: - type: string - total_output: - type: string - BitcoinTransaction: + BitcoinTx: allOf: - - $ref: '#/components/schemas/BitcoinTransactionPreview' + - $ref: '#/components/schemas/BitcoinTxPreview' - type: object properties: coinbase: @@ -381,7 +258,7 @@ components: merkleroot: type: string - BitcoinTransactionIn: + BitcoinTxIn: type: object properties: addresses: @@ -398,7 +275,7 @@ components: type: integer format: int32 - BitcoinTransactionOut: + BitcoinTxOut: type: object properties: addresses: @@ -416,7 +293,7 @@ components: format: int32 - BitcoinAddressTransaction: + BitcoinContractTx: type: object properties: hash: @@ -432,8 +309,8 @@ components: ins: type: array items: - $ref: "#/components/schemas/BitcoinTransactionPreviewIO" + $ref: "#/components/schemas/BitcoinTxPreviewIO" outs: type: array items: - $ref: "#/components/schemas/BitcoinTransactionPreviewIO" \ No newline at end of file + $ref: "#/components/schemas/BitcoinTxPreviewIO" \ No newline at end of file diff --git a/docs/common.v1.yaml b/docs/common.v1.yaml new file mode 100644 index 00000000..66974070 --- /dev/null +++ b/docs/common.v1.yaml @@ -0,0 +1,18 @@ +openapi: 3.0.1 +components: + schemas: + + Chain: + type: string + enum: + - bitcoin + - bitcoin_cash + - ethereum + - ethereum_classic + + ChainEntity: + type: string + enum: + - block + - tx + - contract_summary \ No newline at end of file diff --git a/docs/ethereum.v1.yaml b/docs/ethereum.v1.yaml new file mode 100644 index 00000000..9b9734d6 --- /dev/null +++ b/docs/ethereum.v1.yaml @@ -0,0 +1,392 @@ +openapi: 3.0.1 +servers: + - url: 'http://staging.cyber.fund:32901' +info: + description: 'Access to Ethereum/Ethereum Classic chain entites.
To choose needed chain we use {chainName} parameter with ethereum or ethereum_classic value in url path.' + version: 1.0.0 + title: Cyber.Search Ethereum API +tags: + - name: ethereum + description: Access to Ethereum/Ethereum Classic chain entites +paths: + + '/{chainName}/block/{blockNumber}': + get: + tags: + - ethereum + summary: Find ethereum block by number + description: Returns a block + operationId: getBlockByNumber + parameters: + - name: chainName + in: path + description: Chain name + required: true + schema: + type: string + enum: + - ethereum + - ethereum_classic + - name: blockNumber + in: path + description: Number of the block + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: 'Block found' + content: + application/json: + schema: + $ref: '#/components/schemas/EthereumBlock' + '400': + description: 'Invalid block number supplied' + '404': + description: 'Block not found' + + + '/{chainName}/block/{blockNumber}/transactions': + get: + tags: + - ethereum + summary: 'Download block transactions' + description: Returns a block transactions + operationId: getBlockTransactionsByBlockNumber + parameters: + - name: chainName + in: path + description: Chain name + required: true + schema: + type: string + enum: + - ethereum + - ethereum_classic + - name: blockNumber + in: path + description: Number of the block + required: true + schema: + type: integer + format: int64 + - name: pageSize + in: query + description: 'Size of the page' + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 20 + - name: page + in: query + description: 'Result set page number (starts from 0)' + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 0 + responses: + '200': + description: 'Block transactions found' + content: + application/json: + schema: + $ref: '#/components/schemas/EthereumBlockTx' + '400': + description: "Invalid 'blockNumber', 'page' or 'pageSize' parameters" + '404': + description: 'Block not found' + + + '/{chainName}/address/{id}': + get: + tags: + - ethereum + summary: 'Find ethereum address info by address id' + description: 'Returns an address info' + operationId: getAddress + parameters: + - name: chainName + in: path + description: Chain name + required: true + schema: + type: string + enum: + - ethereum + - ethereum_classic + - name: id + in: path + description: 'Address id' + required: true + schema: + type: string + responses: + '200': + description: 'Address found' + content: + application/json: + schema: + $ref: '#/components/schemas/EthereumAddress' + '400': + description: "Invalid id supplied" + '404': + description: 'Address not found' + + '/{chainName}/address/{id}/transactions': + get: + tags: + - ethereum + summary: 'Download address transactions' + description: Returns an address transactions sorted by time (most recent first) + operationId: getAddressTransactionsByAddressId + parameters: + - name: chainName + in: path + description: Chain name + required: true + schema: + type: string + enum: + - ethereum + - ethereum_classic + - name: id + in: path + description: 'Address id' + required: true + schema: + type: string + - name: pageSize + in: query + description: 'Size of the page' + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 20 + - name: page + in: query + description: 'Result set page number (starts from 0)' + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 0 + responses: + '200': + description: 'Address transactions found' + content: + application/json: + schema: + $ref: '#/components/schemas/EthereumAddressTx' + '400': + description: "Invalid 'id', 'page' or 'pageSize' parameters" + '404': + description: 'Address not found' + + '/{chainName}/tx/{hash}': + get: + tags: + - ethereum + summary: Find ethereum transaction by its hash + description: Returns a transaction + operationId: getTxByHash + parameters: + - name: chainName + in: path + description: Chain name + required: true + schema: + type: string + enum: + - ethereum + - ethereum_classic + - name: hash + in: path + description: Hash of the transaction + required: true + schema: + type: string + responses: + '200': + description: 'Transaction found' + content: + application/json: + schema: + $ref: '#/components/schemas/EthereumTx' + '400': + description: 'Invalid transaction hash supplied' + '404': + description: 'Transaction not found' + +components: + schemas: + + EthereumBlock: + type: object + properties: + number: + type: integer + format: int64 + hash: + type: string + parent_hash: + type: string + timestamp: + type: string + format: date-time + sha3Uncles: + type: string + logsBloom: + type: string + transactionsRoot: + type: string + stateRoot: + type: string + receiptsRoot: + type: string + miner: + type: string + difficulty: + type: number + totalDifficulty: + type: number + extraData: + type: string + size: + type: integer + format: int64 + gasLimit: + type: integer + format: int64 + gasUsed: + type: integer + format: int64 + txNumber: + type: integer + format: int32 + uncles: + type: array + items: + type: string + blockReward: + type: string + unclesReward: + type: string + txFees: + type: string + + EthereumBlockTx: + type: object + properties: + blockNumber: + type: integer + format: int64 + positionInBlock: + type: integer + format: int32 + fee: + type: number + value: + type: number + hash: + type: string + from: + type: string + to: + type: string + createsContract: + type: boolean + + EthereumAddress: + type: object + properties: + id: + type: string + confirmedBalance: + type: number + contractAddress: + type: boolean + confirmedTotalReceived: + type: number + txNumber: + type: integer + format: int32 + minedUncleNumber: + type: integer + format: int32 + version: + type: integer + format: int64 + kafkaDeltaOffset: + type: integer + format: int64 + kafkaDeltaPartition: + type: integer + format: int32 + kafkaDeltaTopic: + type: string + kafkaDeltaOffsetCommited: + type: boolean + + EthereumAddressTx: + type: object + properties: + address: + type: string + blockTime: + type: string + format: date-time + hash: + type: string + fee: + type: number + from: + type: string + to: + type: string + value: + type: string + + EthereumTx: + type: object + properties: + hash: + type: string + nonce: + type: integer + format: int64 + blockHash: + type: string + blockNumber: + type: integer + format: int64 + blockTime: + type: string + format: date-time + from: + type: string + to: + type: string + value: + type: string + gasPrice: + type: number + gasLimit: + type: integer + format: int64 + gasUsed: + type: integer + format: int64 + fee: + type: string + input: + type: string + createdContract: + type: string diff --git a/docs/search.v1.yaml b/docs/search.v1.yaml new file mode 100644 index 00000000..33a86266 --- /dev/null +++ b/docs/search.v1.yaml @@ -0,0 +1,90 @@ +openapi: 3.0.1 +servers: + - url: 'http://staging.cyber.fund:32901' +info: + description: Multichain search + version: 1.0.0 + title: Cyber.Search API +tags: + - name: search +paths: + + /search: + get: + tags: + - search + summary: Multichain search + description: 'General endpoint to search chains entities' + operationId: search + parameters: + - name: query + in: query + description: Search query + required: true + schema: + type: string + - name: page + in: query + description: Result set page number (starts from 0) + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 0 + - name: pageSize + in: query + description: Size of the page + required: false + schema: + type: integer + format: int32 + minimum: 0 + default: 20 + responses: + '200': + description: 'Successful search' + content: + application/json: + schema: + $ref: '#/components/schemas/SearchResponse' + '400': + description: 'Invalid query, page or pageSize parameters supplied' + +components: + schemas: + + SearchResponse: + type: object + properties: + query: + type: string + page: + type: integer + format: int32 + pageSize: + type: integer + format: int32 + totalHits: + type: integer + format: int64 + searchTime: + type: integer + format: int64 + items: + type: array + items: + $ref: "#/components/schemas/ItemPreview" + + ItemPreview: + type: object + properties: + chain: + $ref: "common.v1.yaml#/components/schemas/Chain" + entity: + $ref: "common.v1.yaml#/components/schemas/ChainEntity" + data: + type: object + anyOf: + - $ref: "bitcoin.v1.yaml#/components/schemas/BitcoinBlockPreview" + - $ref: "bitcoin.v1.yaml#/components/schemas/BitcoinTxPreview" \ No newline at end of file diff --git a/search-api/src/main/kotlin/fund/cyber/api/ethereum/AddressHandlers.kt b/search-api/src/main/kotlin/fund/cyber/api/ethereum/AddressHandlers.kt index be032bec..e5c349d4 100644 --- a/search-api/src/main/kotlin/fund/cyber/api/ethereum/AddressHandlers.kt +++ b/search-api/src/main/kotlin/fund/cyber/api/ethereum/AddressHandlers.kt @@ -1,7 +1,7 @@ package fund.cyber.api.ethereum import fund.cyber.api.common.asSingleRouterFunction -import fund.cyber.api.ethereum.functions.AddressTxesByAddres +import fund.cyber.api.ethereum.functions.AddressTxesByAddress import fund.cyber.cassandra.ethereum.model.CqlEthereumAddressSummary import fund.cyber.cassandra.ethereum.repository.EthereumAddressRepository import fund.cyber.cassandra.ethereum.repository.PageableEthereumAddressTxRepository @@ -28,6 +28,7 @@ class AddressHandlersConfiguration { fun addressById(): RouterFunction { return EthereumFamilyChain.values().map { chain -> + val repository = applicationContext .getBean(chain.name + "addressRepository", EthereumAddressRepository::class.java) @@ -44,10 +45,11 @@ class AddressHandlersConfiguration { fun addressTxesByAddress(): RouterFunction { return EthereumFamilyChain.values().map { chain -> + val repository = applicationContext.getBean( chain.name + "pageableAddressTxRepository", PageableEthereumAddressTxRepository::class.java ) - val handler = AddressTxesByAddres(repository) + val handler = AddressTxesByAddress(repository) RouterFunctions.route(RequestPredicates.path("/${chain.lowerCaseName}/address/{id}/transactions"), handler) }.asSingleRouterFunction() } diff --git a/search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddres.kt b/search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddress.kt similarity index 97% rename from search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddres.kt rename to search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddress.kt index a64b53bd..f3f61e71 100644 --- a/search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddres.kt +++ b/search-api/src/main/kotlin/fund/cyber/api/ethereum/functions/AddressTxesByAddress.kt @@ -9,7 +9,7 @@ import org.springframework.web.reactive.function.server.ServerResponse import reactor.core.publisher.Mono import reactor.core.publisher.toFlux -class AddressTxesByAddres( +class AddressTxesByAddress( private val addressTxRepository: PageableEthereumAddressTxRepository ) : HandlerFunction {