xrplf / xrpl4j Goto Github PK
View Code? Open in Web Editor NEWA 100% Java implementation to interact with the XRP Ledger.
License: ISC License
A 100% Java implementation to interact with the XRP Ledger.
License: ISC License
Many of the model objects in xrpl4j-model were written originally in xrpl4j-client and were not tested. Since these objects will now be supported in the library, we should write JSON tests to ensure the request/response and ledger objects are being serialized and deserialized correctly
Currently we only support generating keypairs/wallets from a family seed. We should add support for deriving key pairs from eight 6 digit numbers, as described in this proposal.
We should add the metadata
field to TransactionResult
in case anyone needs it
While most of the methods in XrplClient
follow the rippled API, meaning they take a set of XrplRequestParams
and return an XrplResult
, some methods (such as submit
) are more abstract. We should consider reducing the complexity of the client by simply mirroring the rippled API. Also, we should go through and implement the rest of the rippled public API methods that are available.
For each of the examples in https://xrpl.org/manage-account-settings.html, we need to provide Java samples.
Also see XRPLF/xrpl-dev-portal#1018 @ryangyoung
The ledgerHash
and ledgerIndex
fields are not Optional
in LedgerResult
, nor are closeTimeHuman
and parentCloseTime
in LeaderHeader
. These fields are always present in responses to requests for validated
ledgers, but are absent when asking for the current
ledger.
We should probably go ahead and make the breaking change of making these Optional
LedgerIndex
is just a wrapper around String
. There are three defined character String
s that are recognized by rippled as shortcuts: "validated"
, "current"
, and "closed"
. All other ledger indexes must be a numerical String
like "12345"
.
Currently, we don't do any client side validation that the String
wrapped by LedgerIndex
is either one of the shortcut Strings or a number, so a user could technically construct a LedgerIndex
wrapping "foo"
. While this will ultimately be caught by rippled, we should add validation in the LedgerIndex
class to short circuit any errors.
We need to add a NegativeUnlObject
Immutables declaration to xrpl4j-model/src/main/java/model/ledger.
See https://xrpl.org/negativeunl.html for reference
The BaseEncoder
for HEX values doesn't like lower-cased values. We should normalize the output of UnsignedByteArray.hexValue
to always be upper-case.
We should type all X-Address fields with a String
wrapper type
We need to add an AmendmentsObject
Immutables declaration to xrpl4j-model/src/main/java/model/ledger.
See https://xrpl.org/amendments-object.html for reference
There are some rippled API methods whose request/response objects are not included in our model library. As we get requests for more supported methods, we can create individual issues for each method.
There are unit tests for AccountSetFlags
and PaymentFlags
, but we should write similar tests for all other descendants of Flags
.
There are a lot of missing javadocs and missing elements of certain javadocs. We should go through and improve these javadocs and make sure the maven-javadoc-plugin does not spit out any warnings
Add support for deposit_authorized method in XrplClient.java
.
Currently, WalletFactory.fromSeed
accepts a String
, but this value is ambiguous if a developer isn't looking closely at the Javadoc (e.g., the following are all valid seed constructions, several of which could be represented as a String
).
We should enable CodeCoverage monitoring as part of the build. See https://codecov.io/gh/hyperledger/quilt for e.g., or some other tool.
A lot of the request/response objects have a field called marker
, which is a server defined field that can either be a String
or a JSON object. Currently, our objects are typed as Optional<String>
, which will break Jackson when the server sends back a JSON object in that field.
We should create a Marker
type with a custom serializer/deserializer to handle this.
Currently, if someone opens a PR from a forked version of xrpl4j, we have to assign the PR to someone in order for GH Actions to get triggered. This is fine for now, but if new commits get added to the PR, we have to re-assign the PR to someone else, which is a pain.
I'm using xrpl4j to generate xrp wallet as part of a HD wallet. I am able to generate the wallet fine when the seed size is 16 bytes (128 bits / 12 word mnemonic) but when the seed size is 32 (256 bits / 24 word mnemonic) it fails. The current workaround I have is to strip the seed of the bytes in excess of 16.
See HD wallet generation using bitcoin4j code here.
new DeterministicSeed(
new SecureRandom(),
256,
Optional.ofNullable(passphrase).orElse("")
);
See stripping of bytes in excess of 16 workaround here.
ArrayUtils.subarray(privKey.toByteArray(), 0, 16);
While this is functional, it strips the entropy and is restrictively less secure.
Requirement:
As this library was ported from ripple JS libraries, we should check this library against the following two bugs:
The tfFullyCanonicalSig
transaction flag was recently deprecated, and no new transactions submitted without this flag will be accepted. Currently, we do allow users to set tfFullyCanonicalSig
to false
for transactions which have custom flags, so we should always set tfFullyCanonicalSig
to true
. This can be done by removing the tfFullyCanonicalSig(boolean)
method from every TransactionFlags
Builder
and always setting it to true
.
See Transaction result codes here. It would be useful to have these defined in constants so projects using this library don't accidentally introduce typos.
E.g.:
String TES = "tes";
String TES_SUCCESS = TES + "SUCCESS";
Currently in LedgerResult
, there is no sub object modeling the queue_data
field that gets returned in responses. We should add this field if anyone requests it
This method is deprecated and should not be used. We should use SignatureUtils instead.
The method ledgerIndex()
in Transaction.java
is only ever present in response to a account_tx
call, and even then only sometimes.
So, we can create a new wrapper class called AccountTransactionsTransaction
and inside of AccountTransactionsTransactionResult
we can update the transaction()
method to be as follows:
/**
* The {@link Transaction}.
*
* @return A {@link T} with the transaction fields.
*/
@JsonProperty("tx")
AccountTransactionsTransaction<T> transaction();
If AccountTransactionsTransaction
has ledgerIndex()
then everything should just work during deserialization, but from a developer perspective, the ledgerIndex()
will be present in the correct circumstances.
Instead of using UnsignedLongs
to denote XRPL timestamps, we should just have a type that wraps UnsignedLong
that also has utility constructors for Instant
s and other Java time API primitives
@nhartner can you publish your branch that has Hooks transaction support?
We need to add an FeeSettingsObject
Immutables declaration to xrpl4j-model/src/main/java/model/ledger.
See https://xrpl.org/feesettings.html for reference
Hi, I run into an issue when running a project with embedded tomcat in jar with Java 11.
It causes the following Exception:
Caused by: java.lang.IllegalArgumentException: resource definitions.json not found. at com.google.common.base.Preconditions.checkArgument(Preconditions.java:217) at com.google.common.io.Resources.getResource(Resources.java:195) at org.xrpl.xrpl4j.codec.binary.definitions.DefaultDefinitionsProvider.lambda$new$0(DefaultDefinitionsProvider.java:26)
And is coming from DefaultDefinitionProvider.java:26. The definitions.json file is in the jar, just the classLoader won't resolve it.
Hey guys
Really nice work on this library
Few small things:
org.xrplf.*
not com.ripple.*
We need to add a LedgerHashes
Immutables declaration to xrpl4j-model/src/main/java/model/ledger.
See https://xrpl.org/ledgerhashes.html for reference
Hash256
can use equalsIgnoreCase
since its value is HEX. It also doesn't override the hashcode to conform with equals computation.
This is an edge-case, but see https://github.com/ripple/ripple-binary-codec/pull/121/files
XrplClient.ledger(params)
method throws an exception if transactions are returned because the LedgerHeader.transactions()
declaration tries to deserialize them as String
instead of JSON.
The transactions that are returned can either be full JSON transaction objects, or the identifying hashes of the transactions. We could add a custom deserializer, but this kind of polymorphism isn't easy to do in Java, so I think we should just be opinionated and force the request to set expand=true
when asking for transactions
When we initially wrote xrpl4j-keypairs, we decided to skip over implementing HD Wallet support. For the sake of having a full feature set, we should add support for HD wallet generation
The keyMetadataLoadingCache
in DerivedKeysSignatureService
should be configurable via an overloaded constructor parameter.
Instead of using UnsignedLongs
to denote XRPL timestamps, we should just have a type that wraps UnsignedLong
that also has utility constructors for Instant
s and other Java time API primitives
Per XRPLF/xrpl.js#1401, "When using a rippled server in Reporting Mode, the server_info response does not have a load_factor property."
Currently, XRPL-4j uses an optional field for LoadFactor inside of Serverinfo.java
, but I think we can make this non-optional with an @Default
value of 1
.
There is a unit test called XrpCurrencyAmountTest.java
(introduced as part of #68) but it doesn't cover the math in XrpCurrencyAmount.
I think Transaction.signers()
inadvertently got deprecated when we added SignatureService
. This is a standard transaction field and should not be deprecated.
The way amounts are mapped could be more convenient to use. In most cases, people just want to get the amount in XRP as a decimal, not drops. But on things like payments, that requires doing an instanceof
then a cast to XrpCurrencyAmount
then no obvious way to get the decimal value (instead of drops) from there
I started getting Exceptions from serverInfo() method when connected to s2.ripple.com. I realized the library expects load_factor to be UnsignedInteger (and it usually is "1"), but rippled sometimes returns it as double.
It can be shown here: https://xrpl.org/websocket-api-tool.html?server=wss%3A%2F%2Fs1.ripple.com%2F&req=%7B%22id%22%3A1%2C%22command%22%3A%22server_info%22%7D
clicking send several times eventually get you response with some higher load like:
{
"id": 1,
"result": {
"info": {
"build_version": "1.7.0",
"complete_ledgers": "61881385-62562429",
"hostid": "LARD",
"io_latency_ms": 2,
"jq_trans_overflow": "0",
"last_close": {
"converge_time_s": 3.002,
"proposers": 38
},
"load_factor": 511.83203125,
"load_factor_server": 1,
"peer_disconnects": "224008",
"peer_disconnects_resources": "747",
"peers": 261,
"pubkey_node": "n9MozjnGB3tpULewtTsVtuudg5JqYFyV3QFdAtVLzJaxHcBaxuXD",
"server_state": "full",
"server_state_duration_us": "2274468435925",
"state_accounting": {
"connected": {
"duration_us": "231197490",
"transitions": 2
},
"disconnected": {
"duration_us": "1156933",
"transitions": 2
},
"full": {
"duration_us": "2274468435925",
"transitions": 1
},
"syncing": {
"duration_us": "4065001",
"transitions": 1
},
"tracking": {
"duration_us": "63",
"transitions": 1
}
},
"time": "2021-Mar-30 15:37:51.486384 UTC",
"uptime": 2274704,
"validated_ledger": {
"age": 4,
"base_fee_xrp": 0.00001,
"hash": "E5A958048D98D4EFEEDD2BC3F36D23893BBC1D9354CB3E739068D2DFDE3D1AA3",
"reserve_base_xrp": 20,
"reserve_inc_xrp": 5,
"seq": 62562429
},
"validation_quorum": 31
}
},
"status": "success",
"type": "response"
}
The exception I am getting is clearly saying that jackson can't construct UnsignedInteger from 512.90234375
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.google.common.primitives.UnsignedInteger` (although at least one Creator exists): no double/Double-argument constructor/factory method to deserialize from Number value (512.90234375)
at [Source: (String)"{"info":{"build_version":"1.7.0","complete_ledgers":"32570-62562188","hostid":"CARR","io_latency_ms":1,"jq_trans_overflow":"2942","last_close":{"converge_time_s":3.005,"proposers":38},"load_factor":512.90234375,"load_factor_server":1,"peer_disconnects":"171040","peer_disconnects_resources":"4176","peers":214,"pubkey_node":"n9Kr6UDJAd2yUn9J6bXWpRvQcKRPAEVpeV33NJVBcaDSDVt2eho2","server_state":"full","server_state_duration_us":"172918538055","state_accounting":{"connected":{"duration_us":"471959630"[truncated 524 chars]; line: 1, column: 199] (through reference chain: org.xrpl.xrpl4j.model.client.server.ImmutableServerInfoResult$Json["info"]->org.xrpl.xrpl4j.model.client.server.ImmutableServerInfo$Json["load_factor"])
I suppose there fields like load_factor_local, load_factor_net and others may be the same case. I will try to investigate this to find the proper type later.
The LedgerIndex
class emits an UnsignedLong
via unsignedLongValue()
, but the Transaction
class uses an UnsignedInteger
to represent lastLedgerSequence
.
We should decide which Unsigned number type is best for representing numeric XRP Ledger index values, and be consistent across the library.
Currently, almost everything in the library is public
, when only a few classes are really needed in the public API that we expose. While it's nice to give users flexibility to use bits and pieces of the library, a large API increases the amount of code we need to make sure we don't break.
We should go through the different modules and figure out which classes we want to keep public and which we can make private
We need to add a DirectoryNodeObject
Immutables declaration to xrpl4j-model/src/main/java/model/ledger.
See https://xrpl.org/directorynode.html for reference
Anywhere there's an Optional
result, we should consider a sibling method that helps a developer not have to throw an exception as an alternative case.
Example, in AccountInfoResult.java
, we could add:
@JsonIgnore
default LedgerIndex ledgerIndexSafe() {
return ledgerIndex().orElseThrow(IllegalArgumentException::new);
}
If we embrace this pattern, we should add this to every client model object.
We should think more about where a link could go. Possibly as another section on this page: https://xrpl.org/references.html
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.