-
-
Notifications
You must be signed in to change notification settings - Fork 132
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
ProviderNotConnectedError trying to connect to multiple networks in Python [APE-616] #1296
Comments
Closing and answering the solution to myself:
|
I'm reopening this one because it seems like our documentation needs Improvement for how to use multi-chain environments inside scripts especially creating FastAPI apps |
@fubuloubu thank you for all your efforts and contribution on ApeWorX/ape issues, not everyone post or comment but I'm sure a lot of people like me appreciate your feedbacks, it helps building trust with the devs and the community a lot; I'm very grateful for it. Here's a working version of FastAPI + multi-network connections established when receiving an HTTP REST API call: # ApeX/ape dependencies
from ape import accounts, project, networks
import click
# Web server dependencies
import uvicorn
from fastapi import FastAPI
import os
app = FastAPI()
TESTNETS_IN_APE = [
networks.ethereum.goerli.use_provider("infura"),
networks.bsc.testnet.use_provider("geth"),
networks.avalanche.fuji.use_provider("geth"),
networks.polygon.mumbai.use_provider("geth"),
networks.fantom.testnet.use_provider("geth"),
networks.optimism.goerli.use_provider("alchemy"),
networks.arbitrum.goerli.use_provider("alchemy"),
]
def main():
uvicorn.run(app, host="0.0.0.0", port=os.environ.get("PORT", 8080))
@app.get(path="/networks/list/testnets")
async def list_testnet_networks():
initial_list = []
for _provider in TESTNETS_IN_APE:
try:
with _provider as provider:
initial_list.append({"ecosystem_name": provider.network.ecosystem.name, "network_name": provider.network.name, "provider_name": provider.name})
click.echo(f"Connected successfully to network '{provider.network.ecosystem.name}:{provider.network.name}:{provider.name}'.")
except Exception as e:
click.echo(f"Failed to connect: {e}")
return initial_list Feel free to use this snippet in any form or shape for your future documentation effort. One small thing that also took time for to connect the dots on: Alchemy and Infura don't support all networks, but 'GETH' is not a bad word, it's actually just a way to connect directly to the public RPC endpoints these L1 and L2 projects maintain, or that some other Web3 infra. provider maintain. Here's my ape-config.yaml config for reference: geth:
bsc:
testnet:
uri: https://bsc-testnet.public.blastapi.io
mainnet:
uri: https://bsc-mainnet.public.blastapi.io
avalanche:
fuji:
uri: https://api.avax-test.network/ext/bc/C/rpc # https://ava-testnet.public.blastapi.io/ext/bc/C/rpc
mainnet:
uri: https://api.avax.network/ext/bc/C/rpc # https://ava-mainnet.public.blastapi.io/ext/bc/C/rpc
fantom:
testnet:
uri: https://fantom-testnet.public.blastapi.io
opera:
uri: https://fantom-mainnet.public.blastapi.io
polygon:
mumbai:
uri: https://polygon-testnet.public.blastapi.io
mainnet:
uri: https://polygon-mainnet.public.blastapi.io in case it also helps with the documentation efforts.. |
Thanks for the feedback! Yeah, we are looking much more deeply into FastAPI-based applications for a product idea we have, so this will help us debug some issues with this type of setup and help support you in this use case better. |
Nice! Well, then, the only thing left standing between the current design of ape and its ability to be turned into a REST API micro-service for Web3 tasks = its limitation importing accounts (private key or mnemonic) through CLI only, whereas the preferred way would be through Python (so that the private key can be passed through a secret manager, like that) |
You can very easily create a plugin for a custom account type, that can import secrets from various managed key systems (Vault, AWS, GCloud, Fireblocks, etc.). This is definitely a lot safer than using plaintext private keys (even accessed through a secret manager), so I would suggest doing that for your preferred platform of choice. It's very easy to create an account plugin, just implemented a few methods from this class. Here is an example of an account plugin: https://github.com/ApeWorX/ape-trezor |
I was able to get this to work with the similar code to the OP: dependencies:
- name: OpenZeppelin
github: OpenZeppelin/openzeppelin-contracts
version: 4.8.1
solidity:
import_remapping:
- openzeppelin=OpenZeppelin/4.8.1
default_ecosystem: polygon
polygon:
default_network: mumbai
mumbai:
default_provider: alchemy
$ cat scripts/deploy.py
import uvicorn # type: ignore
from fastapi import FastAPI
import os
from ape import accounts, project, networks
from ape.cli import NetworkBoundCommand, network_option
NETWORKS = [
"polygon:mumbai:alchemy",
"ethereum:goerli:alchemy"
]
app = FastAPI()
account = accounts.load(os.environ["WALLET_NAME"])
account.set_autosign(True, passphrase=os.environ["WALLET_PASSPHRASE"])
@app.get(path="/networks/list")
async def list_networks():
connected_networks = []
for network in NETWORKS:
with networks.parse_network_choice(network) as provider:
provider.connect()
ecosystem_name = provider.network.ecosystem.name
network_name = provider.network.name
provider_name = provider.name
connected_networks.append(network)
print(f"You are connected to network '{ecosystem_name}:{network_name}:{provider_name}'.")
return connected_networks
def main():
uvicorn.run(app, host="0.0.0.0", port=os.environ.get("PORT", 8080)) $ curl http://127.0.0.1:8080/networks/list
["polygon:mumbai:alchemy","ethereum:goerli:alchemy"] $ ape run deploy
WARNING: Danger! This account will now sign any transaction it's given.
INFO: Started server process [12403]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
You are connected to network 'polygon:mumbai:alchemy'.
You are connected to network 'ethereum:goerli:alchemy' This also works with the default network provider in However this doesn't work if the default network provider is different from the network provider you are using in
...
default_ecosystem: polygon
polygon:
default_network: mumbai
mumbai:
default_provider: infura
...
NETWORKS = [
"polygon:mumbai:alchemy",
"ethereum:goerli:alchemy"
]
...
for network in NETWORKS:
with networks.parse_network_choice(network) as provider: results in $ ape run deploy
ERROR: (ProviderNotConnectedError) Not connected to a network provider. |
@sabotagebeats follow up on this: "it seems like |
Updates!
the
For example, I know there was a bug when calling
Thank you! And sorry for being late on this one. |
Environment information
ape-config.yaml
(NOTE: do not post anything private like RPC urls or secrets!):What went wrong?
Please include information like:
How can it be fixed?
No idea, but I've researched, seen #1055, and I'm not sure how it was resolved since some discussions might have happened on Discord.
Also, I do not want to run ape on a specific network, I'm trying to automate the deployment of smart contracts on multiple networks when receiving an HTTP API request to do so.
Is what I'm trying to do even possible?
Let me know if you have any thoughts :)
The text was updated successfully, but these errors were encountered: