-
Notifications
You must be signed in to change notification settings - Fork 76
Fix network handling #303
Fix network handling #303
Conversation
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.
good patch. but i think the real solution is to centralize file writes to avoid this kind of bug. it's also a bit awkward that get_gateways
writes anywhere, we should either refactor or rename.
Agreed on centralizing file writes and with that, a refactor on |
if you think it's small enough, let's squeeze it here. otherwise the patch + tracking the issue is enough. |
On it! |
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 for the fix @andrew-fleming! Left some comments.
@@ -39,11 +43,7 @@ def get_gateways(): | |||
|
|||
except FileNotFoundError: | |||
with open(NODE_FILENAME, "w") as f: | |||
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.
In the try block above, gateway should be in plural.
Also, I think this is still not working for sending transactions if goerli2 is not in the node.json file, but the file exists. OTHER_NETWORKS are added just when the file is not found. Maybe return it in the try block as well?
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 we do this, I think it makes sense to remove writing the DEFAULT_NETWORKS to the node.json file at all, because it will be part of GATEWAYS always anyway.
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.
Good idea!
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 it makes sense to remove writing the DEFAULT_NETWORKS to the node.json file
It seems difficult to handle (at least, to cleanly handle) localhost
network calls when the node.json is not present with this approach^. I think we'd have to add conditionals to get_gateway_url
and get_feeder_url
in starknet_cli.py. Maybe there's a better way. If it's agreeable, I'd say let's make another issue to track that for the future.
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 to handle localhost
calls when node.json
is not present with this approach? The suggestion is to remove DEFAULT_NETWORKS
, which are goerli2
and integration
, which gateway_urls
won't probably change often. localhost
calls would still be going through node.json
. Sorry if I'm missing something.
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.
Forgive me, I did not provide enough context in my response.
The idea was to handle localhost
separately from DEFAULT_NETWORKS
through some sort of conditional. Otherwise, a node.json will be created (if it's not already) for txs querying the DEFAULT_NETWORKS
. This doesn't break anything; however, it's not ideal. This occurs because GATEWAYS.get()
returns None when a key does not exist instead of an error that we can handle.
I'm interested in the networks config idea.
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.
Got it.
My issue with the current PR state is that it is not addressing the real issue IMO, which is the UX using Nile. We can use a different approach than the one I suggested in this thread (mine is probably not the best for sure), but letting this as it is, I fear users will upgrade Nile, and they will struggle with sending transactions to goerli2 or integration. You and I both know how to fix it, but I feel the error they will receive is not well documented (and I think we could prevent the issue by default). Is the details what makes great tooling IMO (hardhat vs truffle).
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 need to give some sort of priority to UX issues like this because they harm adoption. Even if we have a lot of cool functionalities, if we do have not a solid UX, users won't use them IMO as a dev.
I'm of course ok with letting the solution like this if you guys think is enough.
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 my middle ground suggestion:
- let's not write any node.json. it's confusing pollution to the user, and it's information nile already knows. no more writing conflicts nor retrocompatibility issues.
- let's still read node.json. if there's any user custom network, let's add it (or overwrite any default). this is the stem for an actual nile config file, but retrocompatible and it buys us time to design properly, while fixing this.
thoughts?
src/nile/common.py
Outdated
"goerli2": "https://alpha4-2.starknet.io", | ||
"integration": "https://external.integration.starknet.io", | ||
} | ||
networks = {"localhost": "http://127.0.0.1:5050/", **OTHER_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.
If we add DEFAULT_GATEWAYS to queries even when the node.json exists:
networks = {"localhost": "http://127.0.0.1:5050/", **OTHER_NETWORKS} | |
networks = {"localhost": "http://127.0.0.1:5050/"} |
Co-authored-by: Eric Nordelo <[email protected]>
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.
@andrew-fleming The refactor looks good, but this PR is not solving the linked issue imo. Even when the error message differs from the last merges, the expected behavior, for me at least, is goerli2 transactions working by default (there are no docs telling users they need to add this manually to node.json afaik).
I think we have enough content with these different networks to add a nile.ini
(or different name) required config file with networks instead of deleting/creating a node.json
file.
Adding these networks by default to the ini file and documenting this would be a huge improvement to the UX IMO.
Interested in what you guys think about this two thoughts:
- Issue resolution that I think could be solved by returning the DEFAULT_GATEWAYS in the get_gateways method even when they are not in the node.json file.
- Replace node.json with nile.ini file with a networks config.
The patch does solve that^. The user doesn't have to add anything manually. The flow was that if a node.json exists, This PR now (since after that review) doesn't write the
The latest pushed changes follow If we want to go for |
This is assuming users would follow the flow, but my concern was also with upgrades, like what happened to me: Dev already have a nile project, already having a node.json file, they try to use goerli2, cryptic error not documented.
Totally agree. I think we should prioritize this as possible (not necessarily my proposed solution, but something to improve the network handling). cc @martriay |
src/nile/common.py
Outdated
|
||
|
||
def get_gateways(): | ||
"""Get the StarkNet node details.""" | ||
try: | ||
with open(NODE_FILENAME, "r") as f: | ||
gateway = json.load(f) | ||
return gateway | ||
|
||
gateways = {**gateway, **DEFAULT_GATEWAYS} |
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 happens if there's a conflicting goerli2
or integration
network? would it be overwritten by 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.
If there's a conflicting network, the DEFAULT_GATEWAYS
network would overwrite it in the local variable gateways
when the gateways dict is passed to the querying function. Thus, "goerli2": "new_url"
in node.json will return the goerli2 from DEFAULT_NETWORKS
I'll switch the order so that the node.json's gateway overwrites the DEFAULT_GATEWAYS
network of the same name
src/nile/common.py
Outdated
"""Create node.json and return gateways.""" | ||
with open(NODE_FILENAME, "w") as f: | ||
gateway = {network: gateway_url} | ||
f.write(json.dumps(gateway)) |
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.
no more indent=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.
The idea was to only have one gateway in node.json, but I'll add the indent back so it's formatted for users who want to add more networks
@@ -39,11 +43,7 @@ def get_gateways(): | |||
|
|||
except FileNotFoundError: | |||
with open(NODE_FILENAME, "w") as f: | |||
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.
this is my middle ground suggestion:
- let's not write any node.json. it's confusing pollution to the user, and it's information nile already knows. no more writing conflicts nor retrocompatibility issues.
- let's still read node.json. if there's any user custom network, let's add it (or overwrite any default). this is the stem for an actual nile config file, but retrocompatible and it buys us time to design properly, while fixing this.
thoughts?
Just confirming. You mean not writing to the node.json file after creating it, but keeping all network configurations and reading from it, right? I'd keep all the networks in a network config, to allow changing the RPC providers (gateway_urls) if we have more than one at some point for the same network (I assume we'll have). |
I mean not write/create any node.json files anymore, but take it into account if there's one already (e.g. with a custom network). this would be retrocompatible and fix the UX issue you point out, without us introducing any weird, fragile logic to overwrite/fix existing node.json files, and also provide a way for users to add their custom ones. node.json would be the network file you suggest, my approach only simplifies it so we can ship a fix asap. this node.json file can eventually evolve into a full config file #73, but i'm leaving it for later to avoid the design + refactor time it entails. |
Here's a few notes on the latest changes aiming to address the conversations regarding this PR @martriay @ericnordelo:
|
src/nile/common.py
Outdated
with open(NODE_FILENAME, "r") as fp: | ||
gateways = json.load(fp) | ||
gateways[network] = gateway_url | ||
|
||
with open(NODE_FILENAME, "w") as fp: | ||
json.dump(gateways, fp, indent=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.
with open(NODE_FILENAME, "r") as fp: | |
gateways = json.load(fp) | |
gateways[network] = gateway_url | |
with open(NODE_FILENAME, "w") as fp: | |
json.dump(gateways, fp, indent=2) | |
with open(NODE_FILENAME, "w") as fp: | |
gateways = json.load(fp) | |
gateways[network] = gateway_url | |
json.dump(gateways, fp, indent=2) |
isn't this simpler? why indent is only explicit 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.
This is simpler^, but the w
will remove the prior contents. This gives me an idea though
Co-authored-by: Martín Triay <[email protected]>
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.
Looking good! Left just a small suggestion and I think we are good to go.
src/nile/common.py
Outdated
|
||
|
||
def get_gateways(): | ||
"""Get the StarkNet node details.""" | ||
try: | ||
if os.path.exists(NODE_FILENAME): | ||
with open(NODE_FILENAME, "r") as f: | ||
gateway = json.load(f) |
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.
gateway = json.load(f) | |
custom_gateways = json.load(f) |
The name is a bit confusing being possible to have multiple custom gateways in the node.json
file.
1fa494a
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.
LGTM!
Resolves #297.
The current flow of network handling creates the awkward issue of an unresolved query in perpetuity when the node.json exists but the network key does not. This PR, therefore, proposes to add
goerli2
andintegration
gateways to the node.json in thenile node
command. This means that thegoerli2
andintegration
gateways will be accessible irrespective of the node.json file's existence.