Skip to content

Commit

Permalink
Merge branch 'main' into feat/RA-64-Containerisation-for-Distribution
Browse files Browse the repository at this point in the history
  • Loading branch information
Kammerlo committed May 8, 2024
2 parents 3e889d0 + bc72d97 commit 34612f5
Show file tree
Hide file tree
Showing 26 changed files with 97 additions and 444 deletions.
80 changes: 0 additions & 80 deletions CONTRIBUTING.md

This file was deleted.

84 changes: 6 additions & 78 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,14 @@
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=cardano-foundation_cardano-rosetta-java&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=cardano-foundation_cardano-rosetta-java)

# Cardano Rosetta API Java implementation
This repository provides a lightweight java implementation of the Rosetta API. It uses [Yaci-Store](https://github.com/bloxbean/yaci-store) as an indexer
to fetch the data from the node.
## What the project is about?

## :construction: Current Development status :construction:
- [x] Architecture clean up for yaci-store
- [x] Docker-compose setup
- [x] Integration test setup
- API calls
- Data API
- [x] /network/*
- [x] /block/*
- [x] /account/*
- /mempool
- [x] /mempool
- [ ] /mempool/transaction
- [x] Construction API
- [ ] Extending Tests
- [ ] Refactoring
This repository provides a lightweight java implementation of the [Rosetta API](https://github.com/coinbase/mesh-specifications). It uses [Yaci-Store](https://github.com/bloxbean/yaci-store) as an indexer
to fetch the data from a Cardano node.

## Getting Started

### Prerequisites
## Documentation

- Docker
- Docker Compose
- Java 21
- For integration tests: Node 14+

### How to build

- Clone the repository
- For local environment:
- Copy `.env.docker-compose` to `.env`
- Fill the `.env` file with your values (explain below) or use the provided for docker-compose setup
- Start SpringBoot application with `mvn spring-boot:run` within submodule `api` or `yaci-indexer`
- Run `docker compose -f docker-compose.yaml up --build` to start rosetta api service including yaci-store and a cardano node
- Using the provided env file `docker-compose --env-file .env.docker-compose -f docker-compose.yaml up --build`
* Note: the first time you run the command, it will take a little bit of your time to build the cardano-node, and next time it will be cached when run. So please be patient.

### How to run integration tests

- Run `docker compose --env-file .env.IntegrationTest -f docker-integration-test-environment.yaml up --build -d --wait`
- Using CLI
- Install newman `npm install -g newman` (Node version 14+ needed)
- Run `newman run ./postmanTests/rosetta-java.postman_collection.json -e ./postmanTests/Rosetta-java-env.postman_environment.json -r cli`
- Using Postman
- Install [Postman](https://www.postman.com)
- Import the collection `./postmanTests/rosetta-java.postman_collection.json`
- Import the environment `./postmanTests/Rosetta-java-env.postman_environment.json`
- Run the collection


### Restore a snapshot
**TBD for yaci-store**

A node snapshot can be downloaded from [here](https://csnapshots.io/). Download the snapshot and place the files within the `CARDANO_NODE_DB` Path.

For mainnet the following command can be used to restore the snapshot:
```bash
curl -o - https://downloads.csnapshots.io/mainnet/$(curl -s https://downloads.csnapshots.io/mainnet/mainnet-db-snapshot.json| jq -r .[].file_name ) | lz4 -c -d - | tar -x -C ${CARDANO_NODE_DB}
```

### Mempool Monitoring
Mempool monitoring can be activated when adding the spring profile `mempool` to the rosetta api service.
It will be turned off by default. Since it is only working for nodes, which participate in the network and available within P2P from other nodes.
So the Node itself needs extra configuration to be able to query mempool transactions.

### Documentation
- [Architecture Overview](https://github.com/cardano-foundation/cardano-rosetta-java/wiki)
- [Cardano specific API Additions](./docs/cardano-specific-api-additions.md)
- [Dev H2 Quickstart Guide](./docs/dev-h2-quick-start-guide.md)
- [Environment Variables](./docs/environment-variables.md)
- [Rosetta-cli tests](./docs/rosetta-cli-tests.md)

## Contributing

File an issue or a PR or reach out directly to us if you want to contribute.

When contributing to this project and interacting with others, please follow our [Contributing Guidelines](./CONTRIBUTING.md) and [Code of Conduct](./CODE-OF-CONDUCT.md).
Please refer to our [wiki pages](https://github.com/cardano-foundation/cardano-rosetta-java/wiki) for more information on the project.

---

Thanks for visiting and enjoy :heart:!
Thanks for visiting us and enjoy :heart:!
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ public interface AddressBalanceRepository extends
// "WHERE b.address = :address AND b.blockNumber <= :number " +
// "GROUP BY b.address, b.unit, b.quantity, b.addrFull, b.policy, b.assetName, b.paymentCredential, b.stakeAddress, b.blockHash, b.epoch")
@Query(value =
"SELECT b from AddressBalanceEntity b WHERE b.blockNumber in (SELECT MAX(c.blockNumber) FROM AddressBalanceEntity c WHERE c.address = :address AND c.blockNumber <= :number GROUP BY c.unit) AND b.address = :address")
"""
SELECT b FROM AddressBalanceEntity b
WHERE (b.blockNumber, b.unit) in
(SELECT MAX(c.blockNumber), c.unit FROM AddressBalanceEntity c
WHERE c.address = :address AND c.blockNumber <= :number
GROUP BY c.unit)
AND b.address = :address
""")
List<AddressBalanceEntity> findAddressBalanceByAddressAndBlockNumber(
@Param("address") String address, @Param("number") Long number);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class BlockTx {
protected String hash;
protected String blockHash;
protected Long blockNo;
protected String fee; // TODO can be removed if we found another way to calculate the size
protected String fee;
protected Long size;
protected Long scriptSize;
protected List<Utxo> inputs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class ProtocolParams {
private ExtraEntropy extraEntropy; //13
private ProtocolVersion protocolVersion; //14
@JsonProperty("minUTxOValue")
private BigInteger minUtxo; //TODO //15
private BigInteger minUtxoValue; //15

private BigInteger minPoolCost; //16
private BigInteger adaPerUtxoByte; //17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class ProtocolParamsEntity {
private String extraEntropy; //13
private Integer protocolMajorVer; //14
private Integer protocolMinorVer; //14
private BigInteger minUtxo; //TODO //15
private BigInteger minUtxo; //15

private BigInteger minPoolCost; //16
private BigInteger adaPerUtxoByte; //17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import java.io.IOException;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PostMapping;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -28,8 +27,7 @@ public interface NetworkApiDelegate {
@ApiResponse(responseCode = "400", description = "Invalid `body`")
}
)
@RequestMapping(
method = RequestMethod.POST,
@PostMapping(
value = "/network/list",
produces = { "application/json;charset=utf-8" },
consumes = { "application/json;charset=utf-8" }
Expand All @@ -45,8 +43,7 @@ ResponseEntity<NetworkListResponse> networkList(MetadataRequest metadataRequest)
@ApiResponse(responseCode = "400", description = "Invalid `body`")
}
)
@RequestMapping(
method = RequestMethod.POST,
@PostMapping(
value = "/network/options",
produces = { "application/json;charset=utf-8" },
consumes = { "application/json;charset=utf-8" }
Expand All @@ -62,8 +59,7 @@ ResponseEntity<NetworkOptionsResponse> networkOptions(NetworkRequest networkRequ
@ApiResponse(responseCode = "400", description = "Invalid `body`")
}
)
@RequestMapping(
method = RequestMethod.POST,
@PostMapping(
value = "/network/status",
produces = { "application/json;charset=utf-8" },
consumes = { "application/json;charset=utf-8" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import org.cardanofoundation.rosetta.common.enumeration.OperationType;
import org.cardanofoundation.rosetta.common.enumeration.OperationTypeStatus;
import org.cardanofoundation.rosetta.common.exception.ExceptionFactory;
import org.cardanofoundation.rosetta.common.exception.ServerException;
import org.cardanofoundation.rosetta.common.mapper.DataMapper;
import org.cardanofoundation.rosetta.common.model.cardano.network.Producer;
import org.cardanofoundation.rosetta.common.model.cardano.network.PublicRoot;
Expand Down Expand Up @@ -64,13 +63,12 @@ public class NetworkServiceImpl implements NetworkService {
private final ResourceLoader resourceLoader;

@PostConstruct
public void filePathExistingValidator() throws ServerException {
public void filePathExistingValidator() {
validator(topologyFilepath);
validator(genesisPath);
// validator(cardanoNodeVersion);
}

private void validator( String path) throws ServerException {
private void validator( String path) {
if(!new File(path).exists()) {
throw ExceptionFactory.configNotFoundException();
}
Expand Down Expand Up @@ -124,7 +122,6 @@ public NetworkOptionsResponse getNetworkOptions(NetworkRequest networkRequest)
.toList())
.historicalBalanceLookup(true)
.callMethods(new ArrayList<>())
// .balanceExemptions(loadExemptionsFile()) // TODO Removed to get it working clean - add balance exemptions
.mempoolCoins(false))
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,23 @@ public ResponseEntity<Error> handleGlobalException(Exception exception,
}

Error errorResponse;

if (exception instanceof ApiException apiException) {

errorResponse = apiException.getError();

} else if ( exception instanceof MethodArgumentNotValidException methodArgumentNotValidException){
List<String> errors = methodArgumentNotValidException.getBindingResult().getFieldErrors()
.stream().map(FieldError::getDefaultMessage).toList();
errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
Details.builder().message(
"An error occurred for request " + request.getRequestId() + ": "
+ errors ).build());
}
else {
errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
Details.builder().message(
"An error occurred for request " + request.getRequestId() + ": "
+ exception.getMessage()).build());
switch (exception) {
case ApiException apiException:
errorResponse = apiException.getError();
break;
case MethodArgumentNotValidException methodArgumentNotValidException:
List<String> errors = methodArgumentNotValidException.getBindingResult().getFieldErrors()
.stream().map(FieldError::getDefaultMessage).toList();
errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
Details.builder().message(
"An error occurred for request " + request.getRequestId() + ": "
+ errors ).build());
break;
default:
errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
Details.builder().message(
"An error occurred for request " + request.getRequestId() + ": "
+ exception.getMessage()).build());
}

return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import org.cardanofoundation.rosetta.common.services.LoggingService;

Expand All @@ -28,14 +27,4 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons

return true;
}

@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

}

@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

public class CborMapToOperation {

private CborMapToOperation() {}

public static Operation cborMapToOperation(Map operationMap) {
Operation operation = new Operation();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

public class CborMapToTransactionExtraData {

private CborMapToTransactionExtraData() {}

public static TransactionExtraData convertCborMapToTransactionExtraData(Map map) {
String transactionMetadataHex = getTransactionMetadataHexFromMap(map);

Expand Down

0 comments on commit 34612f5

Please sign in to comment.