Skip to content

Commit 04e700c

Browse files
committed
Add tests to validate circular escrows
1 parent 85a1156 commit 04e700c

File tree

1 file changed

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

1 file changed

+226
-0
lines changed

xrpl4j-integration-tests/src/test/java/org/xrpl/xrpl4j/tests/EscrowIT.java

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,119 @@ public void createAndFinishTimeBasedEscrow() throws JsonRpcClientErrorException,
162162

163163
}
164164

165+
/**
166+
* It is acceptable for an escrow to have the same source and destination accounts specified. This test verifies that
167+
* works properly when the escrow is finished.
168+
*/
169+
@Test
170+
public void createAndFinishTimeBasedEscrowToSelf() throws JsonRpcClientErrorException, JsonProcessingException {
171+
//////////////////////
172+
// Create random sender accounts
173+
KeyPair senderKeyPair = createRandomAccountEd25519();
174+
175+
//////////////////////
176+
// Sender account creates an Escrow with the receiver account
177+
FeeResult feeResult = xrplClient.fee();
178+
final AccountInfoResult senderAccountInfo = this.scanForResult(
179+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
180+
);
181+
assertThat(senderAccountInfo.accountData().balance()).isEqualTo(XrpCurrencyAmount.ofDrops(1000000000));
182+
183+
EscrowCreate escrowCreate = EscrowCreate.builder()
184+
.account(senderKeyPair.publicKey().deriveAddress())
185+
.sequence(senderAccountInfo.accountData().sequence())
186+
.fee(feeResult.drops().openLedgerFee())
187+
.amount(XrpCurrencyAmount.ofDrops(123456))
188+
.destination(senderKeyPair.publicKey().deriveAddress())
189+
.cancelAfter(instantToXrpTimestamp(getMinExpirationTime().plus(Duration.ofSeconds(100))))
190+
.finishAfter(instantToXrpTimestamp(getMinExpirationTime().plus(Duration.ofSeconds(5))))
191+
.signingPublicKey(senderKeyPair.publicKey())
192+
.build();
193+
194+
//////////////////////
195+
// Submit the EscrowCreate transaction and validate that it was successful
196+
SingleSignedTransaction<EscrowCreate> signedEscrowCreate = signatureService.sign(
197+
senderKeyPair.privateKey(), escrowCreate
198+
);
199+
SubmitResult<EscrowCreate> createResult = xrplClient.submit(signedEscrowCreate);
200+
assertThat(createResult.engineResult()).isEqualTo("tesSUCCESS");
201+
logger.info(
202+
"EscrowCreate transaction successful: https://testnet.xrpl.org/transactions/{}",
203+
createResult.transactionResult().hash()
204+
);
205+
206+
//////////////////////
207+
// Then wait until the transaction gets committed to a validated ledger
208+
TransactionResult<EscrowCreate> result = this.scanForResult(
209+
() -> this.getValidatedTransaction(createResult.transactionResult().hash(), EscrowCreate.class)
210+
);
211+
212+
assertEntryEqualsObjectFromAccountObjects(
213+
senderKeyPair.publicKey().deriveAddress(),
214+
escrowCreate.sequence()
215+
);
216+
217+
//////////////////////
218+
// Wait until the close time on the current validated ledger is after the finishAfter time on the Escrow
219+
this.scanForResult(
220+
this::getValidatedLedger,
221+
ledgerResult ->
222+
FluentCompareTo.is(ledgerResult.ledger().closeTime().orElse(UnsignedLong.ZERO))
223+
.greaterThan(
224+
createResult.transactionResult().transaction().finishAfter()
225+
.map(finishAfter -> finishAfter.plus(UnsignedLong.valueOf(5)))
226+
.orElse(UnsignedLong.MAX_VALUE)
227+
)
228+
);
229+
230+
final AccountInfoResult postEscrowCreateSenderAccountInfo = this.scanForResult(
231+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
232+
);
233+
assertThat(postEscrowCreateSenderAccountInfo.accountData().balance())
234+
.isEqualTo(XrpCurrencyAmount.ofDrops(999876534));
235+
236+
//////////////////////
237+
// Receiver submits an EscrowFinish transaction to release the Escrow funds
238+
final AccountInfoResult preEscrowFinishSenderAccountInfo = this.scanForResult(
239+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
240+
);
241+
EscrowFinish escrowFinish = EscrowFinish.builder()
242+
.account(senderKeyPair.publicKey().deriveAddress())
243+
.fee(feeResult.drops().openLedgerFee())
244+
.sequence(preEscrowFinishSenderAccountInfo.accountData().sequence())
245+
.owner(senderKeyPair.publicKey().deriveAddress())
246+
.offerSequence(result.transaction().sequence())
247+
.signingPublicKey(senderKeyPair.publicKey())
248+
.build();
249+
250+
SingleSignedTransaction<EscrowFinish> signedEscrowFinish = signatureService.sign(
251+
senderKeyPair.privateKey(), escrowFinish
252+
);
253+
SubmitResult<EscrowFinish> finishResult = xrplClient.submit(signedEscrowFinish);
254+
assertThat(finishResult.engineResult()).isEqualTo("tesSUCCESS");
255+
logger.info(
256+
"EscrowFinish transaction successful: https://testnet.xrpl.org/transactions/{}",
257+
finishResult.transactionResult().hash()
258+
);
259+
260+
//////////////////////
261+
// Wait for the EscrowFinish to get applied to a validated ledger
262+
this.scanForResult(
263+
() -> this.getValidatedTransaction(finishResult.transactionResult().hash(), EscrowFinish.class)
264+
);
265+
266+
/////////////////////
267+
// Ensure that the funds were released to the receiver.
268+
this.scanForResult(
269+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress()),
270+
infoResult -> infoResult.accountData().balance().equals(
271+
preEscrowFinishSenderAccountInfo.accountData().balance()
272+
.plus(escrowCreate.amount())
273+
.minus(feeResult.drops().openLedgerFee()))
274+
&& infoResult.accountData().balance().equals(XrpCurrencyAmount.ofDrops(999999980))
275+
);
276+
}
277+
165278
@Test
166279
public void createAndCancelTimeBasedEscrow() throws JsonRpcClientErrorException, JsonProcessingException {
167280
//////////////////////
@@ -269,6 +382,119 @@ public void createAndCancelTimeBasedEscrow() throws JsonRpcClientErrorException,
269382
);
270383
}
271384

