remove SendPayment.java.

Add Java to send-xrp tutorial
This commit is contained in:
nkramer44
2021-05-04 15:50:32 -04:00
parent b1cbdeb331
commit 762cd6dc34
3 changed files with 163 additions and 61 deletions

View File

@@ -0,0 +1,102 @@
// Example Credentials ----------------------------------------------------------
WalletFactory walletFactory = DefaultWalletFactory.getInstance();
Wallet testWallet = walletFactory.fromSeed("sn3nxiW7v8KXzPzAqzyHXbSSKNuN9", true).wallet();
// Get the Classic address from testWallet
Address classicAddress = testWallet.classicAddress();
System.out.println(classicAddress); // "rMCcNuTcajgw7YTgBy1sys3b89QqjUrMpH"
// Connect ----------------------------------------------------------------------
HttpUrl rippledUrl = HttpUrl.get("https://s.altnet.rippletest.net:51234/");
XrplClient xrplClient = new XrplClient(rippledUrl);
// Prepare transaction ----------------------------------------------------------
// Look up your Account Info
AccountInfoRequestParams requestParams = AccountInfoRequestParams.builder()
.ledgerIndex(LedgerIndex.VALIDATED)
.account(classicAddress)
.build();
AccountInfoResult accountInfoResult = xrplClient.accountInfo(requestParams);
UnsignedInteger sequence = accountInfoResult.accountData().sequence();
// Request current fee information from rippled
FeeResult feeResult = xrplClient.fee();
XrpCurrencyAmount openLedgerFee = feeResult.drops().openLedgerFee();
// Get the latest validated ledger index
LedgerIndex validatedLedger = xrplClient.ledger(LedgerRequestParams.builder().ledgerIndex(LedgerIndex.VALIDATED).build())
.ledgerIndex()
.orElseThrow(() -> new RuntimeException("LedgerIndex not available."));
// Workaround for https://github.com/XRPLF/xrpl4j/issues/84
UnsignedInteger lastLedgerSequence = UnsignedInteger.valueOf(
validatedLedger.plus(UnsignedLong.valueOf(4)).unsignedLongValue().intValue()
);
// Construct a Payment
Payment payment = Payment.builder()
.account(classicAddress)
.amount(XrpCurrencyAmount.ofXrp(BigDecimal.ONE))
.destination(Address.of("rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe"))
.sequence(sequence)
.fee(openLedgerFee)
.signingPublicKey(testWallet.publicKey())
.lastLedgerSequence(lastLedgerSequence)
.build();
System.out.println("Constructed Payment: " + payment);
// Sign transaction -------------------------------------------------------------
// Construct a SignatureService to sign the Payment
PrivateKey privateKey = PrivateKey.fromBase16EncodedPrivateKey(testWallet.privateKey().get());
SignatureService signatureService = new SingleKeySignatureService(privateKey);
// Sign the Payment
SignedTransaction<Payment> signedPayment = signatureService.sign(KeyMetadata.EMPTY, payment);
System.out.println("Signed Payment: " + signedPayment.signedTransaction());
// Submit transaction -----------------------------------------------------------
SubmitResult<Transaction> submitResult = xrplClient.submit(signedPayment);
System.out.println(submitResult);
// Wait for validation ----------------------------------------------------------
boolean transactionValidated = false;
boolean transactionExpired = false;
while (!transactionValidated && !transactionExpired) {
Thread.sleep(4 * 1000);
LedgerIndex latestValidatedLedgerIndex = xrplClient.ledger(
LedgerRequestParams.builder().ledgerIndex(LedgerIndex.VALIDATED).build()
)
.ledgerIndex()
.orElseThrow(() -> new RuntimeException("Ledger response did not contain a LedgerIndex."));
TransactionResult<Payment> transactionResult = xrplClient.transaction(
TransactionRequestParams.of(signedPayment.hash()),
Payment.class
);
if (transactionResult.validated()) {
System.out.println("Payment was validated with result code " + transactionResult.metadata().get().transactionResult());
transactionValidated = true;
} else {
boolean lastLedgerSequenceHasPassed = FluentCompareTo.
is(latestValidatedLedgerIndex.unsignedLongValue())
.greaterThan(UnsignedLong.valueOf(lastLedgerSequence.intValue()));
if (lastLedgerSequenceHasPassed) {
System.out.println("Payment was never validated and has expired.");
transactionExpired = true;
} else {
System.out.println("Payment not yet validated.");
}
}
}
// Check transaction results ----------------------------------------------------
System.out.println(transactionResult);
System.out.println("Explorer link: https://testnet.xrpl.org/transactions/" + signedPayment.hash());
transactionResult.metadata().ifPresent(metadata -> {
System.out.println("Result code: " + metadata.transactionResult());
metadata.deliveredAmount().ifPresent(deliveredAmount ->
System.out.println("XRP Delivered: " + ((XrpCurrencyAmount) deliveredAmount).toXrp())
);
});

