Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
3e862d9
chore: prepare 1.2.11 version.
Jun 27, 2025
7694c1c
feat: prefix support drep (#503)
VladislavKudrin Jul 1, 2025
55be39f
feat: SPO voting (governance) (#467)
matiwinnetou Jul 1, 2025
fe377c1
Merge branch 'main' into develop
matiwinnetou Jul 1, 2025
9c2d653
fix: relay port is not quaranteed? (#517)
matiwinnetou Jul 2, 2025
672517e
refactor: remove catalyst voting (#515)
matiwinnetou Jul 2, 2025
e91a677
Merge branch 'main' into develop
matiwinnetou Jul 2, 2025
1d737fd
feat: error log as default for prod / mainnet environments. (#520)
matiwinnetou Jul 3, 2025
3f27107
fix: not all errors were propagated. (#518)
matiwinnetou Jul 3, 2025
1793161
Merge remote-tracking branch 'origin/main' into develop
Jul 8, 2025
6ea021d
fix: adopt pool gov vote to use blake224 over pool credential.
Jul 8, 2025
209ec2f
fix: add config files for 10.4.1 (#529)
VladislavKudrin Jul 9, 2025
a609457
chore: bump mithril version (#530)
VladislavKudrin Jul 9, 2025
916b540
refactor: change of interface from gov_action and index to gov_action…
Jul 9, 2025
67021a6
feat: upgrade to yaci-store 0.1.4, yaci-core 0.3.7 which has store.co…
matiwinnetou Jul 9, 2025
86e97e5
refactor: rename governance_action to governance_action_hash across t…
linconvidal Jul 10, 2025
fc896ac
chore: adding node waiter
Kartiiyer12 Jul 11, 2025
6adfec9
adding separete file for integration test for indexer
Kartiiyer12 Jul 11, 2025
2cae82b
refactor: update governance action mapping to use governanceActionHash
linconvidal Jul 11, 2025
b8adbf4
refactor: update governance action handling to use governanceActionHa…
linconvidal Jul 11, 2025
6cad9e7
fix: broken build fix.
Jul 11, 2025
9b6ac7b
Merge remote-tracking branch 'origin/main' into develop
Jul 11, 2025
c726ad7
Chore/node sync check (#531)
Kartiiyer12 Jul 11, 2025
9bb6aa5
Merge remote-tracking branch 'origin/main' into develop
Jul 17, 2025
5837645
Merge remote-tracking branch 'origin/develop' into develop
Jul 17, 2025
9664983
fix: idempotency fix
Jul 17, 2025
ad2bbe0
chore: fix Postman collection with governance_action_hash references
linconvidal Jul 22, 2025
4054519
chore: update cbor values in tests and Postman collection according t…
linconvidal Jul 22, 2025
15ffd5b
fix: preprod variable fix
Jul 24, 2025
3116d4c
fix: gov action hash fixes
Jul 24, 2025
5d937cf
chore: version bump to 1.3.0
Jul 24, 2025
57ebcec
refactor: refactored into nested tests.
Jul 24, 2025
ef0846e
fix: update Dockerfile to include wget ca-certificates and correct co…
tienna Jul 25, 2025
db00fd6
fix: review upserting fix.
Jul 25, 2025
f9d0210
Merge remote-tracking branch 'origin/main' into develop
Jul 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .env.IntegrationTest
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,10 @@ DB_POSTGRES_JIT=off
DB_POSTGRES_BGWRITER_LRU_MAXPAGES=50
DB_POSTGRES_BGWRITER_DELAY=500ms

SYNC_GRACE_SLOTS_COUNT=100
SYNC_GRACE_SLOTS_COUNT=100

## When set to true, the parsing / processing blockchain data even if an error occurs.
CONTINUE_PARSING_ON_ERROR=false

## Indexer sync starts after node is at tip. Set false for offline mode.
SYNC=false
12 changes: 9 additions & 3 deletions .env.docker-compose
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Main variables
API_SPRING_PROFILES_ACTIVE=online
LOG=INFO
LOG=ERROR
NETWORK=mainnet
# mainnet, preprod, preview, devkit
PROTOCOL_MAGIC=764824073
Expand Down Expand Up @@ -34,7 +34,7 @@ CARDANO_CONFIG=./config/node/${NETWORK}

## Mithril
MITHRIL_SYNC=true
MITHRIL_VERSION=2517.1
MITHRIL_VERSION=2524.0
SNAPSHOT_DIGEST=latest
# if not set standard values will be used
AGGREGATOR_ENDPOINT=
Expand Down Expand Up @@ -99,4 +99,10 @@ SYNC_GRACE_SLOTS_COUNT=100
## Monitoring variables
PROMETHEUS_PORT=9090
GRAFANA_PORT=3000
POSTGRESQL_EXPORTER_PORT=9187
POSTGRESQL_EXPORTER_PORT=9187

## When set to true, the parsing / processing blockchain data even if an error occurs.
CONTINUE_PARSING_ON_ERROR=true

## Indexer sync starts after node is at tip. Set false for offline mode.
SYNC=true
10 changes: 8 additions & 2 deletions .env.docker-compose-preprod
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ NODE_SUBMIT_API_PORT=8090
CARDANO_NODE_DIR=/opt/rosetta-java-preprod/node_data
CARDANO_NODE_SOCKET_PATH=${CARDANO_NODE_DIR}/node.socket
CARDANO_NODE_DB=${CARDANO_NODE_DIR}/db
CARDANO_CONFIG=./config/${NETWORK}
CARDANO_CONFIG=./config/node/${NETWORK}

## Mithril
MITHRIL_SYNC=true
MITHRIL_VERSION=2517.1
MITHRIL_VERSION=2524.0
SNAPSHOT_DIGEST=latest
# if not set standard values will be used
AGGREGATOR_ENDPOINT=
Expand Down Expand Up @@ -96,6 +96,12 @@ API_DB_LEAK_CONNECTIONS_WARNING_MS=60000

SYNC_GRACE_SLOTS_COUNT=100

## When set to true, the parsing / processing blockchain data even if an error occurs.
CONTINUE_PARSING_ON_ERROR=false

## Indexer sync starts after node is at tip. Set false for offline mode.
SYNC=true

## Monitoring variables
PROMETHEUS_PORT=9090
GRAFANA_PORT=3000
Expand Down
8 changes: 7 additions & 1 deletion .env.h2
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,10 @@ DB_POSTGRES_BGWRITER_DELAY=500ms
# Path to local cardano node socket (Yaci DevKit)
CARDANO_NODE_SOCKET_PATH=${HOME}/.yaci-cli/local-clusters/default/node/node.sock

SYNC_GRACE_SLOTS_COUNT=100
SYNC_GRACE_SLOTS_COUNT=100

## When set to true, the parsing / processing blockchain data even if an error occurs.
CONTINUE_PARSING_ON_ERROR=false

## Indexer sync starts after node is at tip. Set false for offline mode.
SYNC=false
8 changes: 7 additions & 1 deletion .env.h2-testdata
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,10 @@ DB_POSTGRES_BGWRITER_DELAY=500ms
# Path to local cardano node socket (Yaci DevKit)
CARDANO_NODE_SOCKET_PATH=${HOME}/.yaci-cli/local-clusters/default/node/node.sock

SYNC_GRACE_SLOTS_COUNT=100
SYNC_GRACE_SLOTS_COUNT=100

## When set to true, the parsing / processing blockchain data even if an error occurs.
CONTINUE_PARSING_ON_ERROR=false

## Indexer sync starts after node is at tip. Set false for offline mode.
SYNC=false
67 changes: 67 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
Rosetta-Java Cardano Application — Development Guide (Context Window For AI Agents)

✅ Overview

This project is a Java implementation of the Rosetta specification, adapted from Coinbase’s original mesh. It targets the Cardano blockchain and is optimized for performance, scalability, and testability.


🛠️ Technologies & Standards
• Java 24 – Latest LTS features leveraged.
• Lombok – For reducing boilerplate (e.g., getters, constructors).
• Hibernate + JOOQ – A hybrid approach planned:
• Hibernate for standard ORM tasks.
• JOOQ for complex SQL operations.
• Hibernate for standard ORM needs.
• JOOQ for high-performance, complex SQL queries.
• Flywheel – Used for event-sourced state and domain logic.
• OpenAPI (api.yaml) – Contract-first approach:
• Edit src/main/resources/rosetta-specifications-1.4.15/api.yaml for API changes.
• Code generation tools automatically create request/response classes.
• No Spring RestControllers – All endpoints are generated from OpenAPI spec; avoid manually annotating endpoints.
• JUnit 5 with @Nested tests – Organize tests into logical groups.
• AssertJ – Preferred assertion framework for fluent and expressive assertions.


📋 Step-by-Step Context Window / Discovery

1. Rosetta API Specification
• Maintained in:
src/main/resources/rosetta-specifications-1.4.15/api.yaml
• ❗ All endpoints and models are generated, do not manually modify controller classes.

2. Code Generation
• Triggered via build tools (Gradle/Maven).
• Output includes:
• DTOs
• Server interfaces
• Clients
• Ensures OpenAPI remains the single source of truth.

3. Persistence Layer
• Hibernate handles standard CRUD and entity management.
• JOOQ will be used for:
• Bulk operations
• Deep filtering
• Custom joins / window functions
• Both work seamlessly alongside Flywheel event sourcing.

4. Domain Logic with Flywheel
• Domain state transitions are event-driven.
• Promotes traceability and immutability.

5. Testing Strategy
• JUnit 5 with @Nested classes to:
• Separate concerns within test files.
• Improve readability and scope clarity.
• AssertJ provides fluent API for:
• Clean, expressive assertions.
• Better failure messages than vanilla JUnit or Hamcrest.


📎 Notes
• Avoid using @RestController or manual API layer.
• All changes to API contract must be made in api.yaml.
• Lombok annotations (@Value, @Builder, @Getter, etc.) are preferred to minimize boilerplate.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

## What the project is about?


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.

Expand Down Expand Up @@ -99,15 +100,15 @@ For every Release we provide pre-built docker images stored in the DockerHub Rep
To start it use the following command:

```bash
docker run --name rosetta -v {CUSTOM_MOUNT_PATH}:/node --env-file ./docker/.env.dockerfile --env-file ./docker/.env.docker-profile-mid-level -p 8082:8082 --shm-size=4g -d cardanofoundation/cardano-rosetta-java:1.2.10
docker run --name rosetta -v {CUSTOM_MOUNT_PATH}:/node --env-file ./docker/.env.dockerfile --env-file ./docker/.env.docker-profile-mid-level -p 8082:8082 --shm-size=4g -d cardanofoundation/cardano-rosetta-java:1.3.0
```

Changes to the configuration can be made by adjusting the `docker/.env.dockerfile` file. For more information on the environment variables, please refer to the [documentation](https://cardano-foundation.github.io/cardano-rosetta-java/docs/install-and-deploy/env-vars).

If you want to use the `cardano-submit-api` you can additionally expose port `8090`. It can then be used to submit raw cbor transaction (API documentation here: [Link](https://input-output-hk.github.io/cardano-rest/submit-api/))

```bash
docker run --name rosetta -v {CUSTOM_MOUNT_PATH}:/node --env-file ./docker/.env.dockerfile --env-file ./docker/.env.docker-profile-mid-level -p 8090:8090 -p 8082:8082 --shm-size=4g -d cardanofoundation/cardano-rosetta-java:1.2.10
docker run --name rosetta -v {CUSTOM_MOUNT_PATH}:/node --env-file ./docker/.env.dockerfile --env-file ./docker/.env.docker-profile-mid-level -p 8090:8090 -p 8082:8082 --shm-size=4g -d cardanofoundation/cardano-rosetta-java:1.3.0
```

### Docker compose
Expand Down
Empty file modified api/mvnw
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
<sourceFolder>src/gen/java/main</sourceFolder>
<useJakartaEe>true</useJakartaEe>
<skipValidateSpec>true</skipValidateSpec>
<useEnumCaseInsensitive>true</useEnumCaseInsensitive>
<interfaceOnly>true</interfaceOnly>
<!--suppress UnresolvedMavenProperty -->
<additionalModelTypeAnnotations>@lombok.Builder @lombok.NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@SpringBootApplication
@EntityScan({
"org.cardanofoundation.rosetta.api.account.model.entity",
"org.cardanofoundation.rosetta.api.error.model.entity",
"org.cardanofoundation.rosetta.api.block.model.entity",
"org.cardanofoundation.rosetta.api.construction.model.entity",
"org.cardanofoundation.rosetta.api.network.model.entity",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ public interface TransactionMapper {
@Mapping(target = "metadata.drep", source = "model.drep", qualifiedByName = "convertDRepFromRosetta")
Operation mapDRepDelegationToOperation(DRepDelegation model, OperationStatus status, int index);

@Mapping(target = "status", source = "status.status")
@Mapping(target = "type", constant = Constants.OPERATION_TYPE_POOL_GOVERNANCE_VOTE)
@Mapping(target = "operationIdentifier", source = "index", qualifiedByName = "OperationIdentifier")
@Mapping(target = "metadata.poolGovernanceVoteParams.governanceActionHash", source = "governancePoolVote.govActionId", qualifiedByName = "convertGovActionIdToRosetta")
@Mapping(target = "metadata.poolGovernanceVoteParams.poolCredential", source = "governancePoolVote.poolCredentialHex", qualifiedByName = "convertPoolCredentialToRosetta")
@Mapping(target = "metadata.poolGovernanceVoteParams.vote", source = "governancePoolVote.vote", qualifiedByName = "convertGovVoteToRosetta")
@Mapping(target = "metadata.poolGovernanceVoteParams.voteRationale", source = "governancePoolVote.voteRationale", qualifiedByName = "convertGovAnchorFromRosetta")
Operation mapGovernanceVoteToOperation(GovernancePoolVote governancePoolVote, OperationStatus status, int index);

@Mapping(target = "type", constant = Constants.INPUT)
@Mapping(target = "coinChange.coinAction", source = "model", qualifiedByName = "getCoinSpentAction")
@Mapping(target = "metadata", source = "model.amounts", qualifiedByName = "mapAmountsToOperationMetadataInput")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,71 @@
package org.cardanofoundation.rosetta.api.block.mapper;

import java.math.BigInteger;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Component;
import com.bloxbean.cardano.client.transaction.spec.governance.Anchor;
import com.bloxbean.cardano.client.transaction.spec.governance.Vote;
import com.bloxbean.cardano.client.transaction.spec.governance.actions.GovActionId;
import com.bloxbean.cardano.yaci.core.model.certs.CertificateType;
import org.mapstruct.Named;
import org.openapitools.client.model.*;

import lombok.RequiredArgsConstructor;
import org.cardanofoundation.rosetta.api.account.model.domain.Amt;
import org.cardanofoundation.rosetta.api.account.model.domain.Utxo;
import org.cardanofoundation.rosetta.api.block.model.domain.DRepDelegation;
import org.cardanofoundation.rosetta.api.block.model.domain.GovernancePoolVote;
import org.cardanofoundation.rosetta.api.block.model.domain.StakeRegistration;
import org.cardanofoundation.rosetta.common.enumeration.OperationType;
import org.cardanofoundation.rosetta.common.mapper.DataMapper;
import org.cardanofoundation.rosetta.common.services.ProtocolParamService;
import org.cardanofoundation.rosetta.common.util.Constants;
import org.mapstruct.Named;
import org.openapitools.client.model.*;
import org.springframework.stereotype.Component;

import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class TransactionMapperUtils {

final ProtocolParamService protocolParamService;

@Named("convertGovAnchorFromRosetta")
public GovVoteRationaleParams convertGovAnchorFromRosetta(Anchor anchor) {
return GovernancePoolVote.convertFromRosetta(anchor);
}

@Named("convertGovVoteRationaleToRosetta")
public Anchor convertGovVoteRationaleToRosetta(GovVoteRationaleParams params) {
return GovernancePoolVote.convertToRosetta(params);
}

@Named("convertGovVoteToRosetta")
public GovVoteParams convertGovVoteFromRosetta(Vote vote) {
return GovernancePoolVote.convertFromRosetta(vote);
}

@Named("convertGovVoteToRosetta")
public Vote convertGovVoteToRosetta(GovVoteParams voteParams) {
return GovernancePoolVote.convertToRosetta(voteParams);
}

@Named("convertGovActionIdToRosetta")
public String convertGovActionIdFromRosetta(GovActionId govActionId) {
return GovernancePoolVote.convertFromRosetta(govActionId);
}

@Named("convertGovActionIdToRosetta")
public GovActionId convertGovActionIdToRosetta(String govActionParamsString) {
return GovernancePoolVote.convertGovActionIdToRosetta(govActionParamsString);
}

@Named("convertPoolCredentialToRosetta")
public PublicKey convertPoolCredentialToRosetta(String poolCredentialHex) {
return GovernancePoolVote.convertToRosetta(poolCredentialHex);
}

@Named("convertDRepToRosetta")
public DRepDelegation.DRep convertDRepToRosetta(DRepParams dRepParams) {
return DRepDelegation.DRep.convertDRepToRosetta(dRepParams);
Expand Down Expand Up @@ -72,6 +109,7 @@ public OperationMetadata mapToOperationMetaData(boolean spent, List<Amt> amounts
.build()
)
);

return Objects.isNull(operationMetadata.getTokenBundle()) ? null : operationMetadata;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class BlockTx {
protected List<StakeRegistration> stakeRegistrations;
protected List<StakePoolDelegation> stakePoolDelegations;
protected List<DRepDelegation> dRepDelegations;
protected List<GovernancePoolVote> governancePoolVotes;
protected List<PoolRegistration> poolRegistrations;
protected List<PoolRetirement> poolRetirements;
protected List<Withdrawal> withdrawals;
Expand Down
Loading