-
Notifications
You must be signed in to change notification settings - Fork 86
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
[Fix #710] Use network_id to identify faucet_url #715
base: main
Are you sure you want to change the base?
Conversation
- move the utility function _get_network_id_and_build_version into client.py file for convinience
xrpl/asyncio/clients/client.py
Outdated
@@ -51,3 +54,24 @@ async def _request_impl( | |||
:meta private: | |||
""" | |||
pass | |||
|
|||
|
|||
async def _get_network_id_and_build_version(client: Client) -> None: |
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 not automatically run this on every client upon instantiation, instead of having it be a helper function? Then it only needs to be run once, instead of every time a function that uses this is called.
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 are not duplicating invocations of this function. Here are two examples where the network_id
information persists in the client object.
But I agree, this could be done in a cleaner way.
I can only invoke _get_network_id_and_build_version
function after a client has opened the socket-connection. So, I'll need to invoke this in this open()
method of all the child classes of Client
let me try it out
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'm open to the option of doing it lazily - i.e. only if and as needed, but only once. All that would require is checking if the network ID has been instantiated before running the request.
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.
okay, I've added a check: 23d3eb3
xrpl/asyncio/transaction/main.py
Outdated
import math | ||
from typing import Any, Dict, Optional, cast | ||
|
||
from typing_extensions import Final | ||
|
||
from xrpl.asyncio.account import get_next_valid_seq_number | ||
from xrpl.asyncio.clients import Client, XRPLRequestFailureException | ||
from xrpl.asyncio.clients.client import _get_network_id_and_build_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.
Any function that gets imported elsewhere shouldn't start with a _
.
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 ab918dc
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
elif network_id < 0: | ||
raise XRPLFaucetException("network_id cannot be negative.") |
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.
Does rippled even allow this scenario?
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 config file does not allow negative numbers as input for network_id. But it accepts really large numbers (for eg: 4294967295
which could be negative numbers, if typecast into smaller signed-types)
also, rippled unit tests allow negative numbers - XRPLF/rippled@develop...ckeshava:rippled:negNetworkID
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 don't think xrpl-py needs any specific checks for this, "we don't understand this network ID" is fine.
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.
updated in f06e5c1
raise XRPLFaucetException( | ||
"Cannot fund an account with a client that is not on the testnet or devnet." | ||
"Cannot create faucet URL without network_id or the faucet_host information." | ||
) |
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.
Thoughts on throwing this error in the main generate_faucet_wallet
function instead of here? e.g.
if network_id is None and faucet_host is None:
raise XRPLFaucetException(...)
Otherwise, this error currently executes on an unknown devnet as well, which may have 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.
I don't object to that idea, but how is that different from the current implementation?
At line 189 (the last line of the get_faucet_url
method), we have established that faucet_host == None
. You are correct, an unknown devnet might have a networkID, but how can I determine the host_url from a networkID (say 1345
?)
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.
if network_id is None and faucet_host is None: raise XRPLFaucetException(...)
The said devnet will have a networkID, hence this condition needs to be:
if faucet_host is None and networkID >= 1025:
raise XRPLFaucetException(...)
The current implementation is equivalent to the above if-condition
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 difference comes from typing and failing fast. IMO it makes more sense for get_faucet_url
to not accept None
as a valid network ID.
You can't determine the host URL from an unknown Devnet, but the error message should be different.
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 cannot expect all networks to have a valid NetworkID
isn't it?
If we force get_faucet_url
to accept valid networkIDs only, then some of the processing logic shifts into generate_faucet_wallet
method.
def get_faucet_url(network_id: int) -> str:
if network_id == 1:
return _TEST_FAUCET_URL
elif network_id == 2:
return _DEV_FAUCET_URL
elif network_id == 0:
raise XRPLFaucetException("Cannot create faucet with a client on mainnet.")
elif network_id < 0:
raise XRPLFaucetException("network_id cannot be negative.")
# unreachable code
return ""
async def generate_faucet_wallet(
client: Client,
wallet: Optional[Wallet] = None,
debug: bool = False,
faucet_host: Optional[str] = None,
usage_context: Optional[str] = None,
user_agent: Optional[str] = "xrpl-py",
) -> Wallet:
if not client.network_id:
await get_network_id_and_build_version(client)
if client.network_id is None and faucet_host is None:
raise XRPLFaucetException(
"Cannot create faucet URL without network_id or the faucet_host information"
)
if faucet_host is not None:
faucet_url = process_faucet_host_url(faucet_host)
else:
faucet_url = get_faucet_url(client.network_id)
# remaining code in the function ...
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.
That flow makes more sense to me, personally.
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.
alrighty
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.
updated sometime before f06e5c1
if faucet_host is not None: | ||
return process_faucet_host_url(faucet_host) |
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.
Upon further thought, I think it might make more sense to bring this code out of this function and have get_faucet_url
be entirely based on the 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.
yeah, I put down a snippet in a comment below
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.
updated somewhere prior to f06e5c1
self.assertEqual(get_faucet_url(json_client_url, custom_host), expected_faucet) | ||
self.assertEqual(get_faucet_url(ws_client_url, custom_host), expected_faucet) | ||
|
||
def test_get_faucet_wallet_test(self): |
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.
these test cases are already covered in the below class TestProcessFaucetHostURL
raise XRPLFaucetException("Unable to parse the specified network_id.") | ||
|
||
# this line is unreachable. Custom devnets must specify a faucet_host input | ||
return "" |
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 should raise an error here.
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 f06e5c1
if "sidechain-net2" in url: # sidechain issuing chain devnet | ||
raise XRPLFaucetException( | ||
"Cannot fund an account on an issuing chain. Accounts must be created via " | ||
"the bridge." | ||
) |
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 piece still needs to be included. The network ID is 262.
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.
thanks. fixed in f06e5c1
return process_faucet_host_url(faucet_host) | ||
if "altnet" in url or "testnet" in url: # testnet | ||
if network_id == 1: |
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.
Can this if-else be replaced with a dictionary? It'll be easier to maintain that way.
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.
updated in f06e5c1
if "altnet" in url or "testnet" in url: # testnet | ||
return _TEST_FAUCET_URL | ||
if "sidechain-net2" in url: # sidechain issuing chain devnet | ||
map_network_id_to_url: Dict[int, str] = {1: _TEST_FAUCET_URL, 2: _DEV_FAUCET_URL} |
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 object should be outside of the function, since it's not dependent on the data inside. And the name should be in uppercase.
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
Co-authored-by: Mayukha Vadari <mvadari@gmail.com>
@@ -17,6 +17,7 @@ | |||
_DEV_FAUCET_URL: Final[str] = "https://faucet.devnet.rippletest.net/accounts" | |||
|
|||
_TIMEOUT_SECONDS: Final[int] = 40 | |||
_MAP_NETWORK_ID_TO_URL: Dict[int, str] = {1: _TEST_FAUCET_URL, 2: _DEV_FAUCET_URL} |
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:
_MAP_NETWORK_ID_TO_URL: Dict[int, str] = {1: _TEST_FAUCET_URL, 2: _DEV_FAUCET_URL} | |
_NETWORK_ID_URL_MAP: Dict[int, str] = {1: _TEST_FAUCET_URL, 2: _DEV_FAUCET_URL} |
High Level Overview of Change
Context of Change
Type of Change
Did you update CHANGELOG.md?
This change should not modify the experience for external developers
Test Plan
Tests have been modified to accomodate the new API for grabbing the faucet_url