-
Notifications
You must be signed in to change notification settings - Fork 83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add rippled API v2 support and use as default #720
base: v3.0
Are you sure you want to change the base?
Conversation
* add nfts_by_issuer * update Changelog * added nfts_by_issuer to Request's get_method * reformat changelog and add required comment for nfts_by_issuer.py --------- Co-authored-by: Kassaking <kassaking7@gmail.com>
* BaseModel.from_xrpl method should not accept snake_case keys in dictionary input * Fix integration test: Update regex to accomodate Amount2 AMM field --------- Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
use the kw_only=True parameter in the dataclass module. Ensure backwards compatibility for older versions of Python, this feature is enabled in Python v3.10 or later versions --------- Co-authored-by: Jackson Mills <jmills@ripple.com> Co-authored-by: Mayukha Vadari <mvadari@ripple.com>
…st rippled validator
@@ -62,7 +63,16 @@ def from_dict(cls: Type[GenericRequest], value: Dict[str, Any]) -> GenericReques | |||
|
|||
elif "method" in value: # JSON RPC formatting | |||
if "params" in value: # actual JSON RPC formatting | |||
value = {"method": value["method"], **value["params"]} | |||
if "api_version" in value: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does the API version need to be specified in generic requests specifically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Certain requests like tx_history
are implemented through GenericRequest
. But this request ahs been deprecated since api version 2. This PR intends to make API v2 as the default response in xrpl-py.
An api_version < 2
needs to be specified for certain generic-requests, otherwise they fail with an invalid_API_version
error.
Look at test_generic_request
for an example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems fine to leave that as existing behavior then - default to v2. For example, GenericRequest
is also used for ledger_accept
, which doesn't differ between V1 and V2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but api_version: 2
is specified in all requests, by default (including ledger_accept
).
Without this change, tx_history
requests are transmitted with api_version: 2
and they fail. Since we need to support API v1, how do you propose to handle tx_history
requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should error if api_version
isn't included, since the default is 2
. If api_version: 1
is included, it will work. I assume that's what would still happen.
Note: we don't have to specifically support tx_history
, that was just something to use for the test since the RPC doesn't have a model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need the api_version
if check for that. I tried running just this code in the test and it worked:
if "params" in value: # actual JSON RPC formatting
value = {
"api_version": value["api_version"],
"method": value["method"],
**value["params"],
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if a user submits a raw JSON input, but forgets to specify the api_version
?
Since the user is not using the GenericRequest/Request
class, the api_version
field will need to be specified manually
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user can't submit raw JSON input in xrpl-py, you have to go through a model.
Even if you could, it would then default to whatever the rippled instance has as default (probably v1).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a test case at the end of this file: tests/integration/reqs/test_generic_request.py
Users can submit raw-JSON inputs through the from_dict
methods. This request does not reach rippled due to processing errors in the from_dict
function.
We will need to document that api_version
is a mandatory field, if raw-JSON input is provided. If GenericRequest
model is used, then the default api_version
is provided automatically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a mandatory field if a default option is provided. The same is true of any other API method - if you don't specify an api_version
field, you'll get the default version. We don't need to document anything specific for GenericRequest
that's different than any other request model.
xrpl/models/response.py
Outdated
from xrpl.models.base_model import BaseModel | ||
from xrpl.models.required import REQUIRED | ||
from xrpl.models.transactions import PaymentFlag | ||
from xrpl.models.transactions.types import TransactionType | ||
from xrpl.models.utils import KW_ONLY_DATACLASS, require_kwargs_on_init | ||
|
||
DEFAULT_API_VERSION: Final[int] = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this defined in this file, where it's not used, instead of request.py
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking for a global constants file, but I couldn't find it.
I've updated the location to requests.py file 👍
Type of Change should be set to "Breaking change" since response data has changed. Also can you change PR title to: "feat: add rippled API v2 support and use as default"? |
Co-authored-by: Omar Khan <khancodegt@gmail.com>
Co-authored-by: Omar Khan <khancodegt@gmail.com>
|
||
|
||
# TODO: move to test_transaction and use the standard integration test setup | ||
class TestNetworkID(TestCase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this file removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved this test into test_transaction.py
file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're no longer testing both scenarios (network ID < 1024 vs network ID >= 1024), then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the cases where network_ID <= 1024
, we don't need to populate network_id
field inside transactions.
Hence, we don't need to test this function for those networks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will error if NetworkID
is specified, in those cases. So that scenario does still need to be tested.
This PR should be merged into a different branch, called something like |
CHANGELOG.md
Outdated
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
|
|||
### Added | |||
- Add support for the DeliverMax field in Payment transactions | |||
- Use rippled API v2 as default in requests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be at the top (or highlighted some how) since this is a major change. Other than that, LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be in a BREAKING CHANGE
section.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 4179077
.ci-config/rippled.cfg
Outdated
@@ -105,6 +105,10 @@ validators.txt | |||
# Note: The version of rippled you use this config with must have an implementation for the amendments you attempt to enable or it will crash. | |||
# If you need the version of rippled to be more up to date, you may need to make a comment on this repo: https://github.com/WietseWind/docker-rippled | |||
|
|||
# network_id is required otherwise it's read as None | |||
[network_id] | |||
63456 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a network ID?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is related to the integration test: test_autofill_populate_networkid
. Originally, this test was using the hooks-testnet for sending transactions. But it was decided that client libraries are not supporting (or) using hooks test-nets.
The docker container for the integration test uses this config file for startup.
The autofill method's control flow is contingent on network_id > 1025
for this particular test.
This change is not directly related to the API v2 updates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it was decided that client libraries are not supporting (or) using hooks test-nets.
We can still use it for a test.
This change is not directly related to the API v2 updates
Why is this change included in this PR, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i believe the integration tests are better off without the dependency on hooks-test-network -- this particular function can be tested without making network calls to the hooks-network
I can remove this change from this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll be easier if that discussion can happen separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have reverted the changes to the main
branch. But it appears that the hooks testnet is using rippledv1.10
: https://github.com/XRPL-Labs/xrpld-hooks/blob/b13e7db18d1376d40cdbeeea849702b568324279/src/ripple/protocol/impl/BuildInfo.cpp#L36
Here is the Request and Response from hooks testnet validator
# request
ServerInfo(method=<RequestMethod.SERVER_INFO: 'server_info'>, id=None, api_version=2)
# response
Response(status=<ResponseStatus.ERROR: 'error'>, result={'api_version': 2, 'error': 'invalid_API_version', 'id': 'RequestMethod.SERVER_INFO_174181', 'request': {'api_version': 2, 'command': 'server_info', 'id': 'RequestMethod.SERVER_INFO_174181'}, 'status': 'error', 'type': 'response'}, id='RequestMethod.SERVER_INFO_174181', type=<ResponseType.RESPONSE: 'response'>)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to find a fix tomorrow
snippets/multisign.py
Outdated
@@ -57,10 +58,10 @@ | |||
if multisigned_tx_response.result["validated"]: | |||
print("The multisigned transaction was accepted by the ledger:") | |||
print(multisigned_tx_response) | |||
if multisigned_tx_response.result["Signers"]: | |||
if multisigned_tx_response.result["tx_json"]["Signers"]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this would be easier to read with a helper variable for multisigned_tx_response.result["tx_json"]["Signers"]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 4179077
xrpl/models/requests/request.py
Outdated
|
||
import xrpl.models.requests # bare import to get around circular dependency | ||
from xrpl.models.base_model import BaseModel | ||
from xrpl.models.exceptions import XRPLModelException | ||
from xrpl.models.required import REQUIRED | ||
from xrpl.models.utils import KW_ONLY_DATACLASS, require_kwargs_on_init | ||
|
||
DEFAULT_API_VERSION: Final[int] = 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DEFAULT_API_VERSION: Final[int] = 2 | |
_DEFAULT_API_VERSION: Final[int] = 2 |
It's a helper variable that's only used here (other than in tests).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 4179077
xrpl/models/requests/request.py
Outdated
@@ -106,6 +108,13 @@ class Request(BaseModel): | |||
|
|||
id: Optional[Union[str, int]] = None | |||
|
|||
api_version: int = DEFAULT_API_VERSION |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be an additional test for another request that makes sure that the api_version
field is handled properly - perhaps account_info
since there is a significant difference in the shape of the output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what exactly do you want to test about the api_version
field?
Is this what you had in mind, something like test_populate_api_version_field
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be an integration test that ensures that including an api_version
param in a request type that is not GenericRequest
still works correctly and properly returns the correct API version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't a unit test suffice?
It is rippled's responsibility to return the correct api_version
response, why should the client libraries test the response?
Even in the case of GenericRequest
, I'm only forwarding the api_version
input specified by the user. The integration test pertaining to tx_history
tests the older versions of rippled. I have not tested the validity of responses of rippled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't a unit test suffice?
In this case, I'd like to ensure that it matches rippled compatibility, so an integration test is needed.
It is rippled's responsibility to return the correct
api_version
response, why should the client libraries test the response?
I'm not suggesting a test that actually fully tests the rippled response, but a test that ensures that when I put in api_version: 1
in my request model, it actually gives me the rippled API v1 response and not the rippled API v2 response (in which case there's something wrong with the implementation of api_version
in the xrpl-py model). I'm not sure if there's a field that returns the API version of the response (EDIT: there only appears to be one if the api_version
is specified, which IMO is not sufficient), but if there is, just checking that would also be sufficient.
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
High Level Overview of Change
All the requests are updated to use the newer rippled v2 API responses
Type of Change
Did you update CHANGELOG.md?
Test Plan
Existing integration tests have been modified to use the newer API version responses.