Skip to content

Commit af2fc8f

Browse files
committed
added integration tests related to Delegate
1 parent 408efff commit af2fc8f

File tree

1 file changed

+330
-0
lines changed
  • xrpl4j-integration-tests/src/test/java/org/xrpl/xrpl4j/tests

1 file changed

+330
-0
lines changed
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
package org.xrpl.xrpl4j.tests;
2+
3+
/*-
4+
* ========================LICENSE_START=================================
5+
* xrpl4j :: integration-tests
6+
* %%
7+
* Copyright (C) 2020 - 2023 XRPL Foundation and its contributors
8+
* %%
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
* =========================LICENSE_END==================================
21+
*/
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
import com.fasterxml.jackson.core.JsonProcessingException;
26+
import com.google.common.primitives.UnsignedInteger;
27+
import org.junit.jupiter.api.BeforeEach;
28+
import org.junit.jupiter.api.Test;
29+
import org.junit.jupiter.api.condition.DisabledIf;
30+
import org.xrpl.xrpl4j.client.JsonRpcClientErrorException;
31+
import org.xrpl.xrpl4j.crypto.keys.KeyPair;
32+
import org.xrpl.xrpl4j.crypto.signing.SingleSignedTransaction;
33+
import org.xrpl.xrpl4j.model.client.accounts.AccountInfoResult;
34+
import org.xrpl.xrpl4j.model.client.fees.FeeResult;
35+
import org.xrpl.xrpl4j.model.client.fees.FeeUtils;
36+
import org.xrpl.xrpl4j.model.client.transactions.SubmitResult;
37+
import org.xrpl.xrpl4j.model.client.transactions.TransactionResult;
38+
import org.xrpl.xrpl4j.model.flags.TrustSetFlags;
39+
import org.xrpl.xrpl4j.model.transactions.DelegateSet;
40+
import org.xrpl.xrpl4j.model.transactions.GranularPermission;
41+
import org.xrpl.xrpl4j.model.transactions.IssuedCurrencyAmount;
42+
import org.xrpl.xrpl4j.model.transactions.NetworkId;
43+
import org.xrpl.xrpl4j.model.transactions.Payment;
44+
import org.xrpl.xrpl4j.model.transactions.Permission;
45+
import org.xrpl.xrpl4j.model.transactions.PermissionWrapper;
46+
import org.xrpl.xrpl4j.model.transactions.TransactionType;
47+
import org.xrpl.xrpl4j.model.transactions.TrustSet;
48+
import org.xrpl.xrpl4j.model.transactions.XrpCurrencyAmount;
49+
50+
/**
51+
* Integration tests for the Delegate field on transactions (XLS-75 Permission Delegation).
52+
*
53+
* <p><b>IMPORTANT:</b> These tests are currently disabled because the PermissionDelegation amendment
54+
* is not yet implemented in any released version of rippled. The amendment was disabled in rippled 2.6.1
55+
* due to a bug and has not been re-enabled. These tests will fail with "temDISABLED" until XLS-75 is
56+
* implemented and enabled on a rippled node.</p>
57+
*
58+
* <p>To run these tests (they will fail): mvn test -Dtest=DelegateIT -DenableXLS75Tests=true</p>
59+
*/
60+
@DisabledIf(value = "shouldNotRun", disabledReason = "XLS-75 PermissionDelegation is not yet implemented in rippled")
61+
public class DelegateIT extends AbstractIT {
62+
63+
static boolean shouldNotRun() {
64+
// XLS-75 (PermissionDelegation) is not yet implemented in any released version of rippled.
65+
// The amendment was disabled in rippled 2.6.1 due to a bug and has not been re-enabled.
66+
// These tests will always be skipped until XLS-75 is available in rippled.
67+
//
68+
// To force run these tests (they will fail with temDISABLED):
69+
// mvn test -Dtest=DelegateIT -DenableXLS75Tests=true
70+
return System.getProperty("enableXLS75Tests") == null;
71+
}
72+
73+
public static final String SUCCESS_STATUS = "tesSUCCESS";
74+
75+
private NetworkId networkId;
76+
77+
@BeforeEach
78+
public void setUp() throws JsonRpcClientErrorException {
79+
// Query the network ID from the server
80+
networkId = xrplClient.serverInformation().info().networkId()
81+
.orElse(NetworkId.of(UnsignedInteger.ZERO));
82+
logger.info("Using NetworkID: {}", networkId);
83+
}
84+
85+
@Test
86+
public void testDelegateSetTransaction() throws JsonRpcClientErrorException, JsonProcessingException {
87+
// Create two accounts: delegating account and delegate
88+
KeyPair delegatingAccountKeyPair = createRandomAccountEd25519();
89+
KeyPair delegateKeyPair = createRandomAccountEd25519();
90+
91+
FeeResult feeResult = xrplClient.fee();
92+
AccountInfoResult delegatingAccountInfo = this.scanForResult(
93+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
94+
);
95+
96+
// Create a DelegateSet transaction to authorize the delegate
97+
DelegateSet delegateSet = DelegateSet.builder()
98+
.account(delegatingAccountKeyPair.publicKey().deriveAddress())
99+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
100+
.sequence(delegatingAccountInfo.accountData().sequence())
101+
.authorize(delegateKeyPair.publicKey().deriveAddress())
102+
.addPermissions(
103+
PermissionWrapper.builder().permission(Permission.of(TransactionType.PAYMENT)).build(),
104+
PermissionWrapper.builder().permission(Permission.of(TransactionType.TRUST_SET)).build()
105+
)
106+
.signingPublicKey(delegatingAccountKeyPair.publicKey())
107+
.networkId(networkId)
108+
.build();
109+
110+
SingleSignedTransaction<DelegateSet> signedDelegateSet = signatureService.sign(
111+
delegatingAccountKeyPair.privateKey(), delegateSet
112+
);
113+
SubmitResult<DelegateSet> result = xrplClient.submit(signedDelegateSet);
114+
assertThat(result.engineResult()).isEqualTo(SUCCESS_STATUS);
115+
logger.info("DelegateSet successful: https://testnet.xrpl.org/transactions/{}",
116+
result.transactionResult().hash());
117+
118+
TransactionResult<DelegateSet> validatedDelegateSet = this.scanForResult(
119+
() -> this.getValidatedTransaction(result.transactionResult().hash(), DelegateSet.class)
120+
);
121+
122+
assertThat(validatedDelegateSet.metadata().get().transactionResult()).isEqualTo(SUCCESS_STATUS);
123+
}
124+
125+
@Test
126+
public void testPaymentWithDelegate() throws JsonRpcClientErrorException, JsonProcessingException {
127+
// Create three accounts: delegating account, delegate, and destination
128+
KeyPair delegatingAccountKeyPair = createRandomAccountEd25519();
129+
KeyPair delegateKeyPair = createRandomAccountEd25519();
130+
KeyPair destinationKeyPair = createRandomAccountEd25519();
131+
132+
FeeResult feeResult = xrplClient.fee();
133+
134+
// First, authorize the delegate using DelegateSet
135+
AccountInfoResult delegatingAccountInfo = this.scanForResult(
136+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
137+
);
138+
139+
DelegateSet delegateSet = DelegateSet.builder()
140+
.account(delegatingAccountKeyPair.publicKey().deriveAddress())
141+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
142+
.sequence(delegatingAccountInfo.accountData().sequence())
143+
.authorize(delegateKeyPair.publicKey().deriveAddress())
144+
.addPermissions(PermissionWrapper.builder().permission(Permission.of(TransactionType.PAYMENT)).build())
145+
.signingPublicKey(delegatingAccountKeyPair.publicKey())
146+
.networkId(networkId)
147+
.build();
148+
149+
SingleSignedTransaction<DelegateSet> signedDelegateSet = signatureService.sign(
150+
delegatingAccountKeyPair.privateKey(), delegateSet
151+
);
152+
SubmitResult<DelegateSet> delegateSetResult = xrplClient.submit(signedDelegateSet);
153+
assertThat(delegateSetResult.engineResult()).isEqualTo(SUCCESS_STATUS);
154+
155+
this.scanForResult(
156+
() -> this.getValidatedTransaction(delegateSetResult.transactionResult().hash(), DelegateSet.class)
157+
);
158+
159+
// Get updated account info
160+
AccountInfoResult updatedDelegatingAccountInfo = this.scanForResult(
161+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
162+
);
163+
164+
// Get delegate account info to check balance before payment
165+
final AccountInfoResult delegateAccountInfoBefore = this.scanForResult(
166+
() -> this.getValidatedAccountInfo(delegateKeyPair.publicKey().deriveAddress())
167+
);
168+
169+
170+
171+
// Now send a Payment transaction with the Delegate field
172+
// The delegate signs the transaction, but the Account field is the delegating account
173+
XrpCurrencyAmount amount = XrpCurrencyAmount.ofDrops(12345);
174+
Payment payment = Payment.builder()
175+
.account(delegatingAccountKeyPair.publicKey().deriveAddress()) // Delegating account
176+
.delegate(delegateKeyPair.publicKey().deriveAddress()) // Delegate
177+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
178+
.sequence(updatedDelegatingAccountInfo.accountData().sequence())
179+
.destination(destinationKeyPair.publicKey().deriveAddress())
180+
.amount(amount)
181+
.signingPublicKey(delegateKeyPair.publicKey()) // Delegate's public key
182+
.networkId(networkId)
183+
.build();
184+
185+
// Sign with delegate's private key
186+
SingleSignedTransaction<Payment> signedPayment = signatureService.sign(delegateKeyPair.privateKey(), payment);
187+
SubmitResult<Payment> paymentResult = xrplClient.submit(signedPayment);
188+
assertThat(paymentResult.engineResult()).isEqualTo(SUCCESS_STATUS);
189+
logger.info("Payment with Delegate successful: https://testnet.xrpl.org/transactions/{}",
190+
paymentResult.transactionResult().hash());
191+
192+
TransactionResult<Payment> validatedPayment = this.scanForResult(
193+
() -> this.getValidatedTransaction(paymentResult.transactionResult().hash(), Payment.class)
194+
);
195+
196+
assertThat(validatedPayment.metadata().get().transactionResult()).isEqualTo(SUCCESS_STATUS);
197+
198+
// Verify that the delegate paid the fees (delegate's balance should decrease)
199+
AccountInfoResult delegateAccountInfoAfter = this.scanForResult(
200+
() -> this.getValidatedAccountInfo(delegateKeyPair.publicKey().deriveAddress())
201+
);
202+
203+
XrpCurrencyAmount delegateBalanceBefore = delegateAccountInfoBefore.accountData().balance();
204+
XrpCurrencyAmount delegateBalanceAfter = delegateAccountInfoAfter.accountData().balance();
205+
XrpCurrencyAmount fee = payment.fee();
206+
207+
// Delegate's balance should decrease by the fee amount
208+
assertThat(delegateBalanceAfter.plus(fee)).isEqualTo(delegateBalanceBefore);
209+
210+
// Verify that only the delegating account's sequence number was incremented
211+
AccountInfoResult finalDelegatingAccountInfo = this.scanForResult(
212+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
213+
);
214+
215+
assertThat(finalDelegatingAccountInfo.accountData().sequence())
216+
.isEqualTo(updatedDelegatingAccountInfo.accountData().sequence().plus(UnsignedInteger.ONE));
217+
}
218+
219+
@Test
220+
public void testTrustSetWithDelegate() throws JsonRpcClientErrorException, JsonProcessingException {
221+
// Create three accounts: delegating account, delegate, and issuer
222+
KeyPair delegatingAccountKeyPair = createRandomAccountEd25519();
223+
KeyPair delegateKeyPair = createRandomAccountEd25519();
224+
KeyPair issuerKeyPair = createRandomAccountEd25519();
225+
226+
FeeResult feeResult = xrplClient.fee();
227+
228+
// First, authorize the delegate using DelegateSet
229+
AccountInfoResult delegatingAccountInfo = this.scanForResult(
230+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
231+
);
232+
233+
DelegateSet delegateSet = DelegateSet.builder()
234+
.account(delegatingAccountKeyPair.publicKey().deriveAddress())
235+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
236+
.sequence(delegatingAccountInfo.accountData().sequence())
237+
.authorize(delegateKeyPair.publicKey().deriveAddress())
238+
.addPermissions(PermissionWrapper.builder().permission(Permission.of(TransactionType.TRUST_SET)).build())
239+
.signingPublicKey(delegatingAccountKeyPair.publicKey())
240+
.networkId(networkId)
241+
.build();
242+
243+
SingleSignedTransaction<DelegateSet> signedDelegateSet = signatureService.sign(
244+
delegatingAccountKeyPair.privateKey(), delegateSet
245+
);
246+
SubmitResult<DelegateSet> delegateSetResult = xrplClient.submit(signedDelegateSet);
247+
assertThat(delegateSetResult.engineResult()).isEqualTo(SUCCESS_STATUS);
248+
249+
this.scanForResult(
250+
() -> this.getValidatedTransaction(delegateSetResult.transactionResult().hash(), DelegateSet.class)
251+
);
252+
253+
// Get updated account info
254+
AccountInfoResult updatedDelegatingAccountInfo = this.scanForResult(
255+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
256+
);
257+
258+
// Now send a TrustSet transaction with the Delegate field
259+
IssuedCurrencyAmount limitAmount = IssuedCurrencyAmount.builder()
260+
.currency("USD")
261+
.issuer(issuerKeyPair.publicKey().deriveAddress())
262+
.value("1000")
263+
.build();
264+
265+
TrustSet trustSet = TrustSet.builder()
266+
.account(delegatingAccountKeyPair.publicKey().deriveAddress()) // Delegating account
267+
.delegate(delegateKeyPair.publicKey().deriveAddress()) // Delegate
268+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
269+
.sequence(updatedDelegatingAccountInfo.accountData().sequence())
270+
.limitAmount(limitAmount)
271+
.flags(TrustSetFlags.empty())
272+
.signingPublicKey(delegateKeyPair.publicKey()) // Delegate's public key
273+
.networkId(networkId)
274+
.build();
275+
276+
// Sign with delegate's private key
277+
SingleSignedTransaction<TrustSet> signedTrustSet = signatureService.sign(delegateKeyPair.privateKey(), trustSet);
278+
SubmitResult<TrustSet> trustSetResult = xrplClient.submit(signedTrustSet);
279+
assertThat(trustSetResult.engineResult()).isEqualTo(SUCCESS_STATUS);
280+
logger.info("TrustSet with Delegate successful: https://testnet.xrpl.org/transactions/{}",
281+
trustSetResult.transactionResult().hash());
282+
283+
TransactionResult<TrustSet> validatedTrustSet = this.scanForResult(
284+
() -> this.getValidatedTransaction(trustSetResult.transactionResult().hash(), TrustSet.class)
285+
);
286+
287+
assertThat(validatedTrustSet.metadata().get().transactionResult()).isEqualTo(SUCCESS_STATUS);
288+
}
289+
290+
@Test
291+
public void testDelegateSetWithGranularPermissions() throws JsonRpcClientErrorException, JsonProcessingException {
292+
// Create two accounts: delegating account and delegate
293+
KeyPair delegatingAccountKeyPair = createRandomAccountEd25519();
294+
KeyPair delegateKeyPair = createRandomAccountEd25519();
295+
296+
FeeResult feeResult = xrplClient.fee();
297+
AccountInfoResult delegatingAccountInfo = this.scanForResult(
298+
() -> this.getValidatedAccountInfo(delegatingAccountKeyPair.publicKey().deriveAddress())
299+
);
300+
301+
// Create a DelegateSet transaction with granular permissions
302+
DelegateSet delegateSet = DelegateSet.builder()
303+
.account(delegatingAccountKeyPair.publicKey().deriveAddress())
304+
.fee(FeeUtils.computeNetworkFees(feeResult).recommendedFee())
305+
.sequence(delegatingAccountInfo.accountData().sequence())
306+
.authorize(delegateKeyPair.publicKey().deriveAddress())
307+
.addPermissions(
308+
PermissionWrapper.builder().permission(Permission.of(GranularPermission.TRUSTLINE_AUTHORIZE)).build(),
309+
PermissionWrapper.builder().permission(Permission.of(GranularPermission.TRUSTLINE_FREEZE)).build(),
310+
PermissionWrapper.builder().permission(Permission.of(GranularPermission.PAYMENT_MINT)).build()
311+
)
312+
.signingPublicKey(delegatingAccountKeyPair.publicKey())
313+
.networkId(networkId)
314+
.build();
315+
316+
SingleSignedTransaction<DelegateSet> signedDelegateSet = signatureService.sign(
317+
delegatingAccountKeyPair.privateKey(), delegateSet
318+
);
319+
SubmitResult<DelegateSet> result = xrplClient.submit(signedDelegateSet);
320+
assertThat(result.engineResult()).isEqualTo(SUCCESS_STATUS);
321+
logger.info("DelegateSet with granular permissions successful: https://testnet.xrpl.org/transactions/{}",
322+
result.transactionResult().hash());
323+
324+
TransactionResult<DelegateSet> validatedDelegateSet = this.scanForResult(
325+
() -> this.getValidatedTransaction(result.transactionResult().hash(), DelegateSet.class)
326+
);
327+
328+
assertThat(validatedDelegateSet.metadata().get().transactionResult()).isEqualTo(SUCCESS_STATUS);
329+
}
330+
}

0 commit comments

Comments
 (0)