View File

@@ -1,56 +0,0 @@
// Construct a network client
final HttpUrl rippledUrl = HttpUrl.get("https://s.altnet.rippletest.net:51234/");
XrplClient xrplClient = new XrplClient(rippledUrl);
// Create a Wallet using a WalletFactory
WalletFactory walletFactory = DefaultWalletFactory.getInstance();
final Wallet testWallet = walletFactory.randomWallet(true).wallet();
System.out.println("Generated a wallet with the following public key: " + testWallet.publicKey());
// Get the Classic and X-Addresses from testWallet
final Address classicAddress = testWallet.classicAddress();
System.out.println("Classic Address: " + classicAddress);
// Fund the account using the testnet Faucet
final FaucetClient faucetClient = FaucetClient
.construct(HttpUrl.get("https://faucet.altnet.rippletest.net"));
faucetClient.fundAccount(FundAccountRequest.of(classicAddress));
System.out.println("Funded the account using the Testnet faucet.");
// Look up your Account Info
final AccountInfoRequestParams requestParams = AccountInfoRequestParams.of(classicAddress);
final AccountInfoResult accountInfoResult = xrplClient.accountInfo(requestParams);
final UnsignedInteger sequence = accountInfoResult.accountData().sequence();
// Request current fee information from rippled
final FeeResult feeResult = xrplClient.fee();
final XrpCurrencyAmount openLedgerFee = feeResult.drops().openLedgerFee();
// Construct a Payment
Payment payment = Payment.builder()
.account(classicAddress)
.amount(XrpCurrencyAmount.ofXrp(BigDecimal.ONE))
.destination(Address.of("rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe"))
.sequence(sequence)
.fee(openLedgerFee)
.signingPublicKey(testWallet.publicKey())
.build();
// Print the Payment
System.out.println("Constructed Payment: " + payment);
// Construct a SignatureService to sign the Payment
PrivateKey privateKey = PrivateKey.fromBase16EncodedPrivateKey(testWallet.privateKey().get());
SignatureService signatureService = new SingleKeySignatureService(privateKey);
// Sign the Payment
final SignedTransaction<Payment> signedPayment = signatureService.sign(KeyMetadata.EMPTY, payment);
// Print the signed transaction
System.out.println("Signed Payment: " + signedPayment.signedTransaction());
// Submit the Payment
final SubmitResult<Transaction> submitResult = xrplClient.submit(signedPayment);
// Print the response
System.out.println(submitResult);

View File

