From f7b20e36319af90fb778167a0c3cd909e40bc52e Mon Sep 17 00:00:00 2001 From: Shawn Reuland Date: Sat, 1 Jan 2022 12:53:26 -0800 Subject: [PATCH 1/2] #354: use new abs_before_epoch attribute if available for ClaimableBalancePredicate --- CHANGELOG.md | 1 + .../sdk/responses/PredicateDeserializer.java | 6 +- .../sdk/responses/EffectDeserializerTest.java | 78 +++++++++++++++++++ .../responses/OperationDeserializerTest.java | 44 +++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6a5501e5..44bc62ad7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ As this project is pre 1.0, breaking changes may happen for minor version bumps. * Fix missing Liquidity Pool ID in AccountResponse Balance ([#379](https://github.com/stellar/java-stellar-sdk/pull/379)). * Fix null pointer when calling ChangeTrustOperationResponse.getAsset() for LiquidityPool trust line ([#378](https://github.com/stellar/java-stellar-sdk/pull/378)). * Changed the access modifiers of the inner static classes of `AccountResponse` to public. +* Use the new ClaimableBalance Predicate AbsBeforeEpoch field to avoid parsing errors on potenital large dates in AbsBefore ### Breaking changes * Changed offer ids to be represented in requests and response models as long data type. ([#386](https://github.com/stellar/java-stellar-sdk/pull/386)). * Changed all *MuxedId* attributes to be of data type `java.math.BigInteger` in request and response models ([#388](https://github.com/stellar/java-stellar-sdk/pull/388)). diff --git a/src/main/java/org/stellar/sdk/responses/PredicateDeserializer.java b/src/main/java/org/stellar/sdk/responses/PredicateDeserializer.java index 244238832..6c129750f 100644 --- a/src/main/java/org/stellar/sdk/responses/PredicateDeserializer.java +++ b/src/main/java/org/stellar/sdk/responses/PredicateDeserializer.java @@ -36,7 +36,11 @@ public Predicate deserialize(JsonElement json, Type typeOfT, JsonDeserialization return new Predicate.Or(inner); } - if (obj.has("abs_before")) { + // backwards compatible for abs before, uses the newer abs_before_epoch if available from server + // otherwise if abs_before_epoch is absent, it will fall back to original attempt to parse abs_before date string + if (obj.has("abs_before_epoch")) { + return new Predicate.AbsBefore(obj.get("abs_before_epoch").getAsLong()); + } else if (obj.has("abs_before")) { String formattedDate = obj.get("abs_before").getAsString(); return new Predicate.AbsBefore(Instant.parse(formattedDate).getEpochSecond()); } diff --git a/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java b/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java index b4c71e949..1f7d4c054 100644 --- a/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java +++ b/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java @@ -6,6 +6,7 @@ import org.stellar.sdk.Asset; import org.stellar.sdk.AssetAmount; import org.stellar.sdk.AssetTypeNative; +import org.stellar.sdk.Predicate; import org.stellar.sdk.responses.effects.*; import org.stellar.sdk.xdr.LiquidityPoolType; @@ -245,6 +246,83 @@ public void testDeserializeAccountFlagsUpdatedEffect() { assertEquals(effect.getLinks().getPrecedes().getHref(), "http://horizon-testnet.stellar.org/effects?order=asc&cursor=18970870550529-1"); } + @Test + public void testDeserializeClaimableBalanceClaimantCreatedEffect() { + String json = "{\n" + + " \"_links\": {\n" + + " \"operation\": {\n" + + " \"href\": \"https://horizon.stellar.org/operations/158104892991700993\"\n" + + " },\n" + + " \"succeeds\": {\n" + + " \"href\": \"https://horizon.stellar.org/effects?order=desc&cursor=158104892991700993-2\"\n" + + " },\n" + + " \"precedes\": {\n" + + " \"href\": \"https://horizon.stellar.org/effects?order=asc&cursor=158104892991700993-2\"\n" + + " }\n" + + " },\n" + + " \"id\": \"0158104892991700993-0000000002\",\n" + + " \"paging_token\": \"158104892991700993-2\",\n" + + " \"account\": \"GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK\",\n" + + " \"type\": \"claimable_balance_claimant_created\",\n" + + " \"type_i\": 51,\n" + + " \"created_at\": \"2021-08-11T16:16:32Z\",\n" + + " \"asset\": \"KES:GA2MSSZKJOU6RNL3EJKH3S5TB5CDYTFQFWRYFGUJVIN5I6AOIRTLUHTO\",\n" + + " \"balance_id\": \"0000000071d3336fa6b6cf81fcbeda85a503ccfabc786ab1066594716f3f9551ea4b89ca\",\n" + + " \"amount\": \"0.0012200\",\n" + + " \"predicate\": {\n" + + " \"abs_before\": \"+39121901036-03-29T15:30:22Z\",\n" + + " \"abs_before_epoch\": \"1234567890982222222\"\n" + + " }\n" + + " }\n"; + + ClaimableBalanceClaimantCreatedEffectResponse effect = (ClaimableBalanceClaimantCreatedEffectResponse) GsonSingleton.getInstance().fromJson(json, EffectResponse.class); + + assertEquals(effect.getAccount(), "GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK"); + assertEquals(effect.getCreatedAt(), "2021-08-11T16:16:32Z"); + assertEquals(effect.getBalanceId(), "0000000071d3336fa6b6cf81fcbeda85a503ccfabc786ab1066594716f3f9551ea4b89ca"); + assertEquals(effect.getType(), "claimable_balance_claimant_created"); + assertSame(effect.getPredicate().getClass(), Predicate.AbsBefore.class); + assertEquals(((Predicate.AbsBefore)effect.getPredicate()).getTimestampSeconds(), 1234567890982222222L); + } + + @Test + public void testBackwardsCompatAbsBeforeEpoch() { + String json = "{\n" + + " \"_links\": {\n" + + " \"operation\": {\n" + + " \"href\": \"https://horizon.stellar.org/operations/158104892991700993\"\n" + + " },\n" + + " \"succeeds\": {\n" + + " \"href\": \"https://horizon.stellar.org/effects?order=desc&cursor=158104892991700993-2\"\n" + + " },\n" + + " \"precedes\": {\n" + + " \"href\": \"https://horizon.stellar.org/effects?order=asc&cursor=158104892991700993-2\"\n" + + " }\n" + + " },\n" + + " \"id\": \"0158104892991700993-0000000002\",\n" + + " \"paging_token\": \"158104892991700993-2\",\n" + + " \"account\": \"GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK\",\n" + + " \"type\": \"claimable_balance_claimant_created\",\n" + + " \"type_i\": 51,\n" + + " \"created_at\": \"2021-08-11T16:16:32Z\",\n" + + " \"asset\": \"KES:GA2MSSZKJOU6RNL3EJKH3S5TB5CDYTFQFWRYFGUJVIN5I6AOIRTLUHTO\",\n" + + " \"balance_id\": \"0000000071d3336fa6b6cf81fcbeda85a503ccfabc786ab1066594716f3f9551ea4b89ca\",\n" + + " \"amount\": \"0.0012200\",\n" + + " \"predicate\": {\n" + + " \"abs_before\": \"2021-11-21T07:24:10Z\"\n" + + " }\n" + + " }\n"; + + ClaimableBalanceClaimantCreatedEffectResponse effect = (ClaimableBalanceClaimantCreatedEffectResponse) GsonSingleton.getInstance().fromJson(json, EffectResponse.class); + + assertEquals(effect.getAccount(), "GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK"); + assertEquals(effect.getCreatedAt(), "2021-08-11T16:16:32Z"); + assertEquals(effect.getBalanceId(), "0000000071d3336fa6b6cf81fcbeda85a503ccfabc786ab1066594716f3f9551ea4b89ca"); + assertEquals(effect.getType(), "claimable_balance_claimant_created"); + assertSame(effect.getPredicate().getClass(), Predicate.AbsBefore.class); + assertEquals(((Predicate.AbsBefore)effect.getPredicate()).getTimestampSeconds(), 1637479450L); + } + @Test public void testDeserializeAccountInflationDestinationUpdatedEffect() { String json = "{\n" + diff --git a/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java b/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java index 36d831eea..228d6dd2f 100644 --- a/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java +++ b/src/test/java/org/stellar/sdk/responses/OperationDeserializerTest.java @@ -1527,4 +1527,48 @@ public void testDeserializeLiquidityPoolWithdrawOperation() { } )); } + + @Test + public void testDeserializeCreateClaimableBalanceOperation() { + String json = "{\n" + + " \n" + + " \"id\": \"158104892991700993\",\n" + + " \"paging_token\": \"158104892991700993\",\n" + + " \"transaction_successful\": true,\n" + + " \"source_account\": \"GAKFBRS24U3PEN6XDMEX4JEV5NGBARS2ZFF5O4CF3JL464SQSD4MDCPF\",\n" + + " \"type\": \"create_claimable_balance\",\n" + + " \"type_i\": 14,\n" + + " \"created_at\": \"2021-08-11T16:16:32Z\",\n" + + " \"transaction_hash\": \"c78e86007a0ee0bb0c717b02f5e306e524b4913b892e9983e7db4664a0c29841\",\n" + + " \"sponsor\": \"GAKFBRS24U3PEN6XDMEX4JEV5NGBARS2ZFF5O4CF3JL464SQSD4MDCPF\",\n" + + " \"asset\": \"KES:GA2MSSZKJOU6RNL3EJKH3S5TB5CDYTFQFWRYFGUJVIN5I6AOIRTLUHTO\",\n" + + " \"amount\": \"0.0012200\",\n" + + " \"claimants\": [\n" + + " {\n" + + " \"destination\": \"GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK\",\n" + + " \"predicate\": {\n" + + " \"abs_before\": \"+39121901036-03-29T15:30:22Z\",\n" + + " \"abs_before_epoch\": \"1234567890982222222\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"destination\": \"GAKFBRS24U3PEN6XDMEX4JEV5NGBARS2ZFF5O4CF3JL464SQSD4MDCPF\",\n" + + " \"predicate\": {\n" + + " \"unconditional\": true\n" + + " }\n" + + " }\n" + + " ]\n" + + "}"; + + CreateClaimableBalanceOperationResponse operation = (CreateClaimableBalanceOperationResponse) GsonSingleton.getInstance().fromJson(json, OperationResponse.class); + + assertEquals(operation.getId().longValue(), 158104892991700993L); + assertEquals(operation.getClaimants().size(), 2); + assertEquals(operation.getClaimants().get(0).getDestination(), "GBQECQVAS2FJ7DLCUXDASZAJQLWPXNTCR2DGBPKQDO3QS66TJXLRHFIK"); + assertSame(operation.getClaimants().get(0).getPredicate().getClass(), Predicate.AbsBefore.class); + assertEquals(((Predicate.AbsBefore)operation.getClaimants().get(0).getPredicate()).getTimestampSeconds(), 1234567890982222222L); + assertEquals(operation.getClaimants().get(1).getDestination(), "GAKFBRS24U3PEN6XDMEX4JEV5NGBARS2ZFF5O4CF3JL464SQSD4MDCPF"); + assertSame(operation.getClaimants().get(1).getPredicate().getClass(), Predicate.Unconditional.class); + assertEquals(operation.getType(), "create_claimable_balance"); + } } From d45aac295bedb175ef8ff1c11444f76ef5b876c4 Mon Sep 17 00:00:00 2001 From: Shawn Reuland Date: Sat, 1 Jan 2022 13:01:25 -0800 Subject: [PATCH 2/2] #354: updated CHANGELOG entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44bc62ad7..eabaf5323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ As this project is pre 1.0, breaking changes may happen for minor version bumps. * Fix missing Liquidity Pool ID in AccountResponse Balance ([#379](https://github.com/stellar/java-stellar-sdk/pull/379)). * Fix null pointer when calling ChangeTrustOperationResponse.getAsset() for LiquidityPool trust line ([#378](https://github.com/stellar/java-stellar-sdk/pull/378)). * Changed the access modifiers of the inner static classes of `AccountResponse` to public. -* Use the new ClaimableBalance Predicate AbsBeforeEpoch field to avoid parsing errors on potenital large dates in AbsBefore +* Use the new ClaimableBalance Predicate AbsBeforeEpoch field to avoid parsing errors on potenital large dates in AbsBefore ([#394](https://github.com/stellar/java-stellar-sdk/pull/394)). ### Breaking changes * Changed offer ids to be represented in requests and response models as long data type. ([#386](https://github.com/stellar/java-stellar-sdk/pull/386)). * Changed all *MuxedId* attributes to be of data type `java.math.BigInteger` in request and response models ([#388](https://github.com/stellar/java-stellar-sdk/pull/388)).