diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6bf734eeb..ec10c1281 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ As this project is pre 1.0, breaking changes may happen for minor version bumps.
## 0.41.0-beta.4
* Add support for Soroban Preview 11. ([#530](https://github.com/stellar/java-stellar-sdk/pull/530))
+* New effects have been added to support Protocol 20 (Soroban) ([#535](https://github.com/stellar/java-stellar-sdk/pull/535)):
+ - `ContractCredited` occurs when a Stellar asset moves into its corresponding Stellar Asset Contract instance
+ - `ContractDebited` occurs when a Stellar asset moves out of its corresponding Stellar Asset Contract instance
* Bump dependencies & Remove unnecessary dependencies. ([#523](https://github.com/stellar/java-stellar-sdk/pull/523))
## 0.41.0-beta.3
diff --git a/src/main/java/org/stellar/sdk/responses/EffectDeserializer.java b/src/main/java/org/stellar/sdk/responses/EffectDeserializer.java
index abcc12840..d4c324ecc 100644
--- a/src/main/java/org/stellar/sdk/responses/EffectDeserializer.java
+++ b/src/main/java/org/stellar/sdk/responses/EffectDeserializer.java
@@ -139,6 +139,10 @@ public EffectResponse deserialize(
return gson.fromJson(json, LiquidityPoolRemovedEffectResponse.class);
case 95:
return gson.fromJson(json, LiquidityPoolRevokedEffectResponse.class);
+ case 96:
+ return gson.fromJson(json, ContractCreditedEffectResponse.class);
+ case 97:
+ return gson.fromJson(json, ContractDebitedEffectResponse.class);
default:
throw new RuntimeException("Invalid effect type");
}
diff --git a/src/main/java/org/stellar/sdk/responses/effects/ContractCreditedEffectResponse.java b/src/main/java/org/stellar/sdk/responses/effects/ContractCreditedEffectResponse.java
new file mode 100644
index 000000000..763820cea
--- /dev/null
+++ b/src/main/java/org/stellar/sdk/responses/effects/ContractCreditedEffectResponse.java
@@ -0,0 +1,31 @@
+package org.stellar.sdk.responses.effects;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Represents contract_credited effect response.
+ *
+ * @see Effect definition
+ * @see org.stellar.sdk.requests.EffectsRequestBuilder
+ * @see org.stellar.sdk.Server#effects()
+ */
+@AllArgsConstructor
+@Getter
+public class ContractCreditedEffectResponse extends EffectResponse {
+ @SerializedName("asset_type")
+ private final String assetType;
+
+ @SerializedName("asset_code")
+ private final String assetCode;
+
+ @SerializedName("asset_issuer")
+ private final String assetIssuer;
+
+ private final String contract;
+
+ private final String amount;
+}
diff --git a/src/main/java/org/stellar/sdk/responses/effects/ContractDebitedEffectResponse.java b/src/main/java/org/stellar/sdk/responses/effects/ContractDebitedEffectResponse.java
new file mode 100644
index 000000000..33813ea05
--- /dev/null
+++ b/src/main/java/org/stellar/sdk/responses/effects/ContractDebitedEffectResponse.java
@@ -0,0 +1,31 @@
+package org.stellar.sdk.responses.effects;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Represents contract_debited effect response.
+ *
+ * @see Effect definition
+ * @see org.stellar.sdk.requests.EffectsRequestBuilder
+ * @see org.stellar.sdk.Server#effects()
+ */
+@AllArgsConstructor
+@Getter
+public class ContractDebitedEffectResponse extends EffectResponse {
+ @SerializedName("asset_type")
+ private final String assetType;
+
+ @SerializedName("asset_code")
+ private final String assetCode;
+
+ @SerializedName("asset_issuer")
+ private final String assetIssuer;
+
+ private final String contract;
+
+ private final String amount;
+}
diff --git a/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java b/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java
index dadb15509..d1303f1a5 100644
--- a/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java
+++ b/src/test/java/org/stellar/sdk/responses/EffectDeserializerTest.java
@@ -20,6 +20,8 @@
import org.stellar.sdk.responses.effects.AccountThresholdsUpdatedEffectResponse;
import org.stellar.sdk.responses.effects.ClaimableBalanceClaimantCreatedEffectResponse;
import org.stellar.sdk.responses.effects.ClaimableBalanceClawedBackEffectResponse;
+import org.stellar.sdk.responses.effects.ContractCreditedEffectResponse;
+import org.stellar.sdk.responses.effects.ContractDebitedEffectResponse;
import org.stellar.sdk.responses.effects.DataCreatedEffectResponse;
import org.stellar.sdk.responses.effects.DataRemovedEffectResponse;
import org.stellar.sdk.responses.effects.DataUpdatedEffectResponse;
@@ -1417,4 +1419,86 @@ public void testDeserializeLiquidityPoolRevokedEffect() {
});
assertEquals(effect.getSharesRevoked(), "24452.3233794");
}
+
+ @Test
+ public void testDeserializeContractCreditedEffect() {
+ String json =
+ "{\n"
+ + " \"_links\": {\n"
+ + " \"operation\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/operations/21517786157057\"\n"
+ + " },\n"
+ + " \"succeeds\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/effects?order=desc&cursor=21517786157057-2\"\n"
+ + " },\n"
+ + " \"precedes\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/effects?order=asc&cursor=21517786157057-2\"\n"
+ + " }\n"
+ + " },\n"
+ + " \"id\": \"0000021517786157057-0000000002\",\n"
+ + " \"paging_token\": \"21517786157057-2\",\n"
+ + " \"account\": \"GDAT5HWTGIU4TSSZ4752OUC4SABDLTLZFRPZUJ3D6LKBNEPA7V2CIG54\",\n"
+ + " \"type\": \"contract_credited\",\n"
+ + " \"type_i\": 96,\n"
+ + " \"created_at\": \"2023-09-19T05:43:12Z\",\n"
+ + " \"asset_type\": \"native\",\n"
+ + " \"contract\": \"CDCYWK73YTYFJZZSJ5V7EDFNHYBG4QN3VUNG2IGD27KJDDPNCZKBCBXK\",\n"
+ + " \"amount\": \"100.0000000\"\n"
+ + "}\n";
+
+ ContractCreditedEffectResponse effect =
+ (ContractCreditedEffectResponse)
+ GsonSingleton.getInstance().fromJson(json, EffectResponse.class);
+
+ assertEquals(effect.getType(), "contract_credited");
+ assertEquals(effect.getId(), "0000021517786157057-0000000002");
+ assertEquals(effect.getPagingToken(), "21517786157057-2");
+ assertEquals(effect.getAccount(), "GDAT5HWTGIU4TSSZ4752OUC4SABDLTLZFRPZUJ3D6LKBNEPA7V2CIG54");
+ assertEquals(effect.getCreatedAt(), "2023-09-19T05:43:12Z");
+ assertEquals(effect.getAmount(), "100.0000000");
+ assertEquals(effect.getAssetType(), "native");
+ assertNull(effect.getAssetCode());
+ assertNull(effect.getAssetIssuer());
+ }
+
+ @Test
+ public void testDeserializeContractDebitedEffect() {
+ String json =
+ "{\n"
+ + " \"_links\": {\n"
+ + " \"operation\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/operations/21517786157057\"\n"
+ + " },\n"
+ + " \"succeeds\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/effects?order=desc&cursor=21517786157057-2\"\n"
+ + " },\n"
+ + " \"precedes\": {\n"
+ + " \"href\": \"http://100.83.15.43:8000/effects?order=asc&cursor=21517786157057-2\"\n"
+ + " }\n"
+ + " },\n"
+ + " \"id\": \"0000021517786157057-0000000002\",\n"
+ + " \"paging_token\": \"21517786157057-2\",\n"
+ + " \"account\": \"GDAT5HWTGIU4TSSZ4752OUC4SABDLTLZFRPZUJ3D6LKBNEPA7V2CIG54\",\n"
+ + " \"type\": \"contract_debited\",\n"
+ + " \"type_i\": 97,\n"
+ + " \"created_at\": \"2023-09-19T05:43:12Z\",\n"
+ + " \"asset_type\": \"native\",\n"
+ + " \"contract\": \"CDCYWK73YTYFJZZSJ5V7EDFNHYBG4QN3VUNG2IGD27KJDDPNCZKBCBXK\",\n"
+ + " \"amount\": \"100.0000000\"\n"
+ + "}\n";
+
+ ContractDebitedEffectResponse effect =
+ (ContractDebitedEffectResponse)
+ GsonSingleton.getInstance().fromJson(json, EffectResponse.class);
+
+ assertEquals(effect.getType(), "contract_debited");
+ assertEquals(effect.getId(), "0000021517786157057-0000000002");
+ assertEquals(effect.getPagingToken(), "21517786157057-2");
+ assertEquals(effect.getAccount(), "GDAT5HWTGIU4TSSZ4752OUC4SABDLTLZFRPZUJ3D6LKBNEPA7V2CIG54");
+ assertEquals(effect.getCreatedAt(), "2023-09-19T05:43:12Z");
+ assertEquals(effect.getAmount(), "100.0000000");
+ assertEquals(effect.getAssetType(), "native");
+ assertNull(effect.getAssetCode());
+ assertNull(effect.getAssetIssuer());
+ }
}