From 2d227533cfe2ba583c801fb7a060e4bce56fecbc Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Wed, 21 Aug 2024 17:14:34 +0700 Subject: [PATCH 1/5] chore: support AccountState, DRepStakeDistribution local queries --- .../localstate/queries/AccountStateQuery.java | 48 ++++++++++++ .../queries/AccountStateQueryResult.java | 16 ++++ .../queries/DRepStakeDistributionQuery.java | 77 +++++++++++++++++++ .../DRepStakeDistributionQueryResult.java | 25 ++++++ .../localstate/queries/model/DRepStake.java | 18 +++++ 5 files changed, 184 insertions(+) create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQueryResult.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQueryResult.java create mode 100644 core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepStake.java diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQuery.java new file mode 100644 index 0000000..768c1e7 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQuery.java @@ -0,0 +1,48 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import co.nstant.in.cbor.model.Array; +import co.nstant.in.cbor.model.DataItem; +import co.nstant.in.cbor.model.UnsignedInteger; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.ToString; + +import java.math.BigInteger; +import java.util.List; + +@Getter +@AllArgsConstructor +@ToString +public class AccountStateQuery implements EraQuery { + @NonNull + private Era era; + + public AccountStateQuery() { + this.era = Era.Conway; + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array queryArray = new Array(); + queryArray.add(new UnsignedInteger(29)); + + return wrapWithOuterArray(queryArray); + } + + @Override + public AccountStateQueryResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + List dataItems = extractResultArray(di[0]); + + var treasuryDI = ((Array)dataItems.get(0)).getDataItems().get(0); + var reservesDI = ((Array)dataItems.get(0)).getDataItems().get(1); + + BigInteger treasury = ((UnsignedInteger)treasuryDI).getValue(); + BigInteger reserves = ((UnsignedInteger)reservesDI).getValue(); + + return new AccountStateQueryResult(treasury, reserves); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQueryResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQueryResult.java new file mode 100644 index 0000000..6a0169c --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/AccountStateQueryResult.java @@ -0,0 +1,16 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import java.math.BigInteger; + +@Getter +@AllArgsConstructor +@ToString +public class AccountStateQueryResult implements QueryResult { + private BigInteger treasury; + private BigInteger reserves; +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java new file mode 100644 index 0000000..49e9f88 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQuery.java @@ -0,0 +1,77 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import co.nstant.in.cbor.model.*; +import com.bloxbean.cardano.client.transaction.spec.governance.DRep; +import com.bloxbean.cardano.yaci.core.model.governance.Drep; +import com.bloxbean.cardano.yaci.core.protocol.handshake.messages.AcceptVersion; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.EraQuery; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.DRepStake; +import com.bloxbean.cardano.yaci.core.util.HexUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +import static com.bloxbean.cardano.yaci.core.util.CborSerializationUtil.toInt; + +@Getter +@ToString +@AllArgsConstructor +@Slf4j +public class DRepStakeDistributionQuery implements EraQuery { + private Era era; + private List dReps; + + public DRepStakeDistributionQuery(List dReps) { + this(Era.Conway, dReps); + } + + @Override + public DataItem serialize(AcceptVersion protocolVersion) { + Array array = new Array(); + array.add(new UnsignedInteger(26)); + + Array dRepArray = new Array(); + dReps.forEach(dRep -> dRepArray.add(dRep.serialize())); + + array.add(dRepArray); + + return wrapWithOuterArray(array); + } + + @Override + public DRepStakeDistributionQueryResult deserializeResult(AcceptVersion protocolVersion, DataItem[] di) { + DRepStakeDistributionQueryResult result = new DRepStakeDistributionQueryResult(); + + List dataItemList = extractResultArray(di[0]); + Map dRepStakeMap = (Map) dataItemList.get(0); + + for (var key : dRepStakeMap.getKeys()) { + var dRepDI = (Array) key; + int dRepType = toInt(dRepDI.getDataItems().get(0)); + + var votingPower = ((UnsignedInteger) dRepStakeMap.get(key)).getValue(); + Drep dRep = null; + if (dRepType == 0 || dRepType == 1) { + String hash = HexUtil.encodeHexString(((ByteString) dRepDI.getDataItems().get(1)).getBytes()); + dRep = dRepType == 0 ? Drep.addrKeyHash(hash) : Drep.scriptHash(hash); + } else if (dRepType == 2) { + dRep = Drep.abstain(); + } else if (dRepType == 3) { + dRep = Drep.noConfidence(); + } + + DRepStake dRepStake = DRepStake.builder() + .dRep(dRep) + .amount(votingPower) + .build(); + + result.addDRepStake(dRepStake); + } + + return result; + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQueryResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQueryResult.java new file mode 100644 index 0000000..b430416 --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStakeDistributionQueryResult.java @@ -0,0 +1,25 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries; + +import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; +import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.DRepStake; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@ToString +@AllArgsConstructor +public class DRepStakeDistributionQueryResult implements QueryResult { + List dRepStakes; + + public DRepStakeDistributionQueryResult() { + this.dRepStakes = new ArrayList<>(); + } + + public void addDRepStake(DRepStake dRepState) { + dRepStakes.add(dRepState); + } +} diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepStake.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepStake.java new file mode 100644 index 0000000..8b4004c --- /dev/null +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepStake.java @@ -0,0 +1,18 @@ +package com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model; + +import com.bloxbean.cardano.yaci.core.model.governance.Drep; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigInteger; + +@Getter +@Setter +@Builder +@ToString +public class DRepStake { + private Drep dRep; + private BigInteger amount; +} From ec54c91cdd69d58057f240abd9abced22c4ac0cc Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Wed, 21 Aug 2024 17:15:27 +0700 Subject: [PATCH 2/5] chore: add annotations --- .../protocol/localstate/queries/DRepStateQueryResult.java | 4 ++++ .../yaci/core/protocol/localstate/queries/GovStateResult.java | 2 ++ .../core/protocol/localstate/queries/model/DRepState.java | 2 ++ .../core/protocol/localstate/queries/model/EnactState.java | 2 ++ .../yaci/core/protocol/localstate/queries/model/Proposal.java | 2 ++ .../core/protocol/localstate/queries/model/RatifyState.java | 2 ++ 6 files changed, 14 insertions(+) diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java index fd63e5e..a12fd3e 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/DRepStateQueryResult.java @@ -2,14 +2,18 @@ import com.bloxbean.cardano.yaci.core.protocol.localstate.api.QueryResult; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.DRepState; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.ArrayList; import java.util.List; @Setter @Getter +@ToString +@AllArgsConstructor public class DRepStateQueryResult implements QueryResult { List dRepStates; diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java index 4b8fb29..49fb3c2 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/GovStateResult.java @@ -8,11 +8,13 @@ import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.model.RatifyState; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.List; @Getter @Setter +@ToString public class GovStateResult implements QueryResult { private Committee committee; private Constitution constitution; diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java index 9a9d5b2..7c471a0 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/DRepState.java @@ -4,12 +4,14 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.math.BigInteger; @Getter @Setter @Builder +@ToString public class DRepState { private String dRepHash; private Anchor anchor; diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java index ceb1f75..edbb324 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/EnactState.java @@ -7,12 +7,14 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.Map; @Getter @Setter @Builder +@ToString public class EnactState { private Committee committee; private Constitution constitution; diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java index f69d679..2d02efb 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/Proposal.java @@ -9,12 +9,14 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.Map; @Getter @Setter @Builder +@ToString public class Proposal { private GovActionId govActionId; private Map committeeVotes; diff --git a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java index 8fac2e2..24d1da3 100644 --- a/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java +++ b/core/src/main/java/com/bloxbean/cardano/yaci/core/protocol/localstate/queries/model/RatifyState.java @@ -4,12 +4,14 @@ import lombok.Builder; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.List; @Getter @Setter @Builder +@ToString public class RatifyState { private List enactedGovActions; private List expiredGovActions; From f922a49cd039888d57b77ee31defff710b869683 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Wed, 21 Aug 2024 17:15:39 +0700 Subject: [PATCH 3/5] chore: add tests in LocalStateQueryClientIT --- .../yaci/helper/LocalStateQueryClientIT.java | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java b/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java index fa6bb65..44b7685 100644 --- a/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java +++ b/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java @@ -1,7 +1,11 @@ package com.bloxbean.cardano.yaci.helper; import com.bloxbean.cardano.client.address.Address; +import com.bloxbean.cardano.client.transaction.spec.governance.Constitution; +import com.bloxbean.cardano.client.transaction.spec.governance.DRep; import com.bloxbean.cardano.yaci.core.common.Constants; +import com.bloxbean.cardano.yaci.core.model.Credential; +import com.bloxbean.cardano.yaci.core.model.certs.StakeCredType; import com.bloxbean.cardano.yaci.core.protocol.chainsync.messages.Point; import com.bloxbean.cardano.yaci.core.protocol.localstate.api.Era; import com.bloxbean.cardano.yaci.core.protocol.localstate.queries.*; @@ -12,7 +16,6 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import reactor.test.StepVerifier; - import java.math.BigInteger; import java.time.Duration; import java.time.LocalDate; @@ -297,4 +300,68 @@ void delegationRewardsQuery() { assertThat(rewards).hasSizeGreaterThanOrEqualTo(5); //only 5 regular staking keys has rewards } + @Test + void accountStateQuery() { + Mono mono = localStateQueryClient.executeQuery(new AccountStateQuery()); + mono = mono.log(); + + AccountStateQueryResult result = mono.block(Duration.ofSeconds(5)); + System.out.println(result); + } + + @Test + void dRepStakeDistributionQuery() { + Mono mono = localStateQueryClient.executeQuery( + new DRepStakeDistributionQuery( + List.of( + DRep.addrKeyHash("001021a9b538f693f5293b9ad77e9fd2febe5ecd66cf8bb2844b4a8d") + , DRep.scriptHash("1ffa2ae5f54e88a2e6a29642936aceebdd3aea948d70ace645912440") + )) + ); + + mono = mono.log(); + + DRepStakeDistributionQueryResult result = mono.block(Duration.ofSeconds(5)); + System.out.println( result); + } + + @Test + void govStateQuery() { + Mono mono = localStateQueryClient.executeQuery(new GovStateQuery()); + mono = mono.log(); + + GovStateResult result = mono.block(Duration.ofSeconds(10)); + System.out.println(result); + } + + @Test + void constitutionQuery() { + Mono mono = localStateQueryClient.executeQuery(new ConstitutionQuery()); + mono = mono.log(); + + ConstitutionResult result = mono.block(Duration.ofSeconds(5)); + System.out.println(result); + } + + @Test + void dRepStateQuery() { + Mono mono = localStateQueryClient.executeQuery(new DRepStateQuery( + List.of( + Credential + .builder() + .type(StakeCredType.ADDR_KEYHASH) + .hash("5e80b2b80990a738aece6d6068b2991eaea21c52e79c7974719ac275") + .build(), + Credential + .builder() + .type(StakeCredType.ADDR_KEYHASH) + .hash("6e066d1a8bce348956b34438556abb43d597d075f9fdab03bb6f4d39") + .build() + )) + ); + mono = mono.log(); + + DRepStateQueryResult result = mono.block(Duration.ofSeconds(5)); + System.out.println(result); + } } From 197eaa72f5c1543aac6aa919934fc59398ee97e3 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Thu, 22 Aug 2024 11:23:58 +0700 Subject: [PATCH 4/5] chore: add assertions in LocalStateQueryClientIT --- .../yaci/helper/LocalStateQueryClientIT.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java b/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java index 44b7685..22090db 100644 --- a/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java +++ b/helper/src/integrationTest/java/com/bloxbean/cardano/yaci/helper/LocalStateQueryClientIT.java @@ -302,17 +302,22 @@ void delegationRewardsQuery() { @Test void accountStateQuery() { - Mono mono = localStateQueryClient.executeQuery(new AccountStateQuery()); + Mono mono = localStateQueryClient.executeQuery(new AccountStateQuery(Era.Babbage)); + mono = mono.log(); - AccountStateQueryResult result = mono.block(Duration.ofSeconds(5)); - System.out.println(result); + StepVerifier + .create(mono) + .expectNextMatches(accountState -> accountState.getTreasury() != null && accountState.getReserves() != null) + .expectComplete() + .verify(); } @Test void dRepStakeDistributionQuery() { Mono mono = localStateQueryClient.executeQuery( new DRepStakeDistributionQuery( + Era.Conway, List.of( DRep.addrKeyHash("001021a9b538f693f5293b9ad77e9fd2febe5ecd66cf8bb2844b4a8d") , DRep.scriptHash("1ffa2ae5f54e88a2e6a29642936aceebdd3aea948d70ace645912440") @@ -322,30 +327,32 @@ void dRepStakeDistributionQuery() { mono = mono.log(); DRepStakeDistributionQueryResult result = mono.block(Duration.ofSeconds(5)); - System.out.println( result); + assertThat(result.getDRepStakes()).isNotNull(); } @Test void govStateQuery() { - Mono mono = localStateQueryClient.executeQuery(new GovStateQuery()); + Mono mono = localStateQueryClient.executeQuery(new GovStateQuery(Era.Conway)); mono = mono.log(); GovStateResult result = mono.block(Duration.ofSeconds(10)); - System.out.println(result); + assertThat(result.getCommittee()).isNotNull(); + assertThat(result.getCurrentPParams()).isNotNull(); } @Test void constitutionQuery() { - Mono mono = localStateQueryClient.executeQuery(new ConstitutionQuery()); + Mono mono = localStateQueryClient.executeQuery(new ConstitutionQuery(Era.Conway)); mono = mono.log(); ConstitutionResult result = mono.block(Duration.ofSeconds(5)); - System.out.println(result); + assertThat(result).isNotNull(); } @Test void dRepStateQuery() { Mono mono = localStateQueryClient.executeQuery(new DRepStateQuery( + Era.Conway, List.of( Credential .builder() @@ -362,6 +369,6 @@ void dRepStateQuery() { mono = mono.log(); DRepStateQueryResult result = mono.block(Duration.ofSeconds(5)); - System.out.println(result); + assertThat(result.getDRepStates()).isNotNull(); } } From 80268f4d6f6759c3236ff8c37839dab8c36e8419 Mon Sep 17 00:00:00 2001 From: Sotatek-HuyLe3a Date: Thu, 22 Aug 2024 11:26:26 +0700 Subject: [PATCH 5/5] chore: implement AutoClosable for LocalClientProvider --- .../bloxbean/cardano/yaci/helper/LocalClientProvider.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/helper/src/main/java/com/bloxbean/cardano/yaci/helper/LocalClientProvider.java b/helper/src/main/java/com/bloxbean/cardano/yaci/helper/LocalClientProvider.java index dd3316b..cb0b75d 100644 --- a/helper/src/main/java/com/bloxbean/cardano/yaci/helper/LocalClientProvider.java +++ b/helper/src/main/java/com/bloxbean/cardano/yaci/helper/LocalClientProvider.java @@ -41,7 +41,7 @@ * */ @Slf4j -public class LocalClientProvider { +public class LocalClientProvider implements AutoCloseable { private String nodeSocketFile; private String host; private int port; @@ -224,4 +224,9 @@ public void addTxSubmissionListener(LocalTxSubmissionListener listener) { public void setLocalClientProviderListener(LocalClientProviderListener listener) { this.localClientProviderListener = listener; } + + @Override + public void close() throws Exception { + shutdown(); + } }