Skip to content

Commit

Permalink
Add missing operation responses (#373)
Browse files Browse the repository at this point in the history
There were two operations missing related to liquidity pools. This PR also registers the liquidity pool id class in the operation and effect deserializers so it can be serialized / deserialized properly.
  • Loading branch information
tamirms authored Oct 22, 2021
1 parent fc3cde3 commit f0ccceb
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

As this project is pre 1.0, breaking changes may happen for minor version bumps. A breaking change will get clearly notified in this log.

## 0.29.0

* Fixed bug in parsing liquidity pool operation and effect responses ([#373](https://github.com/stellar/java-stellar-sdk/pull/373)).

## 0.28.0

* Added support for 'client_domain' ManageData operations in SEP 10 challenges ([#368](https://github.com/stellar/java-stellar-sdk/pull/368)).
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ apply plugin: 'com.github.ben-manes.versions' // gradle dependencyUpdates -Drevi
apply plugin: 'project-report' // gradle htmlDependencyReport

sourceCompatibility = 1.6
version = '0.28.0'
version = '0.29.0'
group = 'stellar'

jar {
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/stellar/sdk/AssetAmount.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.stellar.sdk;

import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;

public final class AssetAmount {
@SerializedName("asset")
private final Asset asset;
@SerializedName("amount")
private final String amount;

AssetAmount(Asset asset, String amount) {
public AssetAmount(Asset asset, String amount) {
this.asset = asset;
this.amount = amount;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import com.google.gson.JsonParseException;

import org.stellar.sdk.Asset;
import org.stellar.sdk.LiquidityPoolID;
import org.stellar.sdk.Predicate;
import org.stellar.sdk.responses.effects.*;
import org.stellar.sdk.xdr.LiquidityPoolType;

import java.lang.reflect.Type;

Expand All @@ -19,6 +21,8 @@ public EffectResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializ
// Create new Gson object with adapters needed in Operation
Gson gson = new GsonBuilder()
.registerTypeAdapter(Asset.class, new AssetDeserializer())
.registerTypeAdapter(LiquidityPoolID.class, new LiquidityPoolIDDeserializer())
.registerTypeAdapter(LiquidityPoolType.class, new LiquidityPoolTypeDeserializer())
.registerTypeAdapter(Predicate.class, new PredicateDeserializer())
.create();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import com.google.gson.JsonParseException;

import org.stellar.sdk.Asset;
import org.stellar.sdk.LiquidityPoolID;
import org.stellar.sdk.Predicate;
import org.stellar.sdk.responses.operations.*;
import org.stellar.sdk.xdr.LiquidityPoolType;
import org.stellar.sdk.xdr.OperationType;

import java.lang.reflect.Type;
Expand All @@ -25,6 +27,8 @@ public OperationResponse deserialize(JsonElement json, Type typeOfT, JsonDeseria
.registerTypeAdapter(Predicate.class, new PredicateDeserializer())
.registerTypeAdapter(TransactionResponse.class, new TransactionDeserializer())
.registerTypeAdapter(ImmutableList.class, new ImmutableListDeserializer())
.registerTypeAdapter(LiquidityPoolID.class, new LiquidityPoolIDDeserializer())
.registerTypeAdapter(LiquidityPoolType.class, new LiquidityPoolTypeDeserializer())
.create();

int type = json.getAsJsonObject().get("type_i").getAsInt();
Expand Down Expand Up @@ -77,6 +81,10 @@ public OperationResponse deserialize(JsonElement json, Type typeOfT, JsonDeseria
return gson.fromJson(json, ClawbackClaimableBalanceOperationResponse.class);
case SET_TRUST_LINE_FLAGS:
return gson.fromJson(json, SetTrustLineFlagsOperationResponse.class);
case LIQUIDITY_POOL_DEPOSIT:
return gson.fromJson(json, LiquidityPoolDepositOperationResponse.class);
case LIQUIDITY_POOL_WITHDRAW:
return gson.fromJson(json, LiquidityPoolWithdrawOperationResponse.class);
default:
throw new RuntimeException("Invalid operation type");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import org.stellar.sdk.AssetAmount;
import org.stellar.sdk.LiquidityPoolID;
import org.stellar.sdk.xdr.LiquidityPoolType;

import com.google.gson.annotations.SerializedName;
import org.stellar.sdk.xdr.LiquidityPoolType;

public class LiquidityPool {
@SerializedName("id")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.stellar.sdk.responses.operations;

import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
import org.stellar.sdk.LiquidityPoolID;
import org.stellar.sdk.Price;
import org.stellar.sdk.AssetAmount;

import java.util.List;

public class LiquidityPoolDepositOperationResponse extends OperationResponse {
@SerializedName("liquidity_pool_id")
private final LiquidityPoolID liquidityPoolId;
@SerializedName("reserves_max")
private final AssetAmount[] reservesMax;
@SerializedName("min_price")
private final String minPrice;
@SerializedName("min_price_r")
private final Price minPriceR;
@SerializedName("max_price")
private final String maxPrice;
@SerializedName("max_price_r")
private final Price maxPriceR;
@SerializedName("reserves_deposited")
private final AssetAmount[] reservesDeposited;
@SerializedName("shares_received")
private final String sharesReceived;

LiquidityPoolDepositOperationResponse(LiquidityPoolID liquidityPoolId, AssetAmount[] reservesMax, String minPrice, Price minPriceR, String maxPrice, Price maxPriceR, AssetAmount[] reservesDeposited, String sharesReceived) {
this.liquidityPoolId = liquidityPoolId;
this.reservesMax = reservesMax;
this.minPrice = minPrice;
this.minPriceR = minPriceR;
this.maxPrice = maxPrice;
this.maxPriceR = maxPriceR;
this.reservesDeposited = reservesDeposited;
this.sharesReceived = sharesReceived;
}

public LiquidityPoolID getLiquidityPoolId() {
return liquidityPoolId;
}

public AssetAmount[] getReservesMax() {
return reservesMax;
}

public String getMinPrice() {
return minPrice;
}

public Price getMinPriceR() {
return minPriceR;
}

public String getMaxPrice() {
return maxPrice;
}

public Price getMaxPriceR() {
return maxPriceR;
}

public AssetAmount[] getReservesDeposited() {
return reservesDeposited;
}

public String getSharesReceived() {
return sharesReceived;
}

public int hashCode() {
return Objects.hashCode(liquidityPoolId, reservesMax, minPrice, minPriceR, maxPrice, maxPriceR, reservesDeposited, sharesReceived);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof LiquidityPoolDepositOperationResponse)) {
return false;
}

LiquidityPoolDepositOperationResponse o = (LiquidityPoolDepositOperationResponse) object;
return Objects.equal(this.getLiquidityPoolId(), o.getLiquidityPoolId()) &&
Objects.equal(this.getReservesMax(), o.getReservesMax()) &&
Objects.equal(this.getMaxPrice(), o.getMaxPrice()) &&
Objects.equal(this.getMinPrice(), o.getMinPrice()) &&
Objects.equal(this.getMaxPriceR(), o.getMaxPriceR()) &&
Objects.equal(this.getMinPriceR(), o.getMinPriceR()) &&
Objects.equal(this.getReservesDeposited(), o.getReservesDeposited()) &&
Objects.equal(this.getSharesReceived(), o.getSharesReceived());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.stellar.sdk.responses.operations;

import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
import org.stellar.sdk.LiquidityPoolID;
import org.stellar.sdk.AssetAmount;

import java.util.List;

public class LiquidityPoolWithdrawOperationResponse extends OperationResponse {
@SerializedName("liquidity_pool_id")
private final LiquidityPoolID liquidityPoolId;
@SerializedName("reserves_min")
private final AssetAmount[] reservesMin;
@SerializedName("reserves_received")
private final AssetAmount[] reservesReceived;
@SerializedName("shares")
private final String shares;

public LiquidityPoolWithdrawOperationResponse(LiquidityPoolID poolId, AssetAmount[] reservesMin, String shares, AssetAmount[] reservesReceived) {
this.liquidityPoolId = poolId;
this.reservesMin = reservesMin;
this.shares = shares;
this.reservesReceived = reservesReceived;
}
public LiquidityPoolID getLiquidityPoolId() {
return liquidityPoolId;
}

public AssetAmount[] getReservesMin() {
return reservesMin;
}

public AssetAmount[] getReservesReceived() {
return reservesReceived;
}

public String getShares() {
return shares;
}

public int hashCode() {
return Objects.hashCode(liquidityPoolId, reservesMin, reservesReceived, shares);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof LiquidityPoolDepositOperationResponse)) {
return false;
}

LiquidityPoolWithdrawOperationResponse o = (LiquidityPoolWithdrawOperationResponse) object;
return Objects.equal(this.getLiquidityPoolId(), o.getLiquidityPoolId()) &&
Objects.equal(this.getReservesMin(), o.getReservesMin()) &&
Objects.equal(this.getReservesReceived(), o.getReservesReceived()) &&
Objects.equal(this.getShares(), o.getShares());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

import org.junit.Test;
import org.stellar.sdk.Asset;
import org.stellar.sdk.AssetAmount;
import org.stellar.sdk.AssetTypeNative;
import org.stellar.sdk.KeyPair;
import org.stellar.sdk.responses.effects.*;
import org.stellar.sdk.xdr.LiquidityPoolType;

import java.util.Arrays;

public class EffectDeserializerTest extends TestCase {
@Test
Expand Down Expand Up @@ -824,4 +827,69 @@ public void testDeserializeTrustlineFlagsUpdatedEffect() {
assertEquals(effect.getAssetCode(), "EUR");
assertEquals(effect.getAssetType(), "credit_alphanum4");
}

@Test
public void testDeserializeLiquidityPoolTradeEffect() {
String json = " {\n" +
" \"_links\": {\n" +
" \"operation\": {\n" +
" \"href\": \"https://horizon-testnet.stellar.org/operations/2091275411030017\"\n" +
" },\n" +
" \"succeeds\": {\n" +
" \"href\": \"https://horizon-testnet.stellar.org/effects?order=desc\\u0026cursor=2091275411030017-3\"\n" +
" },\n" +
" \"precedes\": {\n" +
" \"href\": \"https://horizon-testnet.stellar.org/effects?order=asc\\u0026cursor=2091275411030017-3\"\n" +
" }\n" +
" },\n" +
" \"id\": \"0002091275411030017-0000000003\",\n" +
" \"paging_token\": \"2091275411030017-3\",\n" +
" \"account\": \"GDUZE3MB2TJVVCGM7LLYUXGZTZNRQS6OEESTQDO4RGI7QZPI2VYOIC4G\",\n" +
" \"type\": \"liquidity_pool_trade\",\n" +
" \"type_i\": 92,\n" +
" \"created_at\": \"2021-10-15T00:15:07Z\",\n" +
" \"liquidity_pool\": {\n" +
" \"id\": \"af961c246cc51e6eda2441482f09cf6b1478e30b34e47daf86c860f753d8f04c\",\n" +
" \"fee_bp\": 30,\n" +
" \"type\": \"constant_product\",\n" +
" \"total_trustlines\": \"3\",\n" +
" \"total_shares\": \"18560.5392046\",\n" +
" \"reserves\": [\n" +
" {\n" +
" \"asset\": \"native\",\n" +
" \"amount\": \"6080.9091224\"\n" +
" },\n" +
" {\n" +
" \"asset\": \"ARST:GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO\",\n" +
" \"amount\": \"56817.1796745\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"sold\": {\n" +
" \"asset\": \"native\",\n" +
" \"amount\": \"0.1067066\"\n" +
" },\n" +
" \"bought\": {\n" +
" \"asset\": \"ARST:GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO\",\n" +
" \"amount\": \"1.0000000\"\n" +
" }\n" +
" }";
LiquidityPoolTradeEffectResponse effect = (LiquidityPoolTradeEffectResponse) GsonSingleton.getInstance().fromJson(json, EffectResponse.class);

assertEquals(effect.getType(), "liquidity_pool_trade");

assertEquals(effect.getAccount(), "GDUZE3MB2TJVVCGM7LLYUXGZTZNRQS6OEESTQDO4RGI7QZPI2VYOIC4G");
assertEquals(effect.getCreatedAt(), "2021-10-15T00:15:07Z");
assertEquals(effect.getLiquidityPool().getID().toString(), "af961c246cc51e6eda2441482f09cf6b1478e30b34e47daf86c860f753d8f04c");
assertEquals(effect.getLiquidityPool().getFeeBP(), Integer.valueOf(30));
assertEquals(effect.getLiquidityPool().getType(), LiquidityPoolType.LIQUIDITY_POOL_CONSTANT_PRODUCT);
assertEquals(effect.getLiquidityPool().getTotalTrustlines(), Long.valueOf(3));
assertEquals(effect.getLiquidityPool().getTotalShares(), "18560.5392046");
assertTrue(Arrays.equals(effect.getLiquidityPool().getReserves(), new AssetAmount[]{
new AssetAmount(Asset.create("native"), "6080.9091224"),
new AssetAmount(Asset.create("ARST:GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO"), "56817.1796745")
}));
assertEquals(effect.getSold(), new AssetAmount(Asset.create("native"), "0.1067066"));
assertEquals(effect.getBought(), new AssetAmount(Asset.create("ARST:GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO"), "1.0000000"));
}
}
Loading

0 comments on commit f0ccceb

Please sign in to comment.