@@ -12,7 +12,7 @@ filters:
---
# Send XRP
This tutorial explains how to send a simple XRP Payment using ripple-lib for JavaScript or xrpl-py for Python. First, we step through the process with the [XRP Ledger Testnet](parallel-networks.html). Then, we compare that to the additional requirements for doing the equivalent in production.
This tutorial explains how to send a simple XRP Payment using ripple-lib for JavaScript, xrpl-py for Python, or xrpl4j for Java. First, we step through the process with the [XRP Ledger Testnet](parallel-networks.html). Then, we compare that to the additional requirements for doing the equivalent in production.
**Tip:** Check out the [Code Samples](https://github.com/ripple/xrpl-dev-portal/tree/master/content/_code-samples) for a complete version of the code used in this tutorial.
@@ -48,7 +48,7 @@ _Python_
_Java_
{{ include_code("_code-samples/send-xrp/send-xrp.py", end_before="# Connect", language="py") }}
{{ include_code("_code-samples/send-xrp/SendXrp.java", end_before="// Connect", language="java") }}
<!-- MULTICODE_BLOCK_END -->
@@ -75,6 +75,10 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py", start_with="# Connect", end_before="# Get credentials", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java", start_with="// Connect", end_before="// Prepare transaction", language="java") }}
<!-- MULTICODE_BLOCK_END -->
For this tutorial, you can connect directly from your browser by pressing the following button:
@@ -106,6 +110,9 @@ Technically, a viable transaction must contain some additional fields, and certa
- If you're using ripple-lib for JavaScript, you can use the [`prepareTransaction()` method](rippleapi-reference.html#preparetransaction) to automatically fill in good defaults for the remaining fields of a transaction.
- With xrpl-py for Python, you can use the models in `xrpl.models.transactions` to construct transactions as native Python objects.
- With xrpl4j for Java, you can use the model objects in the `xrpl4j-model` module to construct transactions as Java objects.
- Unlike the other SDKs, you must provide the account `sequence` and the `signingPublicKey` of the source
account of a `Transaction` at the time of construction, as well as a `fee`.
Here's an example of preparing the above payment:
@@ -119,6 +126,10 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py", start_with="# Prepare", end_before="# Sign", language="py" ) }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java", start_with="// Prepare", end_before="// Sign", language="java") }}
<!-- MULTICODE_BLOCK_END -->
{{ start_step("Prepare") }}
@@ -145,6 +156,7 @@ Signing a transaction uses your credentials to authorize the transaction on your
- **JavaScript:** Use the [sign() method](rippleapi-reference.html#sign) to sign the transaction with ripple-lib. The first argument is a string version of the JSON transaction to sign.
- **Python:** Use the [xrpl.transaction.safe_sign_transaction() method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.transaction.html#xrpl.transaction.safe_sign_transaction) with a model and wallet object.
- **Java:** Use a [`SignatureService`](https://javadoc.io/doc/org.xrpl/xrpl4j-crypto-core/latest/org/xrpl/xrpl4j/crypto/signing/SignatureService.html) instance to sign the transaction. For this tutorial, use the [`SingleKeySignatureService`](https://javadoc.io/doc/org.xrpl/xrpl4j-crypto-bouncycastle/latest/org/xrpl/xrpl4j/crypto/signing/SingleKeySignatureService.html).
<!-- MULTICODE_BLOCK_START -->
@@ -158,12 +170,18 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py",
start_with="# Sign", end_before="# Submit", language="py" ) }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java",
start_with="// Sign", end_before="// Submit", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
The result of the signing operation is a transaction object containing a signature. Typically, XRP Ledger APIs expect a signed transaction to be the hexadecimal representation of the transaction's canonical [binary format](serialization.html), called a "blob".
- In ripple-lib, the signing API also returns the transaction's ID, or identifying hash, which you can use to look up the transaction later. This is a 64-character hexadecimal string that is unique to this transaction.
- In xrpl-py, you can get the transaction's hash in the response to submitting it in the next step.
- In xrpl4j, `SignatureService.sign` returns a `SignedTransaction`, which contains the transaction's hash, which you can use to look up the transaction later.
{{ start_step("Sign") }}
<button id="sign-button" class="btn btn-primary previous-steps-required">Sign
@@ -178,7 +196,7 @@ Now that you have a signed transaction, you can submit it to an XRP Ledger serve
- **JavaScript:** Use the [submit() method](rippleapi-reference.html#submit) to submit a transaction to the network. Use the [`getLedgerVersion()` method](rippleapi-reference.html#getledgerversion) to get the latest validated ledger index.
- **Python:** Use the [xrpl.transaction.submit_transaction() method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.transaction.html#xrpl.transaction.submit_transaction) to submit a transaction to the network. Use the [xrpl.ledger.get_latest_validated_ledger_sequence() method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.ledger.html#xrpl.ledger.get_latest_validated_ledger_sequence) to get the latest validated ledger index.
- **Java:** Use the [XrplClient.submit(SignedTransaction>) method](https://javadoc.io/doc/org.xrpl/xrpl4j-client/latest/org/xrpl/xrpl4j/client/XrplClient.html) to submit a transaction to the network. Use the `XrplClient.ledger()` method to get the latest validated ledger index.
<!-- MULTICODE_BLOCK_START -->
@@ -190,6 +208,9 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py", start_with="# Submit", end_before="# Wait", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java", start_with="// Submit", end_before="// Wait", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
This method returns the **tentative** result of trying to apply the transaction to the open ledger. This result _can_ change when the transaction is included in a validated ledger: transactions that succeed initially might ultimately fail, and transactions that fail initially might ultimately succeed. Still, the tentative result often matches the final result, so it's OK to get excited if you see `tesSUCCESS` here. 😁
@@ -220,6 +241,8 @@ Most transactions are accepted into the next ledger version after they're submit
**Tip:** The [xrpl.transaction.send_reliable_submission() method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.transaction.html#xrpl.transaction.send_reliable_submission) handles this process all in one call. You can use this instead of `submit_transaction()` wherever it's appropriate for your code to stop and wait for a transaction's [final result](finality-of-results.html) to be confirmed.
- **Java** Poll the [XrplClient.transaction() method](https://javadoc.io/doc/org.xrpl/xrpl4j-client/latest/org/xrpl/xrpl4j/client/XrplClient.html) to see if your transaction has a final result. Periodically check that the latest validated ledger index has not passed the `LastLedgerIndex` of the transaction using the `XrplClient.ledger()` method.
<!-- MULTICODE_BLOCK_START -->
_JavaScript_
@@ -230,6 +253,10 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py", start_with="# Wait", end_before="# Check", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java", start_with="// Wait", end_before="// Check", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
{{ start_step("Wait") }}
@@ -243,6 +270,7 @@ To know for sure what a transaction did, you must look up the outcome of the tra
- **JavaScript:** Use the [`getTransaction()` method](rippleapi-reference.html#gettransaction) to check the status of a transaction.
- **Python:** The response of [xrpl.transaction.get_transaction_from_hash() method](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.transaction.html#xrpl.transaction.get_transaction_from_hash) contains the results if the transaction has been validated by consensus. (See [tx result](https://xrpl.org/tx.html#response-format) for a detailed reference of the fields this can contain.)
- **Java:** Use the `XrplClient.transaction()` method to check the status of a transaction.
<!-- MULTICODE_BLOCK_START -->
@@ -254,6 +282,10 @@ _Python_
{{ include_code("_code-samples/send-xrp/send-xrp.py", start_with="# Check", language="py") }}
_Java_
{{ include_code("_code-samples/send-xrp/SendXrp.java", start_with="// Check", language="java" ) }}
<!-- MULTICODE_BLOCK_END -->
The RippleAPI `getTransaction()` method only returns success if the transaction is in a validated ledger version. Otherwise, the `await` expression raises an exception.
@@ -296,6 +328,16 @@ print(my_wallet.classic_address) # Example: rGCkuB7PBr5tNy68tPEABEtcdno4hE6Y7f
print(my_wallet.seed) # Example: sp6JS7f14BuwFY8Mw6bTtLKWauoUs
```
_Java_
```java
WalletFactory walletFactory = DefaultWalletFactory.getInstance();
SeedWalletGenerationResult generationResult = walletFactory.randomWallet(false);
Wallet wallet = generationResult.wallet();
System.out.println(wallet.classicAddress()); // Example: rGCkuB7PBr5tNy68tPEABEtcdno4hE6Y7f
System.out.println(generationResult.seed()); // Example: sp6JS7f14BuwFY8Mw6bTtLKWauoUs
```
<!-- MULTICODE_BLOCK_END -->
**Warning:** You should only use an address and secret that you generated securely, on your local machine. If another computer generated the address and secret and sent it to you over a network, it's possible that someone else on the network may see that information. If they do, they'll have as much control over your XRP as you do. It's also recommended not to use the same address for the Testnet and Mainnet, because transactions that you created for use on one network could potentially also be viable on the other network, depending on the parameters you provided.
@@ -324,6 +366,13 @@ mainnet_url = "https://xrplcluster.com"
client = JsonRpcClient(mainnet_url)
```
_Java_
```java
final HttpUrl rippledUrl = HttpUrl.get("https://xrplcluster.com");
XrplClient xrplClient = new XrplClient(rippledUrl);
```
<!-- MULTICODE_BLOCK_END -->
If you [install `rippled`](install-rippled.html) yourself, it connects to the production network by default. (You can also [configure it to connect to the test net](connect-your-rippled-to-the-xrp-test-net.html) instead.) After the server has synced (typically within about 15 minutes of starting it up), you can connect to it locally, which has [various benefits](the-rippled-server.html). The following example shows how to connect to a server running the default configuration:
@@ -346,6 +395,13 @@ mainnet_url = "http://localhost:5005"
client = JsonRpcClient(mainnet_url)
```
_Java_
```java
final HttpUrl rippledUrl = HttpUrl.get("http://localhost:5005");
XrplClient xrplClient = new XrplClient(rippledUrl);
```
<!-- MULTICODE_BLOCK_END -->
**Tip:** The local connection uses an unencrypted protocol (`ws` or `http`) rather than the TLS-encrypted version (`wss` or `https`). This is secure only because the communications never leave the same machine, and is easier to set up because it does not require a TLS certificate. For connections on an outside network, always use `wss` or `https`.
@@ -355,7 +411,7 @@ client = JsonRpcClient(mainnet_url)
After completing this tutorial, you may want to try the following:
- Build [Reliable transaction submission](reliable-transaction-submission.html) for production systems.
- Consult [RippleAPI JavaScript Reference](rippleapi-reference.html) or [xrpl-py Python Reference](https://xrpl-py.readthedocs.io/) for the full range of XRP Ledger functionality.
- Consult [RippleAPI JavaScript Reference](rippleapi-reference.html), [xrpl-py Python Reference](https://xrpl-py.readthedocs.io/), or [xrpl4j Javadocs](https://javadoc.io/doc/org.xrpl/) for the full range of XRP Ledger functionality.
- Customize your [Account Settings](manage-account-settings.html).
- Learn how [Transaction Metadata](transaction-metadata.html) describes the outcome of a transaction in detail.
- Explore more [Payment Types](payment-types.html) such as Escrows and Payment Channels.