Skip to content

Commit

Permalink
(BREAKING CHANGE) Make fields in LedgerResult and LedgerHeader Option…
Browse files Browse the repository at this point in the history
…al (#91)

* Make LedgerHeader.closeTimeHuman and LedgerHeader.parentCloseTime optional.
Make LedgerResult.ledgerHash and LedgerResult.ledgerIndex optional.
Add LedgerResult.ledgerCurrentIndex for current ledgers.

Add a LedgerResult IT and an extra JSON test.

* test LedgerIndex and ser/deser
  • Loading branch information
nkramer44 authored Apr 14, 2021
1 parent ab7d110 commit 031e55a
Show file tree
Hide file tree
Showing 11 changed files with 267 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.xrpl.xrpl4j.tests;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.client.JsonRpcClientErrorException;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;
import org.xrpl.xrpl4j.model.client.ledger.LedgerRequestParams;
import org.xrpl.xrpl4j.model.client.ledger.LedgerResult;

/**
* These tests ensure {@link LedgerResult}s can be constructed from all of the different JSON responses
* rippled sends back.
*/
public class LedgerResultIT extends AbstractIT {

@Test
void getValidatedLedgerResult() throws JsonRpcClientErrorException {
final LedgerResult ledgerResult = xrplClient.ledger(LedgerRequestParams.builder()
.ledgerIndex(LedgerIndex.VALIDATED)
.build());
assertThat(ledgerResult.ledgerIndex()).isNotEmpty();
assertThat(ledgerResult.ledgerHash()).isNotEmpty();
assertThat(ledgerResult.ledgerCurrentIndex()).isEmpty();
assertThat(ledgerResult.ledger().closeTimeHuman()).isNotEmpty();
assertThat(ledgerResult.ledger().parentCloseTime()).isNotEmpty();
}

@Test
void getCurrentLedgerResult() throws JsonRpcClientErrorException {
final LedgerResult ledgerResult = xrplClient.ledger(LedgerRequestParams.builder()
.ledgerIndex(LedgerIndex.CURRENT)
.build());
assertThat(ledgerResult.ledgerIndex()).isEmpty();
assertThat(ledgerResult.ledgerHash()).isEmpty();
assertThat(ledgerResult.ledgerCurrentIndex()).isNotEmpty();
assertThat(ledgerResult.ledger().closeTimeHuman()).isEmpty();
assertThat(ledgerResult.ledger().parentCloseTime()).isEmpty();
}

@Test
void getClosedLedgerResult() throws JsonRpcClientErrorException {
final LedgerResult ledgerResult = xrplClient.ledger(LedgerRequestParams.builder()
.ledgerIndex(LedgerIndex.CLOSED)
.build());
assertThat(ledgerResult.ledgerIndex()).isNotEmpty();
assertThat(ledgerResult.ledgerHash()).isNotEmpty();
assertThat(ledgerResult.ledgerCurrentIndex()).isEmpty();
assertThat(ledgerResult.ledger().closeTimeHuman()).isNotEmpty();
assertThat(ledgerResult.ledger().parentCloseTime()).isNotEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ private void assertPaymentCloseTimeMatchesLedgerCloseTime(TransactionResult<Paym
LedgerRequestParams.builder().ledgerIndex(validatedPayment.ledgerIndex().get()).build());

assertThat(validatedPayment.transaction().closeDateHuman()).isNotEmpty();
assertThat(ledger.ledger().closeTimeHuman()).isNotEmpty();
assertThat(validatedPayment.transaction().closeDateHuman().get())
.isEqualTo(ledger.ledger().closeTimeHuman());
.isEqualTo(ledger.ledger().closeTimeHuman().get());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.xrpl.xrpl4j.model.ledger.LedgerHeader;
import org.xrpl.xrpl4j.model.transactions.Hash256;

import java.util.Optional;

/**
* The result of a "ledger" rippled API request.
*/
Expand All @@ -34,15 +36,24 @@ static ImmutableLedgerResult.Builder builder() {
* @return A {@link Hash256} containing the ledger hash.
*/
@JsonProperty("ledger_hash")
Hash256 ledgerHash();
Optional<Hash256> ledgerHash();

/**
* The {@link LedgerIndex} of this ledger.
*
* @return The {@link LedgerIndex} of this ledger.
*/
@JsonProperty("ledger_index")
LedgerIndex ledgerIndex();
Optional<LedgerIndex> ledgerIndex();

/**
* The {@link LedgerIndex} of this ledger, if the ledger is the current ledger. Only present on a current ledger
* response.
*
* @return A {@link LedgerIndex} if this result is for the current ledger, otherwise {@link Optional#empty()}.
*/
@JsonProperty("ledger_current_index")
Optional<LedgerIndex> ledgerCurrentIndex();

/**
* True if this data is from a validated ledger version; if false, this data is not final.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
/**
* Custom Jackson serializer for {@link LedgerIndex}s.
*/
// TODO: Unittest
public class LedgerIndexSerializer extends StdScalarSerializer<LedgerIndex> {

public LedgerIndexSerializer() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.google.common.primitives.UnsignedInteger;
import com.google.common.primitives.UnsignedLong;
import org.immutables.value.Value;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;
import org.xrpl.xrpl4j.model.client.transactions.TransactionResult;
import org.xrpl.xrpl4j.model.transactions.Hash256;
import org.xrpl.xrpl4j.model.transactions.Transaction;
Expand Down Expand Up @@ -36,7 +37,7 @@ static ImmutableLedgerHeader.Builder builder() {
* @return A {@link String} containing the ledger index.
*/
@JsonProperty("ledger_index")
String ledgerIndex();
LedgerIndex ledgerIndex();

/**
* The SHA-512Half of this ledger version. This serves as a unique identifier for this ledger and all its contents.
Expand Down Expand Up @@ -71,7 +72,7 @@ static ImmutableLedgerHeader.Builder builder() {
*/
@JsonProperty("close_time_human")
@JsonFormat(pattern = "yyyy-MMM-dd HH:mm:ss.SSSSSSSSS z")
ZonedDateTime closeTimeHuman();
Optional<ZonedDateTime> closeTimeHuman();

/**
* If true, this ledger version is no longer accepting new transactions. (However, unless this ledger
Expand Down Expand Up @@ -99,7 +100,7 @@ default boolean closed() {
* @return An {@link UnsignedLong} denoting this ledger's parent ledger's close time.
*/
@JsonProperty("parent_close_time")
UnsignedLong parentCloseTime();
Optional<UnsignedLong> parentCloseTime();

/**
* The total number of drops of XRP owned by accounts in the ledger. This omits XRP that has been
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.xrpl.xrpl4j.model.client.common;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import com.google.common.primitives.UnsignedLong;
import org.junit.jupiter.api.Test;

class LedgerIndexTest {

@Test
void createValidNumericalLedgerIndex() {
LedgerIndex ledgerIndex = LedgerIndex.of("1");
assertThat(ledgerIndex.value()).isEqualTo("1");

final LedgerIndex fromUnsignedLong = LedgerIndex.of(UnsignedLong.ONE);
assertThat(ledgerIndex).isEqualTo(fromUnsignedLong);

UnsignedLong unsignedLongFromString = ledgerIndex.unsignedLongValue();
UnsignedLong unsignedLongFromUnsignedLong = fromUnsignedLong.unsignedLongValue();
assertThat(unsignedLongFromString).isEqualTo(unsignedLongFromUnsignedLong);

final LedgerIndex added = ledgerIndex.plus(fromUnsignedLong);
assertThat(added).isEqualTo(LedgerIndex.of("2"));
}

@Test
void createInvalidNumericalLedgerIndex() {
final LedgerIndex fooLedgerIndex = LedgerIndex.of("foo");
assertThrows(
NumberFormatException.class,
fooLedgerIndex::unsignedLongValue
);

final LedgerIndex negativeLedgerIndex = LedgerIndex.of("-1");
assertThrows(
NumberFormatException.class,
negativeLedgerIndex::unsignedLongValue
);

assertThrows(
NumberFormatException.class,
() -> fooLedgerIndex.plus(negativeLedgerIndex)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void testJson() throws JsonProcessingException, JSONException {
.closeTimeResolution(UnsignedInteger.valueOf(10))
.closed(true)
.ledgerHash(Hash256.of("3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A"))
.ledgerIndex("54300940")
.ledgerIndex(LedgerIndex.of("54300940"))
.parentCloseTime(UnsignedLong.valueOf(638329270))
.parentHash(Hash256.of("AE996778246BC81F85D5AF051241DAA577C23BCA04C034A7074F93700194520D"))
.totalCoins(XrpCurrencyAmount.ofDrops(99991024049618156L))
Expand All @@ -51,7 +51,7 @@ public void testJson() throws JsonProcessingException, JSONException {
" \"close_time_resolution\": 10,\n" +
" \"closed\": true,\n" +
" \"ledger_hash\": \"3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A\",\n" +
" \"ledger_index\": \"54300940\",\n" +
" \"ledger_index\": 54300940,\n" +
" \"parent_close_time\": 638329270,\n" +
" \"parent_hash\": \"AE996778246BC81F85D5AF051241DAA577C23BCA04C034A7074F93700194520D\",\n" +
" \"total_coins\": \"99991024049618156\",\n" +
Expand All @@ -66,4 +66,32 @@ public void testJson() throws JsonProcessingException, JSONException {
assertCanSerializeAndDeserialize(result, json);

}

@Test
public void testCurrentJson() throws JsonProcessingException, JSONException {
LedgerResult ledgerResult = LedgerResult.builder()
.ledger(
LedgerHeader.builder()
.closed(false)
.ledgerIndex(LedgerIndex.of("4"))
.parentHash(Hash256.of("D2A87A6CA50F96068D0532C00EED693C631BFC03DD11D880E6157999A1C06538"))
.build()
)
.ledgerCurrentIndex(LedgerIndex.of("4"))
.status("success")
.validated(false)
.build();

String json = "{\n" +
" \"ledger\" : {\n" +
" \"closed\" : false,\n" +
" \"ledger_index\" : 4,\n" +
" \"parent_hash\" : \"D2A87A6CA50F96068D0532C00EED693C631BFC03DD11D880E6157999A1C06538\"\n" +
" },\n" +
" \"ledger_current_index\" : 4,\n" +
" \"status\" : \"success\",\n" +
" \"validated\" : false\n" +
"}";
assertCanSerializeAndDeserialize(ledgerResult, json);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.xrpl.xrpl4j.model.jackson.modules;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;

public class AbstractLedgerIndexTest {

@Value.Immutable
@JsonSerialize(as = ImmutableLedgerIndexContainer.class)
@JsonDeserialize(as = ImmutableLedgerIndexContainer.class)
interface LedgerIndexContainer {

static LedgerIndexContainer of(LedgerIndex ledgerIndex) {
return ImmutableLedgerIndexContainer.builder()
.ledgerIndex(ledgerIndex)
.build();
}

LedgerIndex ledgerIndex();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.xrpl.xrpl4j.model.jackson.modules;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;
import org.xrpl.xrpl4j.model.jackson.ObjectMapperFactory;

class LedgerIndexDeserializerTest extends AbstractLedgerIndexTest {

private final ObjectMapper objectMapper = ObjectMapperFactory.create();

@Test
void deserializeCharacterLedgerIndex() throws JsonProcessingException {
final LedgerIndex current = LedgerIndex.CURRENT;
final LedgerIndex validated = LedgerIndex.VALIDATED;
final LedgerIndex closed = LedgerIndex.CLOSED;
final LedgerIndex foo = LedgerIndex.of("foo");

final LedgerIndex currentDeserialized = objectMapper.readValue("\"" + current.value() + "\"", LedgerIndex.class);
assertThat(currentDeserialized).isEqualTo(current);

final LedgerIndex validatedDeserialized = objectMapper.readValue("\"" + validated.value() + "\"", LedgerIndex.class);
assertThat(validatedDeserialized).isEqualTo(validated);

final LedgerIndex closedDeserialized = objectMapper.readValue("\"" + closed.value() + "\"", LedgerIndex.class);
assertThat(closedDeserialized).isEqualTo(closed);

final LedgerIndex fooDeserialized = objectMapper.readValue("\"" + foo.value() + "\"", LedgerIndex.class);
assertThat(fooDeserialized).isEqualTo(foo);
}

@Test
void deserializeNumericalLedgerIndex() throws JsonProcessingException {
final LedgerIndex ledgerIndex = LedgerIndex.of("1");

final LedgerIndex deserialized = objectMapper.readValue("\"1\"", LedgerIndex.class);
assertThat(deserialized).isEqualTo(ledgerIndex);

LedgerIndexContainer container = LedgerIndexContainer.of(ledgerIndex);
final LedgerIndexContainer deserializedContainer = objectMapper.readValue("{\"ledgerIndex\": 1}", LedgerIndexContainer.class);
assertThat(deserializedContainer).isEqualTo(container);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.xrpl.xrpl4j.model.jackson.modules;

import static org.assertj.core.api.Assertions.assertThat;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.primitives.UnsignedLong;
import org.junit.jupiter.api.Test;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;
import org.xrpl.xrpl4j.model.jackson.ObjectMapperFactory;

class LedgerIndexSerializerTest extends AbstractLedgerIndexTest {

private final ObjectMapper objectMapper = ObjectMapperFactory.create();

@Test
void serializeCharacterLedgerIndex() throws JsonProcessingException {
final LedgerIndex current = LedgerIndex.CURRENT;
final LedgerIndex validated = LedgerIndex.VALIDATED;
final LedgerIndex closed = LedgerIndex.CLOSED;
final LedgerIndex foo = LedgerIndex.of("foo");

final String currentSerialized = objectMapper.writeValueAsString(current);
assertThat(currentSerialized).isEqualTo("\"" + current.value() + "\"");

final String validatedSerialized = objectMapper.writeValueAsString(validated);
assertThat(validatedSerialized).isEqualTo("\"" + validated.value() + "\"");

final String closedSerialized = objectMapper.writeValueAsString(closed);
assertThat(closedSerialized).isEqualTo("\"" + closed.value() + "\"");

final String fooSerialized = objectMapper.writeValueAsString(foo);
assertThat(fooSerialized).isEqualTo("\"" + foo.value() + "\"");
}

@Test
void serializeNumericalLedgerIndex() throws JsonProcessingException {
final LedgerIndexContainer fromUnsignedLong = LedgerIndexContainer.of(LedgerIndex.of(UnsignedLong.ONE));
final LedgerIndexContainer fromString = LedgerIndexContainer.of(LedgerIndex.of("1"));

final String serializedFromUnsignedLong = objectMapper.writeValueAsString(fromUnsignedLong);
assertThat(serializedFromUnsignedLong).isEqualTo("{\"ledgerIndex\":1}");

final String serializedFromString = objectMapper.writeValueAsString(fromString);
assertThat(serializedFromString).isEqualTo("{\"ledgerIndex\":1}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.xrpl.xrpl4j.model.AbstractJsonTest;
import org.xrpl.xrpl4j.model.client.common.LedgerIndex;
import org.xrpl.xrpl4j.model.client.transactions.TransactionResult;
import org.xrpl.xrpl4j.model.flags.Flags;
import org.xrpl.xrpl4j.model.transactions.Address;
Expand All @@ -34,7 +35,7 @@ public void deserializeLedgerHeaderWithTransactions() throws JsonProcessingExcep
.closeTimeResolution(UnsignedInteger.valueOf(10))
.closed(true)
.ledgerHash(Hash256.of("3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A"))
.ledgerIndex("54300940")
.ledgerIndex(LedgerIndex.of("54300940"))
.parentCloseTime(UnsignedLong.valueOf(638329270))
.parentHash(Hash256.of("AE996778246BC81F85D5AF051241DAA577C23BCA04C034A7074F93700194520D"))
.totalCoins(XrpCurrencyAmount.ofDrops(99991024049618156L))
Expand Down Expand Up @@ -77,7 +78,7 @@ public void deserializeLedgerHeaderWithTransactions() throws JsonProcessingExcep
.build();

String json = "{\n" +
" \"ledger_index\" : \"54300940\",\n" +
" \"ledger_index\" : 54300940,\n" +
" \"ledger_hash\" : \"3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A\",\n" +
" \"account_hash\" : \"B258A8BB4743FB74CBBD6E9F67E4A56C4432EA09E5805E4CC2DA26F2DBE8F3D1\",\n" +
" \"close_time\" : 638329271,\n" +
Expand Down

0 comments on commit 031e55a

Please sign in to comment.