This guide outlines the differences between v2.5.1 and v3.0.0 and aims to provide an upgrade path from v2.5.1 to v3.0.0.
In v3.0.0, the following modules were condensed into the xrpl-core
module:
xrpl4j-address-codec
xrpl4j-binary-codec
xrpl4j-model
xrpl4j-keypairs
xrpl4j-crypto-core
xrpl4j-crypto-bouncycastle
As a result, there are only three primary dependencies created by this project: xrpl4j-bom
, xrpl4j-core
and
xrpl4j-client
. Any projects that previously depended on any of the above artifacts should now simply depend on
xrpl4j-core
and/or xrpl4j-client
.
All classes in the former xrpl4j-keypairs
module have been removed from the library
and should be replaced by the classes found in the org.xrpl.xrpl4j.crypto
package in
the xrpl-core
module. The following section outlines how to migrate from using classes found in xrpl4j-keypairs
to classes in v3.0.0.
Wallet
, WalletFactory
, DefaultWalletFactory
and SeedWalletGenerationResult
have been removed in favor
of classes in org.xrpl.xrpl4j.crypto
.
Instead of creating a random wallet via WalletFactory.randomWallet
, developers should use the
org.xrpl.xrpl4j.crypto.keys.Seed
class to generate a random seed, which can then be used to derive a
org.xrpl.xrpl4j.crypto.keys.KeyPair
. The KeyPair
's PublicKey
can then be used to derive the wallet's Address
:
import org.xrpl.xrpl4j.crypto.keys.Seed;
import org.xrpl.xrpl4j.crypto.keys.KeyPair;
Seed randomSeed = Seed.ed25519Seed(); // To generate a random secp256k1 Seed, use Seed.secp256k1Seed()
KeyPair keyPair = randomSeed.deriveKeyPair();
Address = keyPair.publicKey().deriveAddress();
Instead of restoring a wallet from a Base58 encoded seed String
, developers can now restore Seed
s of various types
and derive a KeyPair
and Address
from the Seed
.
import org.xrpl.xrpl4j.crypto.keys.Seed;
import org.xrpl.xrpl4j.crypto.keys.Entropy;
import org.xrpl.xrpl4j.crypto.keys.Passphrase;
// From new, random entropy
Seed seedFromRandomEntropy = Seed.ed25519SeedFromEntropy(Entropy.newInstance));
// From existing entropy bytes
Seed seedFromEntropy = Seed.ed25519SeedFromEntropy(BaseEncoding.base16().decode("0102030405060708090A0B0C0D0E0F10"))
// From existing passphrase
Seed seedFromPassphrase = Seed.ed25519SeedFromPassphrase(Passphrase.of("Hello World"));
// From existing secret
Seed seedFromSecret = Seed.fromBase58EncodedSecret(Base58EncodedSecret.of("snoPBrXtMeMyMHUVTgbuqAfg1SUTb"));
All classes in the org.xrpl.xrpl4j.keypairs
package have been removed. org.xrpl.xrpl4j.keypairs.KeyPair
has been replaced by org.xrpl.xrpl4j.crypto.keys.KeyPair
, and all other classes in the keypairs
package do not
have a direct replacement. Instead, the functionality contained in these classes is available in
org.xrpl.xrpl4j.crypto
through the Seed
, KeyPair
, and SignatureService
interfaces.
The primary interface in the keypairs
package was KeyPairService
. The following list describes how to migrate
from each method in KeyPairService
:
- Instead of
KeyPairService.generateSeed()
, useSeed.ed25519Seed()
orSeed.secp256k1Seed()
- Instead of
KeyPairService.generateSeed(UnsignedByteArray entropy)
, useSeed.ed25519SeedFromEntropy(Entropy.of(byteArray))
- Instead of
KeyPairService.deriveKeyPair(String seed)
, useSeed.fromfromBase58EncodedSecret(Base58EncodedSecret.of(secret)).deriveKeyPair()
- Instead of
KeyPairService.sign(UnsignedByteArray message, String privateKey)
orKeyPairService.sign(String message, String privateKey)
, useBcSignatureService.sign(PrivateKey privateKey, T transaction)
- Instead of
KeyPairService.verify(UnsignedByteArray message, String signature, String publicKey)
orKeyPairService.verify(String message, String signature, String publicKey)
, useBcSignatureService.verify(Signer signatureWithPublicKey, T transaction)
- Instead of
KeyPairService.deriveAddress(String publicKey)
orKeyPairService.deriveAddress(UnsignedByteAray publicKey)
, usePublicKey.deriveAddress()
All cryptography operations have been moved to the xrpl4j-core
artifact and a majority of the classes
found in xrpl4j-crypto-core
and xrpl4j-crypto-bouncycastle
have been replaced or rewritten. The following
section describes how to achieve the same functionality in v3.0.0 as was available in v2.5.1.
BcKeyUtils
has been moved from org.xrpl.xrpl4j.crypto
to org.xrpl.xrpl4j.crypto.bc.keys
.
org.xrpl.xrpl4j.crypto.Seed
, org.xrpl.xrpl4j.crypto.PrivateKey
, and org.xrpl4j.crypto.PublicKey
have been
replaced by org.xrpl.xrpl4j.crypto.keys.Seed
, org.xrpl.xrpl4j.crypto.keys.PrivateKey
, and
org.xrpl4j.xrpl4j.crypto.keys.PublicKey
respectively. All seed/private key generation and restoration, as well as
public key and address derivation functionality is now available in these classes. The following example shows
how to generate a new random ED25519 Seed
, derive a KeyPair
from the Seed
, and derive an Address
from the
derived PublicKey
in v3.0.0:
Seed seed = Seed.ed25519Seed();
KeyPair keyPair = seed.deriveKeyPair();
PublicKey publicKey = keyPair.publicKey();
PrivateKey privateKey = keyPair.privateKey();
Address = publicKey.deriveAddress();
KeyMetadata
has been removed altogether. Instead, all private keys are now represented by extensions of
org.xrpl.xrpl4j.crypto.keys.PrivateKeyable
. PrivateKeyable
has two child implementations/extensions: PrivateKey
and PrivateKeyReference
. PrivateKey
represents a private key held in memory in the same runtime. This variant could
be useful in the context of an android or native application, but should be avoided in server-side applications as
holding private keys in-memory poses a large security threat to applications.
PrivateKeyReference
on the other hand is, as the name suggests, a reference to a private key that is held in another
system. For example, keys held in an HSM or other custody service can be referenced by a PrivateKeyReference
.
Different custody systems require different identifying information of private keys. Therefore, developers will likely
need to extend or implement PrivateKeyReference
for each custody provider they use. In turn, developers must
implement SignatureService<MyPrivateKeyReference>
to interact with any given custody service, although
AbstracSignatureService
can be extended to reduce a large portion of this effort.
The main interface used to sign and verify transactions in version 2 was
org.xrpl.xrpl4j.crypto.signing.SignatureService
. In version 3, SignatureService
has been completely rewritten,
though it remains in the same package.
The version 3 SignatureService
now contains a generic type extending PrivateKeyable
. Developers
can now implement the same interface (SignatureService
) for both in-memory PrivateKey
s and private keys managed
by external services (referenced by PrivateKeyReference
). This was possible in version 2, but the interface was
clunky and unintuitive for in-memory private keys, ie calls to SignatureService.sign
required passing in
KeyMetadata.EMPTY
for all in-memory private keys.
The new SignatureService
interface has two implementations: org.xrpl.xrpl4j.crypto.signing.bc.BcSignatureService<PrivateKey>
and org.xrpl.xrpl4j.crypto.signing.bc.BcDerivedKeySignatureService<PrivateKeyReference>
. In version 2, the
analogous classes were org.xrpl.xrpl4j.crypto.signing.SingleKeySignatureService
and
org.xrpl.xrpl4j.crypto.signing.DerivedKeySignatureService
, respectively. However, BcSignatureService
can now
be used as a singleton and sign transactions for any number of PrivateKey
s, unlike SingleKeySignatureService
which
held a singular PrivateKey
.
v3.0.0 introduces many changes to the objects previously found in the xrpl4j-model
dependency. While most of the
changes involved removing previously deprecated fields and methods, some changes were not deprecated in v2.5.1.
Transaction.computeMultiSigFee
has been removed in favor ofFeeUtils.computeMultisigNetworkFees(FeeResult, SignerListObject)
Transaction.closeDate()
has been removed in favor ofTransactionResult.closeDate()
as this field is only present in responses to RPC calls.- Similarly,
Transaction.closeDateHuman()
has been removed in favor ofTransactionResult.closeDateHuman()
. Transaction.hash()
has been removed in favor ofAccountTransactionsTransactionsTransaction.hash()
which are present inAccountTransactionResult.transactions()
.Transaction.ledgerIndex()
has been removed in favor ofAccountTransactionsTransactionsTransaction.ledgerIndex()
which are present inAccountTransactionResult.transactions()
.AccountTransactionsResult.ledgerIndexMin()
andAccountTransactionsResult.ledgerIndexMax
have been removed in favor ofAccountTransactionsResult.ledgerIndexMinimum()
andAccountTransactionsResult.ledgerIndexMaximum()
respectivelyAccountTransactionsTransactionResult.transaction()
has been removed in favor ofAccountTransactionsTransactionResult.resultTransaction()
. The transaction's hash and ledgerIndex can be found inresultTransaction().hash()
andresultTransaction().ledgerIndex()
, respectively.AccountTransactionsRequestParams.builder()
has been renamed toAccountTransactionsRequestParams.unboundedBuilder()
AccountTransactionsRequestParams.ledgerIndexMin()
has been removed in favor ofAccountTransactionsRequestParams.ledgerIndexMinimum()
AccountTransactionsRequestParams.ledgerIndexMax()
has been removed in favor ofAccountTransactionsRequestParams.ledgerIndexMaximum()
- The
LedgerIndex(String value)
constructor,LedgerIndex.of(String value)
, andLedgerIndex.of(UnsignedLong value)
have been removed from the public API.LedgerIndex
es should only be constructed via theLedgerIndex.of(UnsignedInteger value)
static constructor. LedgerIndex.CURRENT
,LedgerIndex.CLOSED
, andLedgerIndex.VALIDATED
have been removed. Ledger index shortcut values can be specified via theLedgerSpecifier
class.LedgerIndex.unsignedLongValue()
andLedgerIndex.value()
have been removed. To get the underlying value of theLedgerIndex
, useLedgerIndex.unsignedIntegerValue()
LedgerIndex.plus(UnsignedLong other)
has been removed. Only theUnsignedInteger
variant is still supported.SubmitMultiSignedResult.result()
has been removed in favor ofSubmitMultiSignedResult.engineResult()
whose type has changed fromOptional<String>
toString
SubmitMultiSignedResult.resultCode()
has been removed in favor ofSubmitMultiSignedResult.engineResultCode()
whose type has changed fromOptional<Integer>
toInteger
SubmitMultiSignedResult.resultMessage()
has been removed in favor ofSubmitMultiSignedResult.engineResultMessage()
whose type has changed fromOptional<String>
toString
SubmitResult.result()
has been removed in favor ofSubmitResult.engineResult()
whose type has changed fromOptional<String>
toString
SubmitResult.resultCode()
has been removed in favor ofSubmitResult.engineResultCode()
whose type has changed fromOptional<Integer>
toInteger
VersionType
has been renamed toKeyType
Transaction.publicKey()
is now typed as aPublicKey
instead of anOptional<String>
The following classes' .ledgerHash()
and .ledgerIndex()
methods have been removed in favor of .ledgerSpecifier()
:
AccountChannelsRequestParams
AccountCurrenciesRequestParams
AccountInfoRequestParams
AccountLinesRequestParams
AccountObjectsRequestParams
AccountOffersRequestParams
AccountTransactionsRequestParams
LedgerRequestParams
RipplePathFindRequestParams
Additionally, .ledgerSpecifier()
no longer defaults to LedgerSpecifier.CURRENT
, so developers must explicitly
set LedgerSpecifier
in each of the classes above.
The following classes .ledgerIndex()
and .ledgerHash()
methods have been changed from @Nullable
to Optional
AccountChannelsResult
AccountCurrenciesResult
Some methods have been removed from XrplClient
.
XrplClient.submit(Wallet wallet, T unsignedTransaction)
,
XrplClient.submit(org.xrpl.xrpl4j.crypto.signing.SignedTransaction)
, and
XrplClient.submit(org.xrpl.xrpl4j.model.client.transactions.SignedTransaction)
have been removed in favor of
XrplClient.submit(SingleSignedTransaction signedTransaction)
.
To create a SingleSignedTransaction
, use BcSignatureService
like this:
KeyPair keyPair = Seed.ed25519Seed().deriveKeyPair();
BcSignatureService signatureService = new BcSignatureService();
SingleSignedTransaction<Transaction> signedTransaction = signatureService.sign(keyPair.privateKey(), transaction);
xrplClient.submit(signedTransaction);
XrplClient.submitMultisigned(T transaction)
has been removed in favor of
XrplClient.submitMultisigned(MultiSignedTransaction<T> transaction)
.
To create a MultiSignedTransaction
, use BcSignatureService
like this:
Set<Signer> signers = Lists.newArrayList(aliceKeyPair, bobKeyPair).stream()
.map(keyPair -> signatureService.multiSignToSigner(keyPair.privateKey(), unsignedPayment))
.collect(Collectors.toSet());
/////////////////////////////
// Then we add the signatures to the Payment object and submit it
MultiSignedTransaction<Payment> multiSigPayment = MultiSignedTransaction.<Payment>builder()
.unsignedTransaction(unsignedPayment)
.signerSet(signers)
.build();
SubmitMultiSignedResult<Payment> paymentResult = xrplClient.submitMultisigned(multiSigPayment);
For a more complete example, see SubmitMultiSignedIT
.
XrplClient.signTransaction(Wallet wallet, T unsignedTransaction)
has also been removed. A SignatureService
should be used instead to sign transactions.
XrplClient.serverInfo()
has been removed in favor of XrplClient.serverInformation()
. XrplClient.serverInformation()
returns an org.xrpo.xrpl4j.model.client.serverinfo.ServerInfoResult
, which could contain one of
RippledServerInfo
, ReportingModeServerInfo
, or ClioServerInfo
depending on which type of XRPL server was
queried.