Skip to content

#576: Add support for AMMClawback #601

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Apr 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8c0896e
generate definitions.json from xrpl.js script
Feb 9, 2025
f7ede3e
add amm clawback transaction and transaction flags
Feb 9, 2025
6208633
add ammclawback to signature utils
Feb 17, 2025
ad2caee
set up tests, almost full flow working
Feb 17, 2025
ccee59b
cleanup test
Feb 17, 2025
e526d46
remove extra print lines
Feb 17, 2025
c8aab1f
make enable rippling private again
Feb 17, 2025
b1f8c42
enable AMMClawback amendment, create two integration tests
Feb 19, 2025
3149b86
add one more integration test
Feb 19, 2025
ee8054c
add comment for unset flag
Feb 19, 2025
21b1e9d
add some comments to AmmClawback class
Feb 19, 2025
fcd0407
merge main into this branch
Feb 19, 2025
10b2b50
fix build by addressing TransactionFlags reference
Feb 26, 2025
850fa74
add Address import to AmmClawback class
Feb 26, 2025
b030ff5
fix all checkstyle issues, successful build
Feb 26, 2025
16dc361
address issues in unit test
Feb 26, 2025
ec0c5d2
address changes for currencies used
Feb 26, 2025
60396cd
add new empty method and add tests for AmmClawbackFlags
Feb 28, 2025
1c92ba8
change default for AmmClawbackFlags to empty instead of Unset
Feb 28, 2025
0513be4
add multi signature transaction helper test for signature utils
Feb 28, 2025
7d8f95d
update rippled version and fix checkstyle issues
Feb 28, 2025
6f41e95
fix amm clawback test class failing test
Feb 28, 2025
d699102
remove failing data driven test types
Mar 3, 2025
f06efc0
go back to version 2.3.0 rippled container
Mar 4, 2025
8984374
remove extra address import
Mar 10, 2025
3c03a3a
apply formatting for files changes
Mar 25, 2025
aaeba34
fix indenting and build
Mar 25, 2025
f67ba31
fix more formatting
Mar 25, 2025
e3a4fec
merge main into this branch
Apr 1, 2025
af2e5b2
undo formatting in SignatureUtils.java
Apr 9, 2025
0f5ec91
fix formatting in signature utils.java
Apr 9, 2025
81f1b9b
fix other small issues with SignatureUtils.java
Apr 9, 2025
59d2099
put back 2 other comments
Apr 9, 2025
81f1962
remove @beta from amm clawback
Apr 9, 2025
609855b
add javadoc to amm clawback transaction type
Apr 9, 2025
83afd49
fix formatting issues in rippledcontainer.java
Apr 9, 2025
ff76e41
apply formatting to signature utils test java
Apr 9, 2025
257c468
apply formatting to amm clawback test java
Apr 9, 2025
c92872c
put back stuff i changed in ripple d container java
Apr 9, 2025
9e4aeaa
fix formatting in AMM It Java
Apr 9, 2025
5dd9b0e
Update xrpl4j-core/src/main/java/org/xrpl/xrpl4j/model/transactions/T…
sappenin Apr 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.xrpl.xrpl4j.model.transactions.AccountSet;
import org.xrpl.xrpl4j.model.transactions.Address;
import org.xrpl.xrpl4j.model.transactions.AmmBid;
import org.xrpl.xrpl4j.model.transactions.AmmClawback;
import org.xrpl.xrpl4j.model.transactions.AmmCreate;
import org.xrpl.xrpl4j.model.transactions.AmmDelete;
import org.xrpl.xrpl4j.model.transactions.AmmDeposit;
Expand Down Expand Up @@ -395,6 +396,10 @@ public <T extends Transaction> SingleSignedTransaction<T> addSignatureToTransact
transactionWithSignature = OracleDelete.builder().from((OracleDelete) transaction)
.transactionSignature(signature)
.build();
} else if (AmmClawback.class.isAssignableFrom(transaction.getClass())) {
transactionWithSignature = AmmClawback.builder().from((AmmClawback) transaction)
.transactionSignature(signature)
.build();
} else if (MpTokenAuthorize.class.isAssignableFrom(transaction.getClass())) {
transactionWithSignature = MpTokenAuthorize.builder().from((MpTokenAuthorize) transaction)
.transactionSignature(signature)
Expand Down Expand Up @@ -622,6 +627,10 @@ public <T extends Transaction> T addMultiSignaturesToTransaction(T transaction,
transactionWithSignatures = OracleDelete.builder().from((OracleDelete) transaction)
.signers(signers)
.build();
} else if (AmmClawback.class.isAssignableFrom(transaction.getClass())) {
transactionWithSignatures = AmmClawback.builder().from((AmmClawback) transaction)
.signers(signers)
.build();
} else if (MpTokenAuthorize.class.isAssignableFrom(transaction.getClass())) {
transactionWithSignatures = MpTokenAuthorize.builder().from((MpTokenAuthorize) transaction)
.signers(signers)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.xrpl.xrpl4j.model.flags;

/*-
* ========================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 org.xrpl.xrpl4j.model.transactions.AmmClawback;

/**
* {@link TransactionFlags} for {@link AmmClawback} transactions.
*/
public class AmmClawbackFlags extends TransactionFlags {
/**
* Constant {@link AmmDepositFlags} for the {@code tfClawTwoAssets} flag.
*/
public static final AmmClawbackFlags CLAW_TWO_ASSETS = new AmmClawbackFlags(0x00000001);

/**
* Constant {@link AmmDepositFlags} for an unset value for "flags".
*/
public static final AmmClawbackFlags UNSET = new AmmClawbackFlags(0L);

private AmmClawbackFlags(long value) {
super(value);
}

private AmmClawbackFlags() {
}

/**
* Construct an empty instance of {@link AmmClawbackFlags}. Transactions with empty flags will
* not be serialized with a {@code Flags} field.
*
* @return An empty {@link AmmClawbackFlags}.
*/
public static AmmClawbackFlags empty() {
return new AmmClawbackFlags();
}

/**
* Whether the {@code tfClawTwoAssets} flag is set.
*
* @return {@code true} if {@code tfLPToken} is set, otherwise {@code false}.
*/
public boolean tfClawTwoAssets() {
return this.isSet(CLAW_TWO_ASSETS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package org.xrpl.xrpl4j.model.transactions;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.google.common.annotations.Beta;
import org.immutables.value.Value;
import org.xrpl.xrpl4j.model.flags.AmmClawbackFlags;
import org.xrpl.xrpl4j.model.ledger.Issue;

import java.util.Optional;

/**
* An {@link AmmClawback} transaction claws back tokens from a holder that has funds in an AMM pool.
*/
@Value.Immutable
@JsonSerialize(as = ImmutableAmmClawback.class)
@JsonDeserialize(as = ImmutableAmmClawback.class)
public interface AmmClawback extends Transaction {

/**
* Construct a builder for this class.
*
* @return An {@link ImmutableAmmClawback.Builder}.
*/
static ImmutableAmmClawback.Builder builder() {
return ImmutableAmmClawback.builder();
}

/**
* The address of the holder that has funds deposited in the AMM pool.
*
* @return An {@link Address}.
*/
@JsonProperty("Holder")
Address holder();

/**
* The asset in the AMM pool that the issuer is looking to claw back.
*
* @return An {@link Issue}.
*/
@JsonProperty("Asset")
Issue asset();

/**
* Other asset in the AMM pool that the issuer is looking to claw back.
*
* @return An {@link Issue}.
*/
@JsonProperty("Asset2")
Issue asset2();

/**
* Optional field that specifies the maximum amount to clawback from the AMM pool.
*
* @return An {@link CurrencyAmount}.
*/
@JsonProperty("Amount")
Optional<CurrencyAmount> amount();

/**
* Transaction Flags for {@link AmmClawback}, with the only option being tfClawTwoAssets.
*
* @return {@link AmmClawbackFlags#UNSET} if field was not set, otherwise returns with the set flag.
*/
@JsonProperty("Flags")
@Value.Default
default AmmClawbackFlags flags() {
return AmmClawbackFlags.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public interface Transaction {
.put(ImmutableMpTokenIssuanceDestroy.class, TransactionType.MPT_ISSUANCE_DESTROY)
.put(ImmutableMpTokenIssuanceSet.class, TransactionType.MPT_ISSUANCE_SET)
.put(ImmutableUnknownTransaction.class, TransactionType.UNKNOWN)
.put(ImmutableAmmClawback.class, TransactionType.AMM_CLAWBACK)
.build();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ public enum TransactionType {
@Beta
ORACLE_DELETE("OracleDelete"),

/**
* The {@link TransactionType} for the {@link AmmClawback} transaction.
*/
AMM_CLAWBACK("AMMClawback"),
@Beta
MPT_ISSUANCE_CREATE("MPTokenIssuanceCreate"),
@Beta
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import org.xrpl.xrpl4j.model.transactions.AccountSet;
import org.xrpl.xrpl4j.model.transactions.Address;
import org.xrpl.xrpl4j.model.transactions.AmmBid;
import org.xrpl.xrpl4j.model.transactions.AmmClawback;
import org.xrpl.xrpl4j.model.transactions.AmmCreate;
import org.xrpl.xrpl4j.model.transactions.AmmDelete;
import org.xrpl.xrpl4j.model.transactions.AmmDeposit;
Expand Down Expand Up @@ -850,6 +851,59 @@ void addSignatureToAmmCreate() {
addSignatureToTransactionHelper(ammCreate);
}

@Test
void addSignatureToAmmClawback() {
AmmClawback ammClawback = AmmClawback.builder()
.account(sourcePublicKey.deriveAddress())
.holder(sourcePublicKey.deriveAddress())
.amount(
IssuedCurrencyAmount.builder()
.currency("TST")
.issuer(Address.of("rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"))
.value("25")
.build()
)
.asset(Issue.XRP)
.asset2(
Issue.builder()
.issuer(Address.of("rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"))
.currency("TST")
.build()
)
.fee(XrpCurrencyAmount.ofDrops(10))
.sequence(UnsignedInteger.valueOf(6))
.signingPublicKey(sourcePublicKey)
.build();

addSignatureToTransactionHelper(ammClawback);
}

@Test
void addMultiSignaturesToAmmClawback() {
AmmClawback ammClawback = AmmClawback.builder()
.account(sourcePublicKey.deriveAddress())
.holder(sourcePublicKey.deriveAddress())
.amount(
IssuedCurrencyAmount.builder()
.currency("TST")
.issuer(Address.of("rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"))
.value("25")
.build()
)
.asset(Issue.XRP)
.asset2(
Issue.builder()
.issuer(Address.of("rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd"))
.currency("TST")
.build()
)
.fee(XrpCurrencyAmount.ofDrops(10))
.sequence(UnsignedInteger.valueOf(6))
.build();

addMultiSignatureToTransactionHelper(ammClawback);
}

@Test
void addSignatureToAmmDeposit() {
AmmDeposit deposit = AmmDeposit.builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.xrpl.xrpl4j.model.flags;

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

import com.fasterxml.jackson.core.JsonProcessingException;
import org.json.JSONException;
import org.junit.jupiter.api.Test;

class AmmClawbackFlagsTest extends AbstractFlagsTest {

@Test
void testFlagWithValue() {
AmmClawbackFlags flags = AmmClawbackFlags.CLAW_TWO_ASSETS;
assertThat(flags.isEmpty()).isFalse();

assertThat(flags.tfClawTwoAssets()).isTrue();
assertThat(flags.tfFullyCanonicalSig()).isFalse();
assertThat(flags.getValue()).isEqualTo(1L);
}

@Test
void testEmptyFlags() {
AmmClawbackFlags flags = AmmClawbackFlags.empty();
assertThat(flags.isEmpty()).isTrue();

assertThat(flags.tfClawTwoAssets()).isFalse();
assertThat(flags.tfFullyCanonicalSig()).isFalse();
assertThat(flags.getValue()).isZero();
}

@Test
void testJson() throws JSONException, JsonProcessingException {
TransactionFlagsWrapper wrapper = TransactionFlagsWrapper.of(AmmClawbackFlags.CLAW_TWO_ASSETS);
String json = String.format("{\n" +
" \"flags\": %s\n" +
"}", AmmClawbackFlags.CLAW_TWO_ASSETS.getValue());

assertCanSerializeAndDeserialize(wrapper, json);
}

@Test
void testEmptyJson() throws JSONException, JsonProcessingException {
AmmClawbackFlags flags = AmmClawbackFlags.empty();
AbstractFlagsTest.TransactionFlagsWrapper wrapper = AbstractFlagsTest.TransactionFlagsWrapper.of(flags);
String json = "{\n" +
"}";

assertCanSerializeAndDeserialize(wrapper, json);
}
}
Loading
Loading