Skip to content

Commit 27004ba

Browse files
Mateusz Czeladkaclaude
andcommitted
feat: implement DRep vote delegation read operations and refactor delegation entities
Add complete read path for DRep vote delegations including database entities, repository, and service layer integration. Rename DelegationEntity to PoolDelegationEntity across codebase to distinguish pool delegation from vote delegation. Add GovernanceTransactions test generator for creating DRep registration and delegation test data. Key changes: - Add DrepVoteDelegationEntity, DrepVoteDelegationId, and DrepVoteDelegationRepository - Rename DelegationEntity → PoolDelegationEntity and update all references - Integrate DRep delegation queries with certIndex filter in LedgerBlockServiceImpl - Add mapper methods for DRep delegation entity-to-domain conversion - Add GovernanceTransactions class with DRep registration and delegation transactions - Update TestTransactionNames enum with DREP_REGISTER and DREP_VOTE_DELEGATION 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7464574 commit 27004ba

File tree

17 files changed

+355
-68
lines changed

17 files changed

+355
-68
lines changed

api/src/main/java/org/cardanofoundation/rosetta/api/block/mapper/TransactionMapper.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public interface TransactionMapper {
4747
@Mapping(target = "operationIdentifier", source = "index", qualifiedByName = "OperationIdentifier")
4848
Operation mapPoolRetirementToOperation(PoolRetirement model, OperationStatus status, int index);
4949

50-
StakePoolDelegation mapDelegationEntityToDelegation(DelegationEntity entity);
50+
StakePoolDelegation mapPoolDelegationEntityToDelegation(PoolDelegationEntity entity);
5151

5252
@Mapping(target = "status", source = "status.status")
5353
@Mapping(target = "type", constant = Constants.OPERATION_TYPE_STAKE_DELEGATION)
@@ -56,6 +56,24 @@ public interface TransactionMapper {
5656
@Mapping(target = "metadata.poolKeyHash", source = "model.poolId")
5757
Operation mapStakeDelegationToOperation(StakePoolDelegation model, OperationStatus status, int index);
5858

59+
default DRepDelegation mapDrepVoteDelegationEntityToDRepDelegation(DrepVoteDelegationEntity entity) {
60+
if (entity == null) {
61+
return null;
62+
}
63+
64+
return DRepDelegation.builder()
65+
.txHash(entity.getTxHash())
66+
.certIndex(entity.getCertIndex())
67+
.address(entity.getAddress())
68+
.drep(new DRepDelegation.DRep(
69+
entity.getDrepId(),
70+
convertDrepTypeStringToEnum(entity.getDrepType())
71+
))
72+
.build();
73+
}
74+
75+
com.bloxbean.cardano.client.transaction.spec.governance.DRepType convertDrepTypeStringToEnum(String drepType);
76+
5977
@Mapping(target = "status", source = "status.status")
6078
@Mapping(target = "type", constant = Constants.OPERATION_TYPE_DREP_VOTE_DELEGATION)
6179
@Mapping(target = "operationIdentifier", source = "index", qualifiedByName = "OperationIdentifier")

api/src/main/java/org/cardanofoundation/rosetta/api/block/mapper/TransactionMapperUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ public DRepParams convertDRepFromRosetta(DRepDelegation.DRep drep) {
8484
return DRepDelegation.DRep.convertDRepFromRosetta(drep);
8585
}
8686

87+
@Named("convertDrepTypeStringToEnum")
88+
public com.bloxbean.cardano.client.transaction.spec.governance.DRepType convertDrepTypeStringToEnum(@Nullable String drepType) {
89+
if (drepType == null) {
90+
return null;
91+
}
92+
93+
return switch (drepType) {
94+
case "ADDR_KEYHASH" -> com.bloxbean.cardano.client.transaction.spec.governance.DRepType.ADDR_KEYHASH;
95+
case "SCRIPTHASH" -> com.bloxbean.cardano.client.transaction.spec.governance.DRepType.SCRIPTHASH;
96+
case "ABSTAIN" -> com.bloxbean.cardano.client.transaction.spec.governance.DRepType.ABSTAIN;
97+
case "NO_CONFIDENCE" -> com.bloxbean.cardano.client.transaction.spec.governance.DRepType.NO_CONFIDENCE;
98+
default -> null;
99+
};
100+
}
101+
87102
@Named("mapAmountsToOperationMetadataInputWithCache")
88103
public OperationMetadata mapToOperationMetaDataInputWithCache(List<Amt> amounts,
89104
@Context Map<AssetFingerprint, TokenRegistryCurrencyData> metadataMap) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.cardanofoundation.rosetta.api.block.model.entity;
2+
3+
import jakarta.persistence.*;
4+
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
import lombok.Setter;
8+
9+
@Getter
10+
@Setter
11+
@NoArgsConstructor
12+
@Entity
13+
@Table(name = "vote_delegation")
14+
@IdClass(DrepVoteDelegationId.class)
15+
public class DrepVoteDelegationEntity {
16+
17+
@Id
18+
@Column(name = "tx_hash")
19+
private String txHash;
20+
21+
@Id
22+
@Column(name = "cert_index")
23+
private long certIndex;
24+
25+
@Column(name = "slot")
26+
private Long slot;
27+
28+
@Column(name = "block_number")
29+
private Long blockNumber;
30+
31+
@Column(name = "block_hash")
32+
private String blockHash;
33+
34+
@Column(name = "address")
35+
private String address;
36+
37+
@Column(name = "drep_hash")
38+
private String drepHash;
39+
40+
@Column(name = "drep_id")
41+
private String drepId;
42+
43+
@Column(name = "drep_type")
44+
private String drepType;
45+
46+
@Column(name = "credential")
47+
private String credential;
48+
49+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.cardanofoundation.rosetta.api.block.model.entity;
2+
3+
import java.io.Serializable;
4+
5+
import lombok.EqualsAndHashCode;
6+
7+
@EqualsAndHashCode
8+
public class DrepVoteDelegationId implements Serializable {
9+
10+
private String txHash;
11+
private long certIndex;
12+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
@NoArgsConstructor
1212
@Entity
1313
@Table(name = "delegation")
14-
@IdClass(DelegationId.class)
15-
public class DelegationEntity {
14+
@IdClass(PoolDelegationId.class)
15+
public class PoolDelegationEntity {
1616

1717
@Id
1818
@Column(name = "tx_hash")

api/src/main/java/org/cardanofoundation/rosetta/api/block/model/entity/DelegationId.java renamed to api/src/main/java/org/cardanofoundation/rosetta/api/block/model/entity/PoolDelegationId.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import lombok.EqualsAndHashCode;
66

77
@EqualsAndHashCode
8-
public class DelegationId implements Serializable {
8+
public class PoolDelegationId implements Serializable {
99

1010
private String txHash;
1111
private long certIndex;

api/src/main/java/org/cardanofoundation/rosetta/api/block/model/repository/DelegationRepository.java

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.cardanofoundation.rosetta.api.block.model.repository;
2+
3+
import java.util.List;
4+
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.stereotype.Repository;
7+
8+
import org.cardanofoundation.rosetta.api.block.model.entity.DrepVoteDelegationEntity;
9+
import org.cardanofoundation.rosetta.api.block.model.entity.DrepVoteDelegationId;
10+
11+
@Repository
12+
public interface DrepVoteDelegationRepository extends JpaRepository<DrepVoteDelegationEntity, DrepVoteDelegationId> {
13+
14+
List<DrepVoteDelegationEntity> findByTxHashInAndCertIndex(List<String> txHashes, long certIndex);
15+
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.cardanofoundation.rosetta.api.block.model.repository;
2+
3+
import java.util.List;
4+
5+
import org.springframework.data.jpa.repository.JpaRepository;
6+
import org.springframework.stereotype.Repository;
7+
8+
import org.cardanofoundation.rosetta.api.block.model.entity.PoolDelegationEntity;
9+
import org.cardanofoundation.rosetta.api.block.model.entity.PoolDelegationId;
10+
11+
@Repository
12+
public interface PoolDelegationRepository extends JpaRepository<PoolDelegationEntity, PoolDelegationId> {
13+
14+
List<PoolDelegationEntity> findByTxHashIn(List<String> txHashes);
15+
16+
}

api/src/main/java/org/cardanofoundation/rosetta/api/block/service/LedgerBlockServiceImpl.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public class LedgerBlockServiceImpl implements LedgerBlockService {
4747
private final BlockRepository blockRepository;
4848
private final TxRepository txRepository;
4949
private final StakeRegistrationRepository stakeRegistrationRepository;
50-
private final DelegationRepository delegationRepository;
50+
private final PoolDelegationRepository poolDelegationRepository;
51+
private final DrepVoteDelegationRepository drepVoteDelegationRepository;
5152
private final PoolRegistrationRepository poolRegistrationRepository;
5253
private final PoolRetirementRepository poolRetirementRepository;
5354
private final WithdrawalRepository withdrawalRepository;
@@ -233,7 +234,8 @@ private TransactionInfo findByTxHash(List<BlockTx> transactions) {
233234
try (ShutdownOnFailure scope = new ShutdownOnFailure()) {
234235
StructuredTaskScope.Subtask<List<AddressUtxoEntity>> utxos = scope.fork(() -> addressUtxoRepository.findByTxHashIn(utxHashes));
235236
StructuredTaskScope.Subtask<List<StakeRegistrationEntity>> sReg = scope.fork(() -> stakeRegistrationRepository.findByTxHashIn(txHashes));
236-
StructuredTaskScope.Subtask<List<DelegationEntity>> delegations = scope.fork(() -> delegationRepository.findByTxHashIn(txHashes));
237+
StructuredTaskScope.Subtask<List<PoolDelegationEntity>> poolDelegations = scope.fork(() -> poolDelegationRepository.findByTxHashIn(txHashes));
238+
StructuredTaskScope.Subtask<List<DrepVoteDelegationEntity>> drepDelegations = scope.fork(() -> drepVoteDelegationRepository.findByTxHashInAndCertIndex(txHashes, 0L));
237239
StructuredTaskScope.Subtask<List<PoolRegistrationEntity>> pReg = scope.fork(() -> poolRegistrationRepository.findByTxHashIn(txHashes));
238240
StructuredTaskScope.Subtask<List<PoolRetirementEntity>> pRet = scope.fork(() -> poolRetirementRepository.findByTxHashIn(txHashes));
239241
StructuredTaskScope.Subtask<List<WithdrawalEntity>> withdrawals = scope.fork(() -> withdrawalRepository.findByTxHashIn(txHashes));
@@ -245,7 +247,8 @@ private TransactionInfo findByTxHash(List<BlockTx> transactions) {
245247
return new TransactionInfo(
246248
utxos.get(),
247249
sReg.get(),
248-
delegations.get(),
250+
poolDelegations.get(),
251+
drepDelegations.get(),
249252
pReg.get(),
250253
pRet.get(),
251254
withdrawals.get(),
@@ -293,10 +296,10 @@ void populateTransaction(BlockTx transaction,
293296
.toList());
294297

295298
transaction.setStakePoolDelegations(
296-
fetched.delegations
299+
fetched.poolDelegations
297300
.stream()
298301
.filter(tx -> tx.getTxHash().equals(transaction.getHash()))
299-
.map(transactionMapper::mapDelegationEntityToDelegation)
302+
.map(transactionMapper::mapPoolDelegationEntityToDelegation)
300303
.toList());
301304

302305
transaction.setWithdrawals(
@@ -319,8 +322,13 @@ void populateTransaction(BlockTx transaction,
319322
.filter(tx -> tx.getTxHash().equals(transaction.getHash()))
320323
.map(transactionMapper::mapEntityToPoolRetirement)
321324
.toList());
322-
// TODO dRep Vote Delegations
323-
//transaction.setDRepDelegations(fetched.delegations
325+
326+
transaction.setDRepDelegations(
327+
fetched.drepDelegations
328+
.stream()
329+
.filter(tx -> tx.getTxHash().equals(transaction.getHash()))
330+
.map(transactionMapper::mapDrepVoteDelegationEntityToDRepDelegation)
331+
.toList());
324332

325333
// TODO governance votes
326334
//transaction.setGovernanceVotes(fetched.);
@@ -345,7 +353,8 @@ private static Map<UtxoKey, AddressUtxoEntity> getUtxoMapFromEntities(Transactio
345353

346354
record TransactionInfo(List<AddressUtxoEntity> utxos,
347355
List<StakeRegistrationEntity> stakeRegistrations,
348-
List<DelegationEntity> delegations,
356+
List<PoolDelegationEntity> poolDelegations,
357+
List<DrepVoteDelegationEntity> drepDelegations,
349358
List<PoolRegistrationEntity> poolRegistrations,
350359
List<PoolRetirementEntity> poolRetirements,
351360
List<WithdrawalEntity> withdrawals,

0 commit comments

Comments
 (0)