385+
/**
386+
* It is acceptable for an escrow to have the same source and destination accounts specified. This test verifies that
387+
* works properly when the escrow is cancelled.
388+
*/
389+
@Test
390+
public void createAndCancelTimeBasedEscrowToSelf() throws JsonRpcClientErrorException, JsonProcessingException {
391+
//////////////////////
392+
// Create random sender accounts
393+
KeyPair senderKeyPair = createRandomAccountEd25519();
394+
395+
//////////////////////
396+
// Sender account creates an Escrow with the receiver account
397+
FeeResult feeResult = xrplClient.fee();
398+
final AccountInfoResult senderAccountInfo = this.scanForResult(
399+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
400+
);
401+
assertThat(senderAccountInfo.accountData().balance()).isEqualTo(XrpCurrencyAmount.ofDrops(1000000000));
402+
403+
EscrowCreate escrowCreate = EscrowCreate.builder()
404+
.account(senderKeyPair.publicKey().deriveAddress())
405+
.sequence(senderAccountInfo.accountData().sequence())
406+
.fee(feeResult.drops().openLedgerFee())
407+
.amount(XrpCurrencyAmount.ofDrops(123456))
408+
.destination(senderKeyPair.publicKey().deriveAddress())
409+
.cancelAfter(instantToXrpTimestamp(getMinExpirationTime().plus(Duration.ofSeconds(100))))
410+
.finishAfter(instantToXrpTimestamp(getMinExpirationTime().plus(Duration.ofSeconds(95))))
411+
.signingPublicKey(senderKeyPair.publicKey())
412+
.build();
413+
414+
//////////////////////
415+
// Submit the EscrowCreate transaction and validate that it was successful
416+
SingleSignedTransaction<EscrowCreate> signedEscrowCreate = signatureService.sign(
417+
senderKeyPair.privateKey(), escrowCreate
418+
);
419+
SubmitResult<EscrowCreate> createResult = xrplClient.submit(signedEscrowCreate);
420+
assertThat(createResult.engineResult()).isEqualTo("tesSUCCESS");
421+
logger.info(
422+
"EscrowCreate transaction successful: https://testnet.xrpl.org/transactions/{}",
423+
createResult.transactionResult().hash()
424+
);
425+
426+
//////////////////////
427+
// Then wait until the transaction gets committed to a validated ledger
428+
TransactionResult<EscrowCreate> result = this.scanForResult(
429+
() -> this.getValidatedTransaction(createResult.transactionResult().hash(), EscrowCreate.class)
430+
);
431+
432+
assertEntryEqualsObjectFromAccountObjects(
433+
senderKeyPair.publicKey().deriveAddress(),
434+
escrowCreate.sequence()
435+
);
436+
437+
//////////////////////
438+
// Wait until the close time on the current validated ledger is after the finishAfter time on the Escrow
439+
this.scanForResult(
440+
this::getValidatedLedger,
441+
ledgerResult ->
442+
FluentCompareTo.is(ledgerResult.ledger().closeTime().orElse(UnsignedLong.ZERO))
443+
.greaterThan(
444+
createResult.transactionResult().transaction().finishAfter()
445+
.map(finishAfter -> finishAfter.plus(UnsignedLong.valueOf(5)))
446+
.orElse(UnsignedLong.MAX_VALUE)
447+
)
448+
);
449+
450+
final AccountInfoResult postEscrowCreateSenderAccountInfo = this.scanForResult(
451+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
452+
);
453+
assertThat(postEscrowCreateSenderAccountInfo.accountData().balance())
454+
.isEqualTo(XrpCurrencyAmount.ofDrops(999876534));
455+
456+
//////////////////////
457+
// Receiver submits an EscrowFinish transaction to release the Escrow funds
458+
final AccountInfoResult preEscrowFinishSenderAccountInfo = this.scanForResult(
459+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress())
460+
);
461+
EscrowCancel escrowCancel = EscrowCancel.builder()
462+
.account(senderKeyPair.publicKey().deriveAddress())
463+
.fee(feeResult.drops().openLedgerFee())
464+
.sequence(preEscrowFinishSenderAccountInfo.accountData().sequence())
465+
.owner(senderKeyPair.publicKey().deriveAddress())
466+
.offerSequence(result.transaction().sequence())
467+
.signingPublicKey(senderKeyPair.publicKey())
468+
.build();
469+
470+
SingleSignedTransaction<EscrowCancel> signedEscrowCancel = signatureService.sign(
471+
senderKeyPair.privateKey(), escrowCancel
472+
);
473+
SubmitResult<EscrowCancel> cancelResult = xrplClient.submit(signedEscrowCancel);
474+
assertThat(cancelResult.engineResult()).isEqualTo("tesSUCCESS");
475+
logger.info(
476+
"EscrowFinish transaction successful: https://testnet.xrpl.org/transactions/{}",
477+
cancelResult.transactionResult().hash()
478+
);
479+
480+
//////////////////////
481+
// Wait for the EscrowFinish to get applied to a validated ledger
482+
this.scanForResult(
483+
() -> this.getValidatedTransaction(cancelResult.transactionResult().hash(), EscrowCancel.class)
484+
);
485+
486+
/////////////////////
487+
// Ensure that the funds were released to the receiver.
488+
this.scanForResult(
489+
() -> this.getValidatedAccountInfo(senderKeyPair.publicKey().deriveAddress()),
490+
infoResult -> infoResult.accountData().balance().equals(
491+
preEscrowFinishSenderAccountInfo.accountData().balance()
492+
.plus(escrowCreate.amount())
493+
.minus(feeResult.drops().openLedgerFee()))
494+
&& infoResult.accountData().balance().equals(XrpCurrencyAmount.ofDrops(999999980))
495+
);
496+
}
497+
272498
@Test
273499
public void createAndFinishCryptoConditionBasedEscrow() throws JsonRpcClientErrorException, JsonProcessingException {
274500
//////////////////////

0 commit comments

Comments
 (0)