diff --git a/pom.xml b/pom.xml index 66cc2104a..aea6c23f1 100644 --- a/pom.xml +++ b/pom.xml @@ -293,7 +293,7 @@ 2.14.2 12.3 2.0.7 - 5.10.0 + 5.10.1 32.1.1-jre @@ -375,7 +375,7 @@ maven-source-plugin - 3.1.0 + 3.3.0 attach-sources diff --git a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/client/ledger/LedgerEntryResult.java b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/client/ledger/LedgerEntryResult.java index 49d71c663..247a1b888 100644 --- a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/client/ledger/LedgerEntryResult.java +++ b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/client/ledger/LedgerEntryResult.java @@ -26,6 +26,8 @@ public interface LedgerEntryResult extends XrplResult { /** * Construct a {@code LedgerEntryResult} builder. * + * @param The type of {@link LedgerObject}. + * * @return An {@link ImmutableLedgerEntryResult.Builder}. */ static ImmutableLedgerEntryResult.Builder builder() { diff --git a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/jackson/modules/BaseFeeDropsDeserializer.java b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/jackson/modules/BaseFeeDropsDeserializer.java new file mode 100644 index 000000000..e7d282fe0 --- /dev/null +++ b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/jackson/modules/BaseFeeDropsDeserializer.java @@ -0,0 +1,61 @@ +package org.xrpl.xrpl4j.model.jackson.modules; + +/*- + * ========================LICENSE_START================================= + * xrpl4j :: model + * %% + * Copyright (C) 2020 - 2022 XRPL Foundation and its contributors + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================LICENSE_END================================== + */ + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.google.common.primitives.UnsignedLong; +import org.xrpl.xrpl4j.model.transactions.SetFee; +import org.xrpl.xrpl4j.model.transactions.XrpCurrencyAmount; + +import java.io.IOException; + +/** + * Custom Jackson deserializer for {@link XrpCurrencyAmount} instances found in {@link SetFee}. + * + *

Before the XRPFees amendment, a {@link SetFee} + * transaction serializes its `BaseFee` to a hex string. After the + * XRPFees amendment, a {@link SetFee} transaction + * serializes its `BaseFee` to a decimal string. + * + * @see "https://xrpl.org/resources/known-amendments/#xrpfees" + */ +public class BaseFeeDropsDeserializer extends StdDeserializer { + + /** + * No-args constructor. + */ + public BaseFeeDropsDeserializer() { + super(XrpCurrencyAmount.class); + } + + @Override + public XrpCurrencyAmount deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException { + // Pre-XRPFees, SetFee transactions serialize `BaseFee` to a hex string. Post XRPFees SetFee transactions + // have a `BaseFeeDrops` field which is a decimal string. + if (jsonParser.currentName().equals("BaseFee")) { + return XrpCurrencyAmount.of(UnsignedLong.valueOf(jsonParser.getText(), 16)); + } else { + return XrpCurrencyAmount.ofDrops(jsonParser.getValueAsLong()); + } + } +} diff --git a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/EscrowFinish.java b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/EscrowFinish.java index 9aa5d8464..a1a7e7a5b 100644 --- a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/EscrowFinish.java +++ b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/EscrowFinish.java @@ -228,9 +228,19 @@ default EscrowFinish normalizeCondition() { // In this case, we should try to read conditionRawValue to a Condition. If that fails, condition() // will remain empty, otherwise we will set condition(). try { - Condition condition = CryptoConditionReader.readCondition( - BaseEncoding.base16().decode(conditionRawValue().get().toUpperCase(Locale.US)) - ); + byte[] conditionRawValueBytes = BaseEncoding.base16() + .decode(conditionRawValue().get().toUpperCase(Locale.US)); + Condition condition = CryptoConditionReader.readCondition(conditionRawValueBytes); + + // CryptoConditionReader.readCondition can succeed if the first part of the condition raw value + // is a valid condition, but the raw value has extra bytes afterward. Here, we check that the parsed + // condition is equivalent to the raw value when re-written. + if (!Arrays.equals(CryptoConditionWriter.writeCondition(condition), conditionRawValueBytes)) { + logger.warn("EscrowFinish Condition was malformed: mismatch between raw value and parsed condition. " + + "conditionRawValue() will contain the condition value, but condition() will be empty."); + return this; + } + return EscrowFinish.builder().from(this) .condition(condition) .build(); @@ -300,9 +310,19 @@ default EscrowFinish normalizeFulfillment() { // In this case, we should try to read fulfillmentRawValue to a Condition. If that fails, fulfillment() // will remain empty, otherwise we will set fulfillment(). try { - Fulfillment fulfillment = CryptoConditionReader.readFulfillment( - BaseEncoding.base16().decode(fulfillmentRawValue().get().toUpperCase(Locale.US)) - ); + byte[] fulfillmentRawValueBytes = BaseEncoding.base16() + .decode(fulfillmentRawValue().get().toUpperCase(Locale.US)); + Fulfillment fulfillment = CryptoConditionReader.readFulfillment(fulfillmentRawValueBytes); + + // CryptoConditionReader.readFulfillment can succeed if the first part of the fulfillment raw value + // is a valid fulfillment, but the raw value has extra bytes afterward. Here, we check that the parsed + // fulfillment is equivalent to the raw value when re-written. + if (!Arrays.equals(CryptoConditionWriter.writeFulfillment(fulfillment), fulfillmentRawValueBytes)) { + logger.warn("EscrowFinish Fulfillment was malformed: mismatch between raw value and parsed fulfillment. " + + "fulfillmentRawValue() will contain the fulfillment value, but fulfillment() will be empty."); + return this; + } + return EscrowFinish.builder().from(this) .fulfillment(fulfillment) .build(); @@ -318,7 +338,7 @@ default EscrowFinish normalizeFulfillment() { } } catch (DerEncodingException e) { - // This should never happen. CryptoconditionWriter.writeCondition errantly declares that it can throw + // This should never happen. CryptoconditionWriter.writeFulfillment errantly declares that it can throw // a DerEncodingException, but nowhere in its implementation does it throw. throw new RuntimeException(e); } diff --git a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/SetFee.java b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/SetFee.java index 65178f352..8b7ee2412 100644 --- a/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/SetFee.java +++ b/xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/SetFee.java @@ -9,9 +9,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,12 +20,15 @@ * =========================LICENSE_END================================== */ +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.google.common.primitives.UnsignedInteger; import org.immutables.value.Value; import org.xrpl.xrpl4j.model.client.common.LedgerIndex; +import org.xrpl.xrpl4j.model.jackson.modules.BaseFeeDropsDeserializer; import java.util.Optional; @@ -53,34 +56,92 @@ static ImmutableSetFee.Builder builder() { * The charge, in drops of XRP, for the reference transaction, as hex. (This is the transaction cost before scaling * for load.) * - * @return A hex {@link String} basefee value. + *

This method only exists for historical purposes. When deserialized from a {@link SetFee} transaction from + * ledgers prior to the {@code XRPFees} amendment, this field will still be set based on {@link #baseFeeDrops()}. + * + * @return A hex {@link String} baseFee value. + */ + @Value.Derived + @JsonIgnore + default String baseFee() { + return baseFeeDrops().value().toString(16); + } + + /** + * The charge, in drops of XRP, for the reference transaction (This is the transaction cost before scaling for load). + * + *

This field will also be populated with the {@code BaseFee} value from any {@link SetFee} transactions + * that occurred before the XRPFees amendment took effect.

+ * + * @return An {@link XrpCurrencyAmount}. */ - @JsonProperty("BaseFee") - String baseFee(); + @JsonProperty("BaseFeeDrops") + @JsonAlias("BaseFee") + @JsonDeserialize(using = BaseFeeDropsDeserializer.class) + XrpCurrencyAmount baseFeeDrops(); /** - * The cost, in fee units, of the reference transaction. + * The cost, in fee units, of the reference transaction. {@link SetFee} transactions deserialized from ledgers prior + * to the {@code XRPFees} amendment will always have this field, but transactions deserialized from ledgers post + * {@code XRPFees} activation will never have this field. * * @return An {@link UnsignedInteger} cost of ref transaction. */ @JsonProperty("ReferenceFeeUnits") - UnsignedInteger referenceFeeUnits(); + Optional referenceFeeUnits(); /** * The base reserve, in drops. * - * @return An {@link UnsignedInteger} base reverse value in {@link org.xrpl.xrpl4j.model.client.fees.FeeDrops}. + *

This method only exists for historical purposes. When deserialized from a {@link SetFee} transaction from + * ledgers prior to the {@code XRPFees} amendment, this field will still be set based on {@link #reserveBaseDrops()}}. + * + * @return An {@link UnsignedInteger} base reserve value in {@link org.xrpl.xrpl4j.model.client.fees.FeeDrops}. */ - @JsonProperty("ReserveBase") - UnsignedInteger reserveBase(); + @Value.Derived + @JsonIgnore + default UnsignedInteger reserveBase() { + return UnsignedInteger.valueOf(reserveBaseDrops().value().longValue()); + } + + /** + * The base reserve, as an {@link XrpCurrencyAmount}. + * + *

This field will also be populated with the {@code ReserveBase} value from any {@link SetFee} transactions + * that occurred before the XRPFees amendment took effect.

+ * + * @return An {@link XrpCurrencyAmount}. + */ + @JsonProperty("ReserveBaseDrops") + @JsonAlias("ReserveBase") + XrpCurrencyAmount reserveBaseDrops(); /** * The incremental reserve, in drops. * + *

This method only exists for historical purposes. When deserialized from a {@link SetFee} transaction from + * ledgers prior to the {@code XRPFees} amendment, this field will still be set based on + * {@link #reserveIncrementDrops()}. + * * @return An {@link UnsignedInteger} incremental reserve in {@link org.xrpl.xrpl4j.model.client.fees.FeeDrops}. */ - @JsonProperty("ReserveIncrement") - UnsignedInteger reserveIncrement(); + @Value.Derived + @JsonIgnore + default UnsignedInteger reserveIncrement() { + return UnsignedInteger.valueOf(reserveIncrementDrops().value().longValue()); + } + + /** + * The incremental reserve, as an {@link XrpCurrencyAmount}. + * + *

This field will also be populated with the {@code ReserveIncrement} value from any {@link SetFee} transactions + * that occurred before the XRPFees amendment took effect.

+ * + * @return An {@link XrpCurrencyAmount}. + */ + @JsonProperty("ReserveIncrementDrops") + @JsonAlias("ReserveIncrement") + XrpCurrencyAmount reserveIncrementDrops(); /** * The index of the ledger version where this pseudo-transaction appears. This distinguishes the pseudo-transaction diff --git a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/EscrowFinishTest.java b/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/EscrowFinishTest.java index 232bf6b6b..15358b4c6 100644 --- a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/EscrowFinishTest.java +++ b/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/EscrowFinishTest.java @@ -28,6 +28,7 @@ import com.google.common.primitives.UnsignedInteger; import com.ripple.cryptoconditions.Condition; import com.ripple.cryptoconditions.CryptoConditionReader; +import com.ripple.cryptoconditions.CryptoConditionWriter; import com.ripple.cryptoconditions.Fulfillment; import com.ripple.cryptoconditions.PreimageSha256Condition; import com.ripple.cryptoconditions.PreimageSha256Fulfillment; @@ -176,6 +177,29 @@ void normalizeWithNoConditionAndRawValueForMalformedCondition() { assertThat(actual.conditionRawValue()).isNotEmpty().get().isEqualTo("1234"); } + /** + * This tests the case where conditionRawValue is present and is parseable to a Condition but when the + * parsed Condition is written to a byte array, the value differs from the conditionRawValue bytes. This + * can occur if the condition raw value contains a valid condition in the first 32 bytes, but also includes + * extra bytes afterward. + */ + @Test + void normalizeConditionWithRawValueThatIsParseableButNotValid() { + EscrowFinish actual = EscrowFinish.builder() + .fee(XrpCurrencyAmount.ofDrops(1)) + .account(Address.of("rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59Ba")) + .sequence(UnsignedInteger.ONE) + .owner(Address.of("rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")) + .offerSequence(UnsignedInteger.ZERO) + .conditionRawValue(GOOD_CONDITION_STR + GOOD_CONDITION_STR) + .build(); + + assertThat(actual.condition()).isEmpty(); + assertThat(actual.conditionRawValue()).isNotEmpty().get().isEqualTo( + GOOD_CONDITION_STR + GOOD_CONDITION_STR + ); + } + @Test void normalizeWithNoConditionAndRawValueForBadHexLengthCondition() { EscrowFinish actual = EscrowFinish.builder() @@ -284,6 +308,29 @@ void normalizeWithNoFulfillmentAndRawValueForMalformedFulfillment() { assertThat(actual.fulfillmentRawValue()).isNotEmpty().get().isEqualTo("1234"); } + /** + * This tests the case where fulfillmentRawValue is present and is parseable to a Fulfillment but when the + * parsed Fulfillment is written to a byte array, the value differs from the fulfillmentRawValue bytes. This + * can occur if the fulfillment raw value contains a valid fulfillment in the first 32 bytes, but also includes + * extra bytes afterward, such as in transaction 138543329687544CDAFCD3AB0DCBFE9C4F8E710397747BA7155F19426F493C8D. + */ + @Test + void normalizeFulfillmentWithRawValueThatIsParseableButNotValid() { + EscrowFinish actual = EscrowFinish.builder() + .fee(XrpCurrencyAmount.ofDrops(1)) + .account(Address.of("rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59Ba")) + .sequence(UnsignedInteger.ONE) + .owner(Address.of("rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")) + .offerSequence(UnsignedInteger.ZERO) + .fulfillmentRawValue(GOOD_FULFILLMENT_STR + GOOD_FULFILLMENT_STR) + .build(); + + assertThat(actual.fulfillment()).isEmpty(); + assertThat(actual.fulfillmentRawValue()).isNotEmpty().get().isEqualTo( + GOOD_FULFILLMENT_STR + GOOD_FULFILLMENT_STR + ); + } + @Test void normalizeWithNoFulfillmentAndRawValueForBadHexLengthFulfillment() { EscrowFinish actual = EscrowFinish.builder() diff --git a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/SetFeeTest.java b/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/SetFeeTest.java index dbf5c3118..42018706f 100644 --- a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/SetFeeTest.java +++ b/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/SetFeeTest.java @@ -22,25 +22,57 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.primitives.UnsignedInteger; import com.google.common.primitives.UnsignedLong; +import org.json.JSONException; import org.junit.jupiter.api.Test; +import org.xrpl.xrpl4j.model.AbstractJsonTest; import org.xrpl.xrpl4j.model.client.common.LedgerIndex; import java.util.Optional; -public class SetFeeTest { +/** + * Unit tests for {@link SetFee}. + */ +public class SetFeeTest extends AbstractJsonTest { + + @Test + public void testConstructWithNoFeeUnits() { + SetFee setFee = SetFee.builder() + .account(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")) + .fee(XrpCurrencyAmount.ofDrops(12)) + .sequence(UnsignedInteger.valueOf(2470665)) + .baseFeeDrops(XrpCurrencyAmount.ofDrops(10)) + .reserveBaseDrops(XrpCurrencyAmount.ofDrops(20000000)) + .reserveIncrementDrops(XrpCurrencyAmount.ofDrops(5000000)) + .ledgerSequence(Optional.of(LedgerIndex.of(UnsignedInteger.valueOf(67850752)))) + .build(); + + assertThat(setFee.transactionType()).isEqualTo(TransactionType.SET_FEE); + assertThat(setFee.account()).isEqualTo(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")); + assertThat(setFee.fee().value()).isEqualTo(UnsignedLong.valueOf(12)); + assertThat(setFee.sequence()).isEqualTo(UnsignedInteger.valueOf(2470665)); + assertThat(setFee.ledgerSequence()).isNotEmpty().get().isEqualTo(LedgerIndex.of(UnsignedInteger.valueOf(67850752))); + assertThat(setFee.baseFee()).isEqualTo("a"); + assertThat(setFee.baseFeeDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(10)); + assertThat(setFee.referenceFeeUnits()).isEmpty(); + assertThat(setFee.reserveIncrement()).isEqualTo(UnsignedInteger.valueOf(5000000)); + assertThat(setFee.reserveIncrementDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(5000000)); + assertThat(setFee.reserveBase()).isEqualTo(UnsignedInteger.valueOf(20000000)); + assertThat(setFee.reserveBaseDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(20000000)); + } @Test - public void testBuilder() { + public void testConstructWithFeeUnits() { SetFee setFee = SetFee.builder() .account(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")) .fee(XrpCurrencyAmount.ofDrops(12)) .sequence(UnsignedInteger.valueOf(2470665)) - .baseFee("000000000000000A") + .baseFeeDrops(XrpCurrencyAmount.ofDrops(10)) + .reserveBaseDrops(XrpCurrencyAmount.ofDrops(20000000)) + .reserveIncrementDrops(XrpCurrencyAmount.ofDrops(5000000)) .referenceFeeUnits(UnsignedInteger.valueOf(10)) - .reserveBase(UnsignedInteger.valueOf(20000000)) - .reserveIncrement(UnsignedInteger.valueOf(5000000)) .ledgerSequence(Optional.of(LedgerIndex.of(UnsignedInteger.valueOf(67850752)))) .build(); @@ -49,8 +81,78 @@ public void testBuilder() { assertThat(setFee.fee().value()).isEqualTo(UnsignedLong.valueOf(12)); assertThat(setFee.sequence()).isEqualTo(UnsignedInteger.valueOf(2470665)); assertThat(setFee.ledgerSequence()).isNotEmpty().get().isEqualTo(LedgerIndex.of(UnsignedInteger.valueOf(67850752))); - assertThat(setFee.referenceFeeUnits()).isEqualTo(UnsignedInteger.valueOf(10)); + assertThat(setFee.baseFee()).isEqualTo("a"); + assertThat(setFee.baseFeeDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(10)); + assertThat(setFee.referenceFeeUnits()).isNotEmpty().get().isEqualTo(UnsignedInteger.valueOf(10)); assertThat(setFee.reserveIncrement()).isEqualTo(UnsignedInteger.valueOf(5000000)); + assertThat(setFee.reserveIncrementDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(5000000)); assertThat(setFee.reserveBase()).isEqualTo(UnsignedInteger.valueOf(20000000)); + assertThat(setFee.reserveBaseDrops()).isEqualTo(XrpCurrencyAmount.ofDrops(20000000)); + } + + @Test + public void testDeserializePreXrpFeesTransaction() throws JsonProcessingException { + SetFee expected = SetFee.builder() + .account(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")) + .fee(XrpCurrencyAmount.ofDrops(12)) + .sequence(UnsignedInteger.valueOf(2470665)) + .baseFeeDrops(XrpCurrencyAmount.ofDrops(10)) + .referenceFeeUnits(UnsignedInteger.valueOf(10)) + .reserveBaseDrops(XrpCurrencyAmount.ofDrops(20000000)) + .reserveIncrementDrops(XrpCurrencyAmount.ofDrops(5000000)) + .ledgerSequence(Optional.of(LedgerIndex.of(UnsignedInteger.valueOf(67850752)))) + .build(); + + String json = "{" + + "\"Account\":\"rrrrrrrrrrrrrrrrrrrrrhoLvTp\"," + + "\"Fee\":\"12\"," + + "\"LedgerSequence\":67850752," + + "\"Sequence\":2470665," + + "\"SigningPubKey\":\"\"," + + "\"TransactionType\":\"SetFee\"," + + "\"ReserveIncrement\":5000000," + + "\"ReserveBase\":20000000," + + "\"ReferenceFeeUnits\":10," + + "\"BaseFee\":\"a\"}"; + + Transaction actual = objectMapper.readValue(json, Transaction.class); + assertThat(actual).isEqualTo(expected); + + String reserialized = objectMapper.writeValueAsString(actual); + Transaction redeserialized = objectMapper.readValue(reserialized, Transaction.class); + + assertThat(redeserialized).isEqualTo(expected); + } + + @Test + public void testDeserializePostXrpFeesTransaction() throws JsonProcessingException { + SetFee expected = SetFee.builder() + .account(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")) + .fee(XrpCurrencyAmount.ofDrops(0)) + .sequence(UnsignedInteger.valueOf(0)) + .baseFeeDrops(XrpCurrencyAmount.ofDrops(10)) + .reserveBaseDrops(XrpCurrencyAmount.ofDrops(10000000)) + .reserveIncrementDrops(XrpCurrencyAmount.ofDrops(2000000)) + .ledgerSequence(Optional.of(LedgerIndex.of(UnsignedInteger.valueOf(66462465)))) + .build(); + + String json = "{\n" + + " \"Account\": \"rrrrrrrrrrrrrrrrrrrrrhoLvTp\",\n" + + " \"BaseFeeDrops\": \"10\",\n" + + " \"Fee\": \"0\",\n" + + " \"LedgerSequence\": 66462465,\n" + + " \"ReserveBaseDrops\": \"10000000\",\n" + + " \"ReserveIncrementDrops\": \"2000000\",\n" + + " \"Sequence\": 0,\n" + + " \"SigningPubKey\": \"\",\n" + + " \"TransactionType\": \"SetFee\"}"; + + Transaction actual = objectMapper.readValue(json, Transaction.class); + assertThat(actual).isEqualTo(expected); + + String reserialized = objectMapper.writeValueAsString(actual); + Transaction redeserialized = objectMapper.readValue(reserialized, Transaction.class); + + assertThat(redeserialized).isEqualTo(expected); } } diff --git a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/json/SetFeeJsonTests.java b/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/json/SetFeeJsonTests.java deleted file mode 100644 index 05e0fa594..000000000 --- a/xrpl4j-core/src/test/java/org/xrpl/xrpl4j/model/transactions/json/SetFeeJsonTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.xrpl.xrpl4j.model.transactions.json; - -/*- - * ========================LICENSE_START================================= - * xrpl4j :: core - * %% - * Copyright (C) 2020 - 2023 XRPL Foundation and its contributors - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.common.primitives.UnsignedInteger; -import org.json.JSONException; -import org.junit.jupiter.api.Test; -import org.xrpl.xrpl4j.model.AbstractJsonTest; -import org.xrpl.xrpl4j.model.client.common.LedgerIndex; -import org.xrpl.xrpl4j.model.transactions.Address; -import org.xrpl.xrpl4j.model.transactions.SetFee; -import org.xrpl.xrpl4j.model.transactions.XrpCurrencyAmount; - -import java.util.Optional; - -public class SetFeeJsonTests extends AbstractJsonTest { - - @Test - public void testJson() throws JsonProcessingException, JSONException { - SetFee setFee = SetFee.builder() - .account(Address.of("rrrrrrrrrrrrrrrrrrrrrhoLvTp")) - .fee(XrpCurrencyAmount.ofDrops(12)) - .sequence(UnsignedInteger.valueOf(2470665)) - .baseFee("000000000000000A") - .referenceFeeUnits(UnsignedInteger.valueOf(10)) - .reserveBase(UnsignedInteger.valueOf(20000000)) - .reserveIncrement(UnsignedInteger.valueOf(5000000)) - .ledgerSequence(Optional.of(LedgerIndex.of(UnsignedInteger.valueOf(67850752)))) - .build(); - - String json = "{" + - "\"Account\":\"rrrrrrrrrrrrrrrrrrrrrhoLvTp\"," + - "\"Fee\":\"12\"," + - "\"LedgerSequence\":67850752," + - "\"Sequence\":2470665," + - "\"SigningPubKey\":\"\"," + - "\"TransactionType\":\"SetFee\"," + - "\"ReserveIncrement\":5000000," + - "\"ReserveBase\":20000000," + - "\"ReferenceFeeUnits\":10," + - "\"BaseFee\":\"000000000000000A\"}"; - - assertCanSerializeAndDeserialize(setFee, json); - } -}