diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md
index acec68f8e..645802440 100644
--- a/.ai/categories/smart-contracts.md
+++ b/.ai/categories/smart-contracts.md
@@ -2690,9 +2690,6 @@ Add the Solidity compiler so you can generate standard EVM bytecode:
npm install --save-dev solc
```
-!!! tip
- The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements.
-
## Set Up the Web3 Provider
The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
@@ -2749,7 +2746,7 @@ With the provider set up, you can start querying the blockchain. For instance, t
const PROVIDER_RPC = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const main = async () => {
@@ -3012,7 +3009,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -3120,7 +3117,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -3140,7 +3137,7 @@ After running this script, your contract will be deployed to Polkadot Hub, and i
## Interact with the Contract
-Once the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
+Once the contract is deployed, you can interact with it by calling its functions. For example, to read the current stored value and then update it to a new value, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
```js title="scripts/updateStorage.js"
const { readFileSync } = require('fs');
@@ -3210,7 +3207,7 @@ updateStorage(config)
.catch((error) => console.error('Update error'));
```
-Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor.
+Ensure you replace the `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script reads the current stored value, sets it to 1, and then displays the updated value.
To interact with the contract, run:
@@ -3226,9 +3223,9 @@ node scripts/updateStorage.js
---
- Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, etc.
+ Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/)
+ [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/){target=\_blank}
@@ -6218,165 +6215,6 @@ The system maintains precise conversion mechanisms between:
This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows.
----
-
-Page Title: Troubleshooting Remix IDE
-
-- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md
-- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/
-- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions.
-
-# Remix IDE Troubleshooting
-
-This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here.
-
-## Contract fails to compile or shows errors in the terminal
-
-- **Check Solidity version compatibility**:
- - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab.
- - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher.
-
-- **Review syntax errors**:
- - Carefully read error messages in the terminal panel at the bottom of the screen.
- - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets.
-
-- **Clear cache and recompile**:
- - Delete the `artifacts` folder in the **File Explorer**.
- - Try compiling again with `Ctrl+S` or click the **Compile** button.
-
-## The `artifacts` folder doesn't appear after compilation
-
-- Ensure compilation completed successfully without errors.
-- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab.
-- Check that your `.sol` file is saved before compiling.
-
-## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.)
-
-- **Verify wallet installation**:
- - Ensure your wallet extension is properly installed and enabled in your browser.
- - Check that the extension icon appears in your browser toolbar.
-
-- **Refresh the page**:
- - Reload the Remix IDE page and try reconnecting.
-
-- **Check browser permissions**:
- - Ensure Remix has permission to interact with the wallet extension.
- - Check your browser's extension settings.
-
-- **Use correct environment**:
- - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown.
- - Choose **Injected Provider - MetaMask** (works with most wallet providers).
-
-## Wallet is connected but to the wrong network
-
-1. Open your wallet extension.
-2. Switch to the Polkadot Hub network.
-3. Refresh the Remix IDE if the network change isn't detected automatically.
-4. Verify the network name and chain ID match Polkadot Hub's configuration.
-
-## Deployment fails with "insufficient funds" or similar error
-
-- **Check your balance**:
- - Verify you have enough test tokens in your connected wallet.
- - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens.
-
-- **Wait for faucet tokens**:
- - Allow a few minutes for faucet transactions to complete.
- - Refresh your wallet to see the updated balance.
-
-## Deployment transaction is rejected or fails
-
-- **Increase gas limit**:
- - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field.
- - Try increasing it by 20-30% from the estimated amount.
-
-- **Check contract constructor parameters**:
- - Ensure any required constructor parameters are provided correctly.
- - Verify parameter types match the contract's constructor signature.
-
-- **Verify contract selection**:
- - Ensure you've selected the correct contract from the **Contract** dropdown.
- - If you have multiple contracts, make sure you're deploying the intended one.
-
-## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown
-
-- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option.
-- Ensure your wallet extension is unlocked and active.
-- Try disabling and re-enabling the wallet extension.
-- Refresh the Remix IDE page.
-
-## Wallet rejects transactions when trying to interact with deployed contracts
-
-- **Check wallet unlock status**:
- - Ensure your wallet is unlocked.
- - Verify you're approving the transaction in the wallet pop-up.
-
-- **Verify sufficient gas**:
- - Ensure you have enough tokens to cover the transaction fee.
- - The wallet pop-up should show the estimated gas cost.
-
-- **Network mismatch**:
- - Confirm your wallet is still connected to Polkadot Hub.
- - Check that Remix is using the same network.
-
-## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section
-
-- Wait for the transaction to be confirmed on-chain.
-- Check the Remix terminal for deployment confirmation.
-- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section.
-- If the deployment transaction failed, check the terminal for error messages.
-
-## Blue buttons (read functions) don't display return values
-
-- **Check the terminal**:
- - Return values appear in the terminal panel at the bottom.
- - Look for the decoded output section.
-
-- **Verify contract state**:
- - Ensure the contract has been properly initialized.
- - Check if the function requires a specific contract state to return values.
-
-- **Network connection**:
- - Verify you're still connected to the correct network.
- - Try refreshing the connection to your wallet.
-
-
-## Orange/red buttons (write functions) execute, but the state doesn't change
-
-- **Wait for transaction confirmation**:
- - Transactions need to be mined before state changes are reflected.
- - Check the terminal for transaction status.
- - Wait a few seconds and try rereading the state.
-
-- **Transaction failed**:
- - Check if the transaction was actually successful in the terminal.
- - Look for revert reasons or error messages.
- - Verify you approved the transaction in your wallet.
-
-- **Check transaction parameters**:
- - Ensure you're passing the correct parameters to the function.
- - For payable functions (red buttons), verify you're sending the correct amount.
-
-## Remix takes a long time to load or becomes unresponsive
-
-- **Clear browser cache**:
- - Clear your browser's cache and cookies.
- - Restart your browser.
-
-- **Disable unnecessary plugins**:
- - In Remix, deactivate plugins you're not using via the Plugin Manager.
-
-- **Use a supported browser**:
- - Use Chrome, Firefox, or Brave for the best compatibility.
- - Ensure your browser is up to date.
-
-## Changes to files or folders don't appear in the File Explorer
-
-- Click the refresh icon in the **File Explorer**.
-- Switch to a different tab and back to **File Explorer**.
-- Save your work and reload the Remix IDE page.
-
-
---
Page Title: Troubleshooting Hardhat
@@ -6907,6 +6745,165 @@ This guide provides solutions to common issues you may encounter when using Hard
```
+---
+
+Page Title: Troubleshooting Remix IDE
+
+- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md
+- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/
+- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions.
+
+# Remix IDE Troubleshooting
+
+This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here.
+
+## Contract fails to compile or shows errors in the terminal
+
+- **Check Solidity version compatibility**:
+ - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab.
+ - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher.
+
+- **Review syntax errors**:
+ - Carefully read error messages in the terminal panel at the bottom of the screen.
+ - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets.
+
+- **Clear cache and recompile**:
+ - Delete the `artifacts` folder in the **File Explorer**.
+ - Try compiling again with `Ctrl+S` or click the **Compile** button.
+
+## The `artifacts` folder doesn't appear after compilation
+
+- Ensure compilation completed successfully without errors.
+- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab.
+- Check that your `.sol` file is saved before compiling.
+
+## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.)
+
+- **Verify wallet installation**:
+ - Ensure your wallet extension is properly installed and enabled in your browser.
+ - Check that the extension icon appears in your browser toolbar.
+
+- **Refresh the page**:
+ - Reload the Remix IDE page and try reconnecting.
+
+- **Check browser permissions**:
+ - Ensure Remix has permission to interact with the wallet extension.
+ - Check your browser's extension settings.
+
+- **Use correct environment**:
+ - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown.
+ - Choose **Injected Provider - MetaMask** (works with most wallet providers).
+
+## Wallet is connected but to the wrong network
+
+1. Open your wallet extension.
+2. Switch to the Polkadot Hub network.
+3. Refresh the Remix IDE if the network change isn't detected automatically.
+4. Verify the network name and chain ID match Polkadot Hub's configuration.
+
+## Deployment fails with "insufficient funds" or similar error
+
+- **Check your balance**:
+ - Verify you have enough test tokens in your connected wallet.
+ - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens.
+
+- **Wait for faucet tokens**:
+ - Allow a few minutes for faucet transactions to complete.
+ - Refresh your wallet to see the updated balance.
+
+## Deployment transaction is rejected or fails
+
+- **Increase gas limit**:
+ - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field.
+ - Try increasing it by 20-30% from the estimated amount.
+
+- **Check contract constructor parameters**:
+ - Ensure any required constructor parameters are provided correctly.
+ - Verify parameter types match the contract's constructor signature.
+
+- **Verify contract selection**:
+ - Ensure you've selected the correct contract from the **Contract** dropdown.
+ - If you have multiple contracts, make sure you're deploying the intended one.
+
+## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown
+
+- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option.
+- Ensure your wallet extension is unlocked and active.
+- Try disabling and re-enabling the wallet extension.
+- Refresh the Remix IDE page.
+
+## Wallet rejects transactions when trying to interact with deployed contracts
+
+- **Check wallet unlock status**:
+ - Ensure your wallet is unlocked.
+ - Verify you're approving the transaction in the wallet pop-up.
+
+- **Verify sufficient gas**:
+ - Ensure you have enough tokens to cover the transaction fee.
+ - The wallet pop-up should show the estimated gas cost.
+
+- **Network mismatch**:
+ - Confirm your wallet is still connected to Polkadot Hub.
+ - Check that Remix is using the same network.
+
+## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section
+
+- Wait for the transaction to be confirmed on-chain.
+- Check the Remix terminal for deployment confirmation.
+- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section.
+- If the deployment transaction failed, check the terminal for error messages.
+
+## Blue buttons (read functions) don't display return values
+
+- **Check the terminal**:
+ - Return values appear in the terminal panel at the bottom.
+ - Look for the decoded output section.
+
+- **Verify contract state**:
+ - Ensure the contract has been properly initialized.
+ - Check if the function requires a specific contract state to return values.
+
+- **Network connection**:
+ - Verify you're still connected to the correct network.
+ - Try refreshing the connection to your wallet.
+
+
+## Orange/red buttons (write functions) execute, but the state doesn't change
+
+- **Wait for transaction confirmation**:
+ - Transactions need to be mined before state changes are reflected.
+ - Check the terminal for transaction status.
+ - Wait a few seconds and try rereading the state.
+
+- **Transaction failed**:
+ - Check if the transaction was actually successful in the terminal.
+ - Look for revert reasons or error messages.
+ - Verify you approved the transaction in your wallet.
+
+- **Check transaction parameters**:
+ - Ensure you're passing the correct parameters to the function.
+ - For payable functions (red buttons), verify you're sending the correct amount.
+
+## Remix takes a long time to load or becomes unresponsive
+
+- **Clear browser cache**:
+ - Clear your browser's cache and cookies.
+ - Restart your browser.
+
+- **Disable unnecessary plugins**:
+ - In Remix, deactivate plugins you're not using via the Plugin Manager.
+
+- **Use a supported browser**:
+ - Use Chrome, Firefox, or Brave for the best compatibility.
+ - Ensure your browser is up to date.
+
+## Changes to files or folders don't appear in the File Explorer
+
+- Click the refresh icon in the **File Explorer**.
+- Switch to a different tab and back to **File Explorer**.
+- Save your work and reload the Remix IDE page.
+
+
---
Page Title: Use Hardhat with Polkadot Hub
@@ -8264,8 +8261,6 @@ Page Title: Web3.py
# Web3.py
-!!! smartcontract "PolkaVM Preview Release"
- PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
## Introduction
Interacting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols.
@@ -8296,74 +8291,53 @@ This guide illustrates how to utilize Web3.py for interactions with Polkadot Hub
## Set Up the Web3 Provider
-The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:
+The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
-1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
+To interact with Polkadot Hub, you must set up a Web3.py provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. The following code sets up the provider configuration:
- ```python
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
- ```
-
- The provider connection script should look something like this:
+```python
+from web3 import Web3
- ```python title="connect_to_provider.py"
- from web3 import Web3
+PROVIDER_RPC = "INSERT_RPC_URL"
+web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
+```
- PROVIDER_RPC = 'INSERT_RPC_URL'
+!!! note
+ Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
- create_provider(PROVIDER_RPC)
+ ```python
+ PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
```
-1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:
+With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain.
+
+??? code "Fetch last block example"
```python title="fetch_last_block.py"
+ from web3 import Web3
+
+
def main():
try:
- web3 = create_provider(PROVIDER_RPC)
+ PROVIDER_RPC = "https://testnet-passet-hub-eth-rpc.polkadot.io"
+ web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
+ print("Last block: " + str(latest_block))
except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
+ print("Error connecting to Polkadot Hub TestNet: " + str(error))
+
if __name__ == "__main__":
main()
- ```
-
- ??? code "View complete script"
-
- ```python title="fetch_last_block.py"
- from web3 import Web3
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
-
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
-
- def main():
- try:
- web3 = create_provider(PROVIDER_RPC)
- latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
- except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
-
- if __name__ == "__main__":
- main()
- ```
-
-## Contract Deployment
+ ```
-Before deploying your contracts, make sure you've compiled them and obtained two key files:
+## Sample Storage Contract
-- An ABI (.json) file, which provides a JSON interface describing the contract's functions and how to interact with it.
-- A bytecode (.polkavm) file, which contains the low-level machine code executable on [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} that represents the compiled smart contract ready for blockchain deployment.
+Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the [`py-solc-x`](https://solcx.readthedocs.io/en/latest/){target=\_blank} compiler.
-To follow this guide, you can use the following solidity contract as an example:
+To follow this guide, you can use the following Solidity contract as an example:
```solidity title="Storage.sol"
//SPDX-License-Identifier: MIT
@@ -8389,86 +8363,156 @@ contract Storage {
}
```
+
+
+After you've compiled the `Storage.sol` contract, you should have:
+
+- **An ABI (`.json`) file**: Provides a JSON interface describing the contract's functions and how to interact with it.
+- **A bytecode (`.bin`) file**: Contains the low-level machine code executable on EVM that represents the compiled smart contract ready for blockchain deployment.
+
+## Contract Deployment
+
To deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:
```python title="deploy.py"
from web3 import Web3
import json
+import time
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
def get_bytecode(contract_name):
try:
- with open(f"{contract_name}.polkavm", 'rb') as file:
- return '0x' + file.read().hex()
+ with open(f"{contract_name}.bin", "r") as file:
+ bytecode = file.read().strip()
+ return bytecode if bytecode.startswith("0x") else f"0x{bytecode}"
except Exception as error:
print(f"❌ Could not find bytecode for contract {contract_name}: {error}")
raise error
-async def deploy(config):
+
+def deploy_with_retry(config, max_retries=3):
+ """Deploy with retry logic for RPC errors"""
+ for attempt in range(max_retries):
+ try:
+ return deploy(config)
+ except Exception as error:
+ error_str = str(error)
+ if (
+ "500" in error_str
+ or "Internal Server Error" in error_str
+ or "Connection" in error_str
+ ):
+ if attempt < max_retries - 1:
+ wait_time = (attempt + 1) * 3
+ print(
+ f"RPC error, retrying in {wait_time} seconds... (attempt {attempt + 1}/{max_retries})"
+ )
+ time.sleep(wait_time)
+ continue
+ raise error
+
+
+def deploy(config):
try:
- # Initialize Web3 with RPC URL
- web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+ # Initialize Web3 with RPC URL and longer timeout
+ web3 = Web3(
+ Web3.HTTPProvider(config["rpc_url"], request_kwargs={"timeout": 120})
+ )
+
# Prepare account
- account = web3.eth.account.from_key(config["private_key"])
- print(f"address: {account.address}")
-
- # Load ABI
- abi = get_abi('Storage')
-
+ formatted_private_key = (
+ config["private_key"]
+ if config["private_key"].startswith("0x")
+ else f"0x{config['private_key']}"
+ )
+ account = web3.eth.account.from_key(formatted_private_key)
+ print(f"Deploying from address: {account.address}")
+
+ # Load ABI and bytecode
+ abi = get_abi("Storage")
+ bytecode = get_bytecode("Storage")
+ print(f"Bytecode length: {len(bytecode)}")
+
# Create contract instance
- contract = web3.eth.contract(abi=abi, bytecode=get_bytecode('Storage'))
-
- # Get current nonce
+ contract = web3.eth.contract(abi=abi, bytecode=bytecode)
+
+ # Get current nonce (this will test the connection)
+ print("Getting nonce...")
nonce = web3.eth.get_transaction_count(account.address)
-
- # Prepare deployment transaction
- transaction = {
- 'from': account.address,
- 'nonce': nonce,
- }
-
- # Build and sign transaction
- construct_txn = contract.constructor().build_transaction(transaction)
- signed_txn = web3.eth.account.sign_transaction(construct_txn, private_key=config["private_key"])
-
+ print(f"Nonce: {nonce}")
+
+ # Estimate gas
+ print("Estimating gas...")
+ gas_estimate = web3.eth.estimate_gas(
+ {"from": account.address, "data": bytecode}
+ )
+ print(f"Estimated gas: {gas_estimate}")
+
+ # Get gas price
+ print("Getting gas price...")
+ gas_price = web3.eth.gas_price
+ print(f"Gas price: {web3.from_wei(gas_price, 'gwei')} gwei")
+
+ # Build deployment transaction
+ print("Building transaction...")
+ construct_txn = contract.constructor().build_transaction(
+ {
+ "from": account.address,
+ "nonce": nonce,
+ "gas": gas_estimate,
+ "gasPrice": gas_price,
+ }
+ )
+
+ # Sign transaction
+ print("Signing transaction...")
+ signed_txn = web3.eth.account.sign_transaction(
+ construct_txn, private_key=formatted_private_key
+ )
+
# Send transaction
+ print("Sending transaction...")
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for transaction receipt
- tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
+ print("Waiting for transaction receipt...")
+ tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
contract_address = tx_receipt.contractAddress
-
- # Log and return contract details
- print(f"Contract deployed at: {contract_address}")
+
+ # Log results
+ print(f"✅ Contract deployed at: {contract_address}")
+ print(f"Gas used: {tx_receipt.gasUsed}")
+ print(f"Block number: {tx_receipt.blockNumber}")
+
return web3.eth.contract(address=contract_address, abi=abi)
-
+
except Exception as error:
- print('Deployment failed:', error)
+ print(f"❌ Deployment failed: {error}")
raise error
+
if __name__ == "__main__":
- # Example usage
- import asyncio
-
deployment_config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
}
-
- asyncio.run(deploy(deployment_config))
+
+ deploy_with_retry(deployment_config)
+
```
!!!warning
- Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead.
+ Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds.
## Interact with the Contract
@@ -8478,119 +8522,89 @@ After deployment, interact with your contract using Web3.py methods. The example
from web3 import Web3
import json
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
async def update_storage(config):
try:
# Initialize Web3 with RPC URL
web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+
# Prepare account
account = web3.eth.account.from_key(config["private_key"])
-
+
# Load ABI
- abi = get_abi('Storage')
-
+ abi = get_abi("Storage")
+
# Create contract instance
contract = web3.eth.contract(address=config["contract_address"], abi=abi)
-
+
# Get initial value
initial_value = contract.functions.storedNumber().call()
- print('Current stored value:', initial_value)
-
+ print("Current stored value:", initial_value)
+
# Get current nonce
nonce = web3.eth.get_transaction_count(account.address)
-
+
# Prepare transaction
- transaction = contract.functions.setNumber(1).build_transaction({
- 'from': account.address,
- 'nonce': nonce
- })
-
+ transaction = contract.functions.setNumber(1).build_transaction(
+ {"from": account.address, "nonce": nonce}
+ )
+
# Sign transaction
- signed_txn = web3.eth.account.sign_transaction(transaction, private_key=config["private_key"])
-
+ signed_txn = web3.eth.account.sign_transaction(
+ transaction, private_key=config["private_key"]
+ )
+
# Send transaction
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for receipt
receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
-
+
# Get updated value
new_value = contract.functions.storedNumber().call()
- print('New stored value:', new_value)
-
+ print("New stored value:", new_value)
+
return receipt
-
+
except Exception as error:
- print('Update failed:', error)
+ print("Update failed:", error)
raise error
+
if __name__ == "__main__":
# Example usage
import asyncio
-
+
config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
"contract_address": "INSERT_CONTRACT_ADDRESS",
}
-
+
asyncio.run(update_storage(config))
+
```
## Where to Go Next
-Now that you have the foundation for using Web3.py with Polkadot Hub, consider exploring:
-
--
External __Advanced Web3.py Features__
-
- ---
- Explore Web3.py's documentation:
-
- - [:octicons-arrow-right-24: Middleware](https://web3py.readthedocs.io/en/stable/middleware.html){target=\_blank}
- - [:octicons-arrow-right-24: Filters & Events](https://web3py.readthedocs.io/en/stable/filters.html){target=\_blank}
- - [:octicons-arrow-right-24: ENS](https://web3py.readthedocs.io/en/stable/ens_overview.html){target=\_blank}
-
-
--
External __Testing Frameworks__
+-
External __Web3.py Docs__
---
- Integrate Web3.py with Python testing frameworks:
-
- - [:octicons-arrow-right-24: Pytest](https://docs.pytest.org/){target=\_blank}
- - [:octicons-arrow-right-24: Brownie](https://eth-brownie.readthedocs.io/){target=\_blank}
-
-
--
External __Transaction Management__
-
- ---
- Learn advanced transaction handling:
-
-
- - [:octicons-arrow-right-24: Gas Strategies](https://web3py.readthedocs.io/en/stable/gas_price.html){target=\_blank}
- - [:octicons-arrow-right-24: Account Management](https://web3py.readthedocs.io/en/stable/web3.eth.account.html){target=\_blank}
-
-
--
External __Building dApps__
+ Explore the Web3.py documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- ---
- Combine Web3.py with these frameworks to create full-stack applications:
-
-
- - [:octicons-arrow-right-24: Flask](https://flask.palletsprojects.com/){target=\_blank}
- - [:octicons-arrow-right-24: Django](https://www.djangoproject.com/){target=\_blank}
- - [:octicons-arrow-right-24: FastAPI](https://fastapi.tiangolo.com/){target=\_blank}
-
+ [:octicons-arrow-right-24: Get Started](https://web3py.readthedocs.io/en/stable/){target=\_blank}
diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md
index afb47225a..61a4eeef7 100644
--- a/.ai/categories/tooling.md
+++ b/.ai/categories/tooling.md
@@ -1736,9 +1736,6 @@ Add the Solidity compiler so you can generate standard EVM bytecode:
npm install --save-dev solc
```
-!!! tip
- The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements.
-
## Set Up the Web3 Provider
The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
@@ -1795,7 +1792,7 @@ With the provider set up, you can start querying the blockchain. For instance, t
const PROVIDER_RPC = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const main = async () => {
@@ -2058,7 +2055,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -2166,7 +2163,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -2186,7 +2183,7 @@ After running this script, your contract will be deployed to Polkadot Hub, and i
## Interact with the Contract
-Once the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
+Once the contract is deployed, you can interact with it by calling its functions. For example, to read the current stored value and then update it to a new value, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
```js title="scripts/updateStorage.js"
const { readFileSync } = require('fs');
@@ -2256,7 +2253,7 @@ updateStorage(config)
.catch((error) => console.error('Update error'));
```
-Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor.
+Ensure you replace the `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script reads the current stored value, sets it to 1, and then displays the updated value.
To interact with the contract, run:
@@ -2272,9 +2269,9 @@ node scripts/updateStorage.js
---
- Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, etc.
+ Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/)
+ [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/){target=\_blank}
@@ -6339,165 +6336,6 @@ The system maintains precise conversion mechanisms between:
This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows.
----
-
-Page Title: Troubleshooting Remix IDE
-
-- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md
-- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/
-- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions.
-
-# Remix IDE Troubleshooting
-
-This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here.
-
-## Contract fails to compile or shows errors in the terminal
-
-- **Check Solidity version compatibility**:
- - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab.
- - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher.
-
-- **Review syntax errors**:
- - Carefully read error messages in the terminal panel at the bottom of the screen.
- - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets.
-
-- **Clear cache and recompile**:
- - Delete the `artifacts` folder in the **File Explorer**.
- - Try compiling again with `Ctrl+S` or click the **Compile** button.
-
-## The `artifacts` folder doesn't appear after compilation
-
-- Ensure compilation completed successfully without errors.
-- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab.
-- Check that your `.sol` file is saved before compiling.
-
-## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.)
-
-- **Verify wallet installation**:
- - Ensure your wallet extension is properly installed and enabled in your browser.
- - Check that the extension icon appears in your browser toolbar.
-
-- **Refresh the page**:
- - Reload the Remix IDE page and try reconnecting.
-
-- **Check browser permissions**:
- - Ensure Remix has permission to interact with the wallet extension.
- - Check your browser's extension settings.
-
-- **Use correct environment**:
- - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown.
- - Choose **Injected Provider - MetaMask** (works with most wallet providers).
-
-## Wallet is connected but to the wrong network
-
-1. Open your wallet extension.
-2. Switch to the Polkadot Hub network.
-3. Refresh the Remix IDE if the network change isn't detected automatically.
-4. Verify the network name and chain ID match Polkadot Hub's configuration.
-
-## Deployment fails with "insufficient funds" or similar error
-
-- **Check your balance**:
- - Verify you have enough test tokens in your connected wallet.
- - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens.
-
-- **Wait for faucet tokens**:
- - Allow a few minutes for faucet transactions to complete.
- - Refresh your wallet to see the updated balance.
-
-## Deployment transaction is rejected or fails
-
-- **Increase gas limit**:
- - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field.
- - Try increasing it by 20-30% from the estimated amount.
-
-- **Check contract constructor parameters**:
- - Ensure any required constructor parameters are provided correctly.
- - Verify parameter types match the contract's constructor signature.
-
-- **Verify contract selection**:
- - Ensure you've selected the correct contract from the **Contract** dropdown.
- - If you have multiple contracts, make sure you're deploying the intended one.
-
-## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown
-
-- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option.
-- Ensure your wallet extension is unlocked and active.
-- Try disabling and re-enabling the wallet extension.
-- Refresh the Remix IDE page.
-
-## Wallet rejects transactions when trying to interact with deployed contracts
-
-- **Check wallet unlock status**:
- - Ensure your wallet is unlocked.
- - Verify you're approving the transaction in the wallet pop-up.
-
-- **Verify sufficient gas**:
- - Ensure you have enough tokens to cover the transaction fee.
- - The wallet pop-up should show the estimated gas cost.
-
-- **Network mismatch**:
- - Confirm your wallet is still connected to Polkadot Hub.
- - Check that Remix is using the same network.
-
-## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section
-
-- Wait for the transaction to be confirmed on-chain.
-- Check the Remix terminal for deployment confirmation.
-- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section.
-- If the deployment transaction failed, check the terminal for error messages.
-
-## Blue buttons (read functions) don't display return values
-
-- **Check the terminal**:
- - Return values appear in the terminal panel at the bottom.
- - Look for the decoded output section.
-
-- **Verify contract state**:
- - Ensure the contract has been properly initialized.
- - Check if the function requires a specific contract state to return values.
-
-- **Network connection**:
- - Verify you're still connected to the correct network.
- - Try refreshing the connection to your wallet.
-
-
-## Orange/red buttons (write functions) execute, but the state doesn't change
-
-- **Wait for transaction confirmation**:
- - Transactions need to be mined before state changes are reflected.
- - Check the terminal for transaction status.
- - Wait a few seconds and try rereading the state.
-
-- **Transaction failed**:
- - Check if the transaction was actually successful in the terminal.
- - Look for revert reasons or error messages.
- - Verify you approved the transaction in your wallet.
-
-- **Check transaction parameters**:
- - Ensure you're passing the correct parameters to the function.
- - For payable functions (red buttons), verify you're sending the correct amount.
-
-## Remix takes a long time to load or becomes unresponsive
-
-- **Clear browser cache**:
- - Clear your browser's cache and cookies.
- - Restart your browser.
-
-- **Disable unnecessary plugins**:
- - In Remix, deactivate plugins you're not using via the Plugin Manager.
-
-- **Use a supported browser**:
- - Use Chrome, Firefox, or Brave for the best compatibility.
- - Ensure your browser is up to date.
-
-## Changes to files or folders don't appear in the File Explorer
-
-- Click the refresh icon in the **File Explorer**.
-- Switch to a different tab and back to **File Explorer**.
-- Save your work and reload the Remix IDE page.
-
-
---
Page Title: Troubleshooting Hardhat
@@ -7028,6 +6866,165 @@ This guide provides solutions to common issues you may encounter when using Hard
```
+---
+
+Page Title: Troubleshooting Remix IDE
+
+- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md
+- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/
+- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions.
+
+# Remix IDE Troubleshooting
+
+This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here.
+
+## Contract fails to compile or shows errors in the terminal
+
+- **Check Solidity version compatibility**:
+ - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab.
+ - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher.
+
+- **Review syntax errors**:
+ - Carefully read error messages in the terminal panel at the bottom of the screen.
+ - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets.
+
+- **Clear cache and recompile**:
+ - Delete the `artifacts` folder in the **File Explorer**.
+ - Try compiling again with `Ctrl+S` or click the **Compile** button.
+
+## The `artifacts` folder doesn't appear after compilation
+
+- Ensure compilation completed successfully without errors.
+- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab.
+- Check that your `.sol` file is saved before compiling.
+
+## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.)
+
+- **Verify wallet installation**:
+ - Ensure your wallet extension is properly installed and enabled in your browser.
+ - Check that the extension icon appears in your browser toolbar.
+
+- **Refresh the page**:
+ - Reload the Remix IDE page and try reconnecting.
+
+- **Check browser permissions**:
+ - Ensure Remix has permission to interact with the wallet extension.
+ - Check your browser's extension settings.
+
+- **Use correct environment**:
+ - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown.
+ - Choose **Injected Provider - MetaMask** (works with most wallet providers).
+
+## Wallet is connected but to the wrong network
+
+1. Open your wallet extension.
+2. Switch to the Polkadot Hub network.
+3. Refresh the Remix IDE if the network change isn't detected automatically.
+4. Verify the network name and chain ID match Polkadot Hub's configuration.
+
+## Deployment fails with "insufficient funds" or similar error
+
+- **Check your balance**:
+ - Verify you have enough test tokens in your connected wallet.
+ - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens.
+
+- **Wait for faucet tokens**:
+ - Allow a few minutes for faucet transactions to complete.
+ - Refresh your wallet to see the updated balance.
+
+## Deployment transaction is rejected or fails
+
+- **Increase gas limit**:
+ - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field.
+ - Try increasing it by 20-30% from the estimated amount.
+
+- **Check contract constructor parameters**:
+ - Ensure any required constructor parameters are provided correctly.
+ - Verify parameter types match the contract's constructor signature.
+
+- **Verify contract selection**:
+ - Ensure you've selected the correct contract from the **Contract** dropdown.
+ - If you have multiple contracts, make sure you're deploying the intended one.
+
+## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown
+
+- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option.
+- Ensure your wallet extension is unlocked and active.
+- Try disabling and re-enabling the wallet extension.
+- Refresh the Remix IDE page.
+
+## Wallet rejects transactions when trying to interact with deployed contracts
+
+- **Check wallet unlock status**:
+ - Ensure your wallet is unlocked.
+ - Verify you're approving the transaction in the wallet pop-up.
+
+- **Verify sufficient gas**:
+ - Ensure you have enough tokens to cover the transaction fee.
+ - The wallet pop-up should show the estimated gas cost.
+
+- **Network mismatch**:
+ - Confirm your wallet is still connected to Polkadot Hub.
+ - Check that Remix is using the same network.
+
+## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section
+
+- Wait for the transaction to be confirmed on-chain.
+- Check the Remix terminal for deployment confirmation.
+- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section.
+- If the deployment transaction failed, check the terminal for error messages.
+
+## Blue buttons (read functions) don't display return values
+
+- **Check the terminal**:
+ - Return values appear in the terminal panel at the bottom.
+ - Look for the decoded output section.
+
+- **Verify contract state**:
+ - Ensure the contract has been properly initialized.
+ - Check if the function requires a specific contract state to return values.
+
+- **Network connection**:
+ - Verify you're still connected to the correct network.
+ - Try refreshing the connection to your wallet.
+
+
+## Orange/red buttons (write functions) execute, but the state doesn't change
+
+- **Wait for transaction confirmation**:
+ - Transactions need to be mined before state changes are reflected.
+ - Check the terminal for transaction status.
+ - Wait a few seconds and try rereading the state.
+
+- **Transaction failed**:
+ - Check if the transaction was actually successful in the terminal.
+ - Look for revert reasons or error messages.
+ - Verify you approved the transaction in your wallet.
+
+- **Check transaction parameters**:
+ - Ensure you're passing the correct parameters to the function.
+ - For payable functions (red buttons), verify you're sending the correct amount.
+
+## Remix takes a long time to load or becomes unresponsive
+
+- **Clear browser cache**:
+ - Clear your browser's cache and cookies.
+ - Restart your browser.
+
+- **Disable unnecessary plugins**:
+ - In Remix, deactivate plugins you're not using via the Plugin Manager.
+
+- **Use a supported browser**:
+ - Use Chrome, Firefox, or Brave for the best compatibility.
+ - Ensure your browser is up to date.
+
+## Changes to files or folders don't appear in the File Explorer
+
+- Click the refresh icon in the **File Explorer**.
+- Switch to a different tab and back to **File Explorer**.
+- Save your work and reload the Remix IDE page.
+
+
---
Page Title: Use Hardhat with Polkadot Hub
@@ -8473,8 +8470,6 @@ Page Title: Web3.py
# Web3.py
-!!! smartcontract "PolkaVM Preview Release"
- PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
## Introduction
Interacting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols.
@@ -8505,74 +8500,53 @@ This guide illustrates how to utilize Web3.py for interactions with Polkadot Hub
## Set Up the Web3 Provider
-The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:
-
-1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
+The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
- ```python
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
- ```
+To interact with Polkadot Hub, you must set up a Web3.py provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. The following code sets up the provider configuration:
- The provider connection script should look something like this:
+```python
+from web3 import Web3
- ```python title="connect_to_provider.py"
- from web3 import Web3
+PROVIDER_RPC = "INSERT_RPC_URL"
+web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
+```
- PROVIDER_RPC = 'INSERT_RPC_URL'
+!!! note
+ Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
- create_provider(PROVIDER_RPC)
+ ```python
+ PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
```
-1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:
+With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain.
+
+??? code "Fetch last block example"
```python title="fetch_last_block.py"
+ from web3 import Web3
+
+
def main():
try:
- web3 = create_provider(PROVIDER_RPC)
+ PROVIDER_RPC = "https://testnet-passet-hub-eth-rpc.polkadot.io"
+ web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
+ print("Last block: " + str(latest_block))
except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
+ print("Error connecting to Polkadot Hub TestNet: " + str(error))
+
if __name__ == "__main__":
main()
- ```
-
- ??? code "View complete script"
- ```python title="fetch_last_block.py"
- from web3 import Web3
-
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
-
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
-
- def main():
- try:
- web3 = create_provider(PROVIDER_RPC)
- latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
- except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
-
- if __name__ == "__main__":
- main()
- ```
-
-## Contract Deployment
+ ```
-Before deploying your contracts, make sure you've compiled them and obtained two key files:
+## Sample Storage Contract
-- An ABI (.json) file, which provides a JSON interface describing the contract's functions and how to interact with it.
-- A bytecode (.polkavm) file, which contains the low-level machine code executable on [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} that represents the compiled smart contract ready for blockchain deployment.
+Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the [`py-solc-x`](https://solcx.readthedocs.io/en/latest/){target=\_blank} compiler.
-To follow this guide, you can use the following solidity contract as an example:
+To follow this guide, you can use the following Solidity contract as an example:
```solidity title="Storage.sol"
//SPDX-License-Identifier: MIT
@@ -8598,86 +8572,156 @@ contract Storage {
}
```
+
+
+After you've compiled the `Storage.sol` contract, you should have:
+
+- **An ABI (`.json`) file**: Provides a JSON interface describing the contract's functions and how to interact with it.
+- **A bytecode (`.bin`) file**: Contains the low-level machine code executable on EVM that represents the compiled smart contract ready for blockchain deployment.
+
+## Contract Deployment
+
To deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:
```python title="deploy.py"
from web3 import Web3
import json
+import time
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
def get_bytecode(contract_name):
try:
- with open(f"{contract_name}.polkavm", 'rb') as file:
- return '0x' + file.read().hex()
+ with open(f"{contract_name}.bin", "r") as file:
+ bytecode = file.read().strip()
+ return bytecode if bytecode.startswith("0x") else f"0x{bytecode}"
except Exception as error:
print(f"❌ Could not find bytecode for contract {contract_name}: {error}")
raise error
-async def deploy(config):
+
+def deploy_with_retry(config, max_retries=3):
+ """Deploy with retry logic for RPC errors"""
+ for attempt in range(max_retries):
+ try:
+ return deploy(config)
+ except Exception as error:
+ error_str = str(error)
+ if (
+ "500" in error_str
+ or "Internal Server Error" in error_str
+ or "Connection" in error_str
+ ):
+ if attempt < max_retries - 1:
+ wait_time = (attempt + 1) * 3
+ print(
+ f"RPC error, retrying in {wait_time} seconds... (attempt {attempt + 1}/{max_retries})"
+ )
+ time.sleep(wait_time)
+ continue
+ raise error
+
+
+def deploy(config):
try:
- # Initialize Web3 with RPC URL
- web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+ # Initialize Web3 with RPC URL and longer timeout
+ web3 = Web3(
+ Web3.HTTPProvider(config["rpc_url"], request_kwargs={"timeout": 120})
+ )
+
# Prepare account
- account = web3.eth.account.from_key(config["private_key"])
- print(f"address: {account.address}")
-
- # Load ABI
- abi = get_abi('Storage')
-
+ formatted_private_key = (
+ config["private_key"]
+ if config["private_key"].startswith("0x")
+ else f"0x{config['private_key']}"
+ )
+ account = web3.eth.account.from_key(formatted_private_key)
+ print(f"Deploying from address: {account.address}")
+
+ # Load ABI and bytecode
+ abi = get_abi("Storage")
+ bytecode = get_bytecode("Storage")
+ print(f"Bytecode length: {len(bytecode)}")
+
# Create contract instance
- contract = web3.eth.contract(abi=abi, bytecode=get_bytecode('Storage'))
-
- # Get current nonce
+ contract = web3.eth.contract(abi=abi, bytecode=bytecode)
+
+ # Get current nonce (this will test the connection)
+ print("Getting nonce...")
nonce = web3.eth.get_transaction_count(account.address)
-
- # Prepare deployment transaction
- transaction = {
- 'from': account.address,
- 'nonce': nonce,
- }
-
- # Build and sign transaction
- construct_txn = contract.constructor().build_transaction(transaction)
- signed_txn = web3.eth.account.sign_transaction(construct_txn, private_key=config["private_key"])
-
+ print(f"Nonce: {nonce}")
+
+ # Estimate gas
+ print("Estimating gas...")
+ gas_estimate = web3.eth.estimate_gas(
+ {"from": account.address, "data": bytecode}
+ )
+ print(f"Estimated gas: {gas_estimate}")
+
+ # Get gas price
+ print("Getting gas price...")
+ gas_price = web3.eth.gas_price
+ print(f"Gas price: {web3.from_wei(gas_price, 'gwei')} gwei")
+
+ # Build deployment transaction
+ print("Building transaction...")
+ construct_txn = contract.constructor().build_transaction(
+ {
+ "from": account.address,
+ "nonce": nonce,
+ "gas": gas_estimate,
+ "gasPrice": gas_price,
+ }
+ )
+
+ # Sign transaction
+ print("Signing transaction...")
+ signed_txn = web3.eth.account.sign_transaction(
+ construct_txn, private_key=formatted_private_key
+ )
+
# Send transaction
+ print("Sending transaction...")
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for transaction receipt
- tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
+ print("Waiting for transaction receipt...")
+ tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
contract_address = tx_receipt.contractAddress
-
- # Log and return contract details
- print(f"Contract deployed at: {contract_address}")
+
+ # Log results
+ print(f"✅ Contract deployed at: {contract_address}")
+ print(f"Gas used: {tx_receipt.gasUsed}")
+ print(f"Block number: {tx_receipt.blockNumber}")
+
return web3.eth.contract(address=contract_address, abi=abi)
-
+
except Exception as error:
- print('Deployment failed:', error)
+ print(f"❌ Deployment failed: {error}")
raise error
+
if __name__ == "__main__":
- # Example usage
- import asyncio
-
deployment_config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
}
-
- asyncio.run(deploy(deployment_config))
+
+ deploy_with_retry(deployment_config)
+
```
!!!warning
- Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead.
+ Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds.
## Interact with the Contract
@@ -8687,120 +8731,90 @@ After deployment, interact with your contract using Web3.py methods. The example
from web3 import Web3
import json
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
async def update_storage(config):
try:
# Initialize Web3 with RPC URL
web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+
# Prepare account
account = web3.eth.account.from_key(config["private_key"])
-
+
# Load ABI
- abi = get_abi('Storage')
-
+ abi = get_abi("Storage")
+
# Create contract instance
contract = web3.eth.contract(address=config["contract_address"], abi=abi)
-
+
# Get initial value
initial_value = contract.functions.storedNumber().call()
- print('Current stored value:', initial_value)
-
+ print("Current stored value:", initial_value)
+
# Get current nonce
nonce = web3.eth.get_transaction_count(account.address)
-
+
# Prepare transaction
- transaction = contract.functions.setNumber(1).build_transaction({
- 'from': account.address,
- 'nonce': nonce
- })
-
+ transaction = contract.functions.setNumber(1).build_transaction(
+ {"from": account.address, "nonce": nonce}
+ )
+
# Sign transaction
- signed_txn = web3.eth.account.sign_transaction(transaction, private_key=config["private_key"])
-
+ signed_txn = web3.eth.account.sign_transaction(
+ transaction, private_key=config["private_key"]
+ )
+
# Send transaction
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for receipt
receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
-
+
# Get updated value
new_value = contract.functions.storedNumber().call()
- print('New stored value:', new_value)
-
+ print("New stored value:", new_value)
+
return receipt
-
+
except Exception as error:
- print('Update failed:', error)
+ print("Update failed:", error)
raise error
+
if __name__ == "__main__":
# Example usage
import asyncio
-
+
config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
"contract_address": "INSERT_CONTRACT_ADDRESS",
}
-
+
asyncio.run(update_storage(config))
+
```
## Where to Go Next
-Now that you have the foundation for using Web3.py with Polkadot Hub, consider exploring:
-
--
External __Advanced Web3.py Features__
-
- ---
- Explore Web3.py's documentation:
-
- - [:octicons-arrow-right-24: Middleware](https://web3py.readthedocs.io/en/stable/middleware.html){target=\_blank}
- - [:octicons-arrow-right-24: Filters & Events](https://web3py.readthedocs.io/en/stable/filters.html){target=\_blank}
- - [:octicons-arrow-right-24: ENS](https://web3py.readthedocs.io/en/stable/ens_overview.html){target=\_blank}
-
-
--
External __Testing Frameworks__
+-
External __Web3.py Docs__
---
- Integrate Web3.py with Python testing frameworks:
-
- - [:octicons-arrow-right-24: Pytest](https://docs.pytest.org/){target=\_blank}
- - [:octicons-arrow-right-24: Brownie](https://eth-brownie.readthedocs.io/){target=\_blank}
-
-
--
External __Transaction Management__
-
- ---
- Learn advanced transaction handling:
-
-
- - [:octicons-arrow-right-24: Gas Strategies](https://web3py.readthedocs.io/en/stable/gas_price.html){target=\_blank}
- - [:octicons-arrow-right-24: Account Management](https://web3py.readthedocs.io/en/stable/web3.eth.account.html){target=\_blank}
-
-
--
External __Building dApps__
+ Explore the Web3.py documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- ---
- Combine Web3.py with these frameworks to create full-stack applications:
-
-
- - [:octicons-arrow-right-24: Flask](https://flask.palletsprojects.com/){target=\_blank}
- - [:octicons-arrow-right-24: Django](https://www.djangoproject.com/){target=\_blank}
- - [:octicons-arrow-right-24: FastAPI](https://fastapi.tiangolo.com/){target=\_blank}
-
+ [:octicons-arrow-right-24: Get Started](https://web3py.readthedocs.io/en/stable/){target=\_blank}
diff --git a/.ai/pages/smart-contracts-libraries-web3-js.md b/.ai/pages/smart-contracts-libraries-web3-js.md
index dbfdfc037..dd576e49a 100644
--- a/.ai/pages/smart-contracts-libraries-web3-js.md
+++ b/.ai/pages/smart-contracts-libraries-web3-js.md
@@ -73,9 +73,6 @@ Add the Solidity compiler so you can generate standard EVM bytecode:
npm install --save-dev solc
```
-!!! tip
- The sample scripts use ECMAScript modules. Add `"type": "module"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements.
-
## Set Up the Web3 Provider
The provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
@@ -132,7 +129,7 @@ With the provider set up, you can start querying the blockchain. For instance, t
const PROVIDER_RPC = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const main = async () => {
@@ -395,7 +392,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -503,7 +500,7 @@ You can create a `deploy.js` script in the `scripts` directory of your project t
const providerConfig = {
rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready
chainId: 420420422,
- name: 'polkadot-hub-testnet',
+ name: 'polkadotTestNet',
};
const privateKey = 'INSERT_PRIVATE_KEY';
@@ -523,7 +520,7 @@ After running this script, your contract will be deployed to Polkadot Hub, and i
## Interact with the Contract
-Once the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
+Once the contract is deployed, you can interact with it by calling its functions. For example, to read the current stored value and then update it to a new value, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:
```js title="scripts/updateStorage.js"
const { readFileSync } = require('fs');
@@ -593,7 +590,7 @@ updateStorage(config)
.catch((error) => console.error('Update error'));
```
-Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor.
+Ensure you replace the `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script reads the current stored value, sets it to 1, and then displays the updated value.
To interact with the contract, run:
@@ -609,8 +606,8 @@ node scripts/updateStorage.js
---
- Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, etc.
+ Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/)
+ [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/){target=\_blank}
diff --git a/.ai/pages/smart-contracts-libraries-web3-py.md b/.ai/pages/smart-contracts-libraries-web3-py.md
index 7f9333825..205d8bd1b 100644
--- a/.ai/pages/smart-contracts-libraries-web3-py.md
+++ b/.ai/pages/smart-contracts-libraries-web3-py.md
@@ -7,8 +7,6 @@ url: https://docs.polkadot.com/smart-contracts/libraries/web3-py/
# Web3.py
-!!! smartcontract "PolkaVM Preview Release"
- PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
## Introduction
Interacting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols.
@@ -39,74 +37,53 @@ This guide illustrates how to utilize Web3.py for interactions with Polkadot Hub
## Set Up the Web3 Provider
-The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:
+The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
-1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
+To interact with Polkadot Hub, you must set up a Web3.py provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. The following code sets up the provider configuration:
- ```python
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
- ```
-
- The provider connection script should look something like this:
+```python
+from web3 import Web3
- ```python title="connect_to_provider.py"
- from web3 import Web3
+PROVIDER_RPC = "INSERT_RPC_URL"
+web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
+```
- PROVIDER_RPC = 'INSERT_RPC_URL'
+!!! note
+ Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
- create_provider(PROVIDER_RPC)
+ ```python
+ PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
```
-1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:
+With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain.
+
+??? code "Fetch last block example"
```python title="fetch_last_block.py"
+ from web3 import Web3
+
+
def main():
try:
- web3 = create_provider(PROVIDER_RPC)
+ PROVIDER_RPC = "https://testnet-passet-hub-eth-rpc.polkadot.io"
+ web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
+ print("Last block: " + str(latest_block))
except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
+ print("Error connecting to Polkadot Hub TestNet: " + str(error))
+
if __name__ == "__main__":
main()
- ```
-
- ??? code "View complete script"
-
- ```python title="fetch_last_block.py"
- from web3 import Web3
-
- def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
-
- PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
-
- def main():
- try:
- web3 = create_provider(PROVIDER_RPC)
- latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
- except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
-
- if __name__ == "__main__":
- main()
- ```
-## Contract Deployment
+ ```
-Before deploying your contracts, make sure you've compiled them and obtained two key files:
+## Sample Storage Contract
-- An ABI (.json) file, which provides a JSON interface describing the contract's functions and how to interact with it.
-- A bytecode (.polkavm) file, which contains the low-level machine code executable on [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} that represents the compiled smart contract ready for blockchain deployment.
+Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the [`py-solc-x`](https://solcx.readthedocs.io/en/latest/){target=\_blank} compiler.
-To follow this guide, you can use the following solidity contract as an example:
+To follow this guide, you can use the following Solidity contract as an example:
```solidity title="Storage.sol"
//SPDX-License-Identifier: MIT
@@ -132,86 +109,156 @@ contract Storage {
}
```
+
+
+After you've compiled the `Storage.sol` contract, you should have:
+
+- **An ABI (`.json`) file**: Provides a JSON interface describing the contract's functions and how to interact with it.
+- **A bytecode (`.bin`) file**: Contains the low-level machine code executable on EVM that represents the compiled smart contract ready for blockchain deployment.
+
+## Contract Deployment
+
To deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:
```python title="deploy.py"
from web3 import Web3
import json
+import time
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
def get_bytecode(contract_name):
try:
- with open(f"{contract_name}.polkavm", 'rb') as file:
- return '0x' + file.read().hex()
+ with open(f"{contract_name}.bin", "r") as file:
+ bytecode = file.read().strip()
+ return bytecode if bytecode.startswith("0x") else f"0x{bytecode}"
except Exception as error:
print(f"❌ Could not find bytecode for contract {contract_name}: {error}")
raise error
-async def deploy(config):
+
+def deploy_with_retry(config, max_retries=3):
+ """Deploy with retry logic for RPC errors"""
+ for attempt in range(max_retries):
+ try:
+ return deploy(config)
+ except Exception as error:
+ error_str = str(error)
+ if (
+ "500" in error_str
+ or "Internal Server Error" in error_str
+ or "Connection" in error_str
+ ):
+ if attempt < max_retries - 1:
+ wait_time = (attempt + 1) * 3
+ print(
+ f"RPC error, retrying in {wait_time} seconds... (attempt {attempt + 1}/{max_retries})"
+ )
+ time.sleep(wait_time)
+ continue
+ raise error
+
+
+def deploy(config):
try:
- # Initialize Web3 with RPC URL
- web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+ # Initialize Web3 with RPC URL and longer timeout
+ web3 = Web3(
+ Web3.HTTPProvider(config["rpc_url"], request_kwargs={"timeout": 120})
+ )
+
# Prepare account
- account = web3.eth.account.from_key(config["private_key"])
- print(f"address: {account.address}")
-
- # Load ABI
- abi = get_abi('Storage')
-
+ formatted_private_key = (
+ config["private_key"]
+ if config["private_key"].startswith("0x")
+ else f"0x{config['private_key']}"
+ )
+ account = web3.eth.account.from_key(formatted_private_key)
+ print(f"Deploying from address: {account.address}")
+
+ # Load ABI and bytecode
+ abi = get_abi("Storage")
+ bytecode = get_bytecode("Storage")
+ print(f"Bytecode length: {len(bytecode)}")
+
# Create contract instance
- contract = web3.eth.contract(abi=abi, bytecode=get_bytecode('Storage'))
-
- # Get current nonce
+ contract = web3.eth.contract(abi=abi, bytecode=bytecode)
+
+ # Get current nonce (this will test the connection)
+ print("Getting nonce...")
nonce = web3.eth.get_transaction_count(account.address)
-
- # Prepare deployment transaction
- transaction = {
- 'from': account.address,
- 'nonce': nonce,
- }
-
- # Build and sign transaction
- construct_txn = contract.constructor().build_transaction(transaction)
- signed_txn = web3.eth.account.sign_transaction(construct_txn, private_key=config["private_key"])
-
+ print(f"Nonce: {nonce}")
+
+ # Estimate gas
+ print("Estimating gas...")
+ gas_estimate = web3.eth.estimate_gas(
+ {"from": account.address, "data": bytecode}
+ )
+ print(f"Estimated gas: {gas_estimate}")
+
+ # Get gas price
+ print("Getting gas price...")
+ gas_price = web3.eth.gas_price
+ print(f"Gas price: {web3.from_wei(gas_price, 'gwei')} gwei")
+
+ # Build deployment transaction
+ print("Building transaction...")
+ construct_txn = contract.constructor().build_transaction(
+ {
+ "from": account.address,
+ "nonce": nonce,
+ "gas": gas_estimate,
+ "gasPrice": gas_price,
+ }
+ )
+
+ # Sign transaction
+ print("Signing transaction...")
+ signed_txn = web3.eth.account.sign_transaction(
+ construct_txn, private_key=formatted_private_key
+ )
+
# Send transaction
+ print("Sending transaction...")
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for transaction receipt
- tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
+ print("Waiting for transaction receipt...")
+ tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
contract_address = tx_receipt.contractAddress
-
- # Log and return contract details
- print(f"Contract deployed at: {contract_address}")
+
+ # Log results
+ print(f"✅ Contract deployed at: {contract_address}")
+ print(f"Gas used: {tx_receipt.gasUsed}")
+ print(f"Block number: {tx_receipt.blockNumber}")
+
return web3.eth.contract(address=contract_address, abi=abi)
-
+
except Exception as error:
- print('Deployment failed:', error)
+ print(f"❌ Deployment failed: {error}")
raise error
+
if __name__ == "__main__":
- # Example usage
- import asyncio
-
deployment_config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
}
-
- asyncio.run(deploy(deployment_config))
+
+ deploy_with_retry(deployment_config)
+
```
!!!warning
- Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead.
+ Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds.
## Interact with the Contract
@@ -221,119 +268,89 @@ After deployment, interact with your contract using Web3.py methods. The example
from web3 import Web3
import json
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
async def update_storage(config):
try:
# Initialize Web3 with RPC URL
web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+
# Prepare account
account = web3.eth.account.from_key(config["private_key"])
-
+
# Load ABI
- abi = get_abi('Storage')
-
+ abi = get_abi("Storage")
+
# Create contract instance
contract = web3.eth.contract(address=config["contract_address"], abi=abi)
-
+
# Get initial value
initial_value = contract.functions.storedNumber().call()
- print('Current stored value:', initial_value)
-
+ print("Current stored value:", initial_value)
+
# Get current nonce
nonce = web3.eth.get_transaction_count(account.address)
-
+
# Prepare transaction
- transaction = contract.functions.setNumber(1).build_transaction({
- 'from': account.address,
- 'nonce': nonce
- })
-
+ transaction = contract.functions.setNumber(1).build_transaction(
+ {"from": account.address, "nonce": nonce}
+ )
+
# Sign transaction
- signed_txn = web3.eth.account.sign_transaction(transaction, private_key=config["private_key"])
-
+ signed_txn = web3.eth.account.sign_transaction(
+ transaction, private_key=config["private_key"]
+ )
+
# Send transaction
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for receipt
receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
-
+
# Get updated value
new_value = contract.functions.storedNumber().call()
- print('New stored value:', new_value)
-
+ print("New stored value:", new_value)
+
return receipt
-
+
except Exception as error:
- print('Update failed:', error)
+ print("Update failed:", error)
raise error
+
if __name__ == "__main__":
# Example usage
import asyncio
-
+
config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
"contract_address": "INSERT_CONTRACT_ADDRESS",
}
-
+
asyncio.run(update_storage(config))
+
```
## Where to Go Next
-Now that you have the foundation for using Web3.py with Polkadot Hub, consider exploring:
-
--
External __Advanced Web3.py Features__
-
- ---
- Explore Web3.py's documentation:
-
- - [:octicons-arrow-right-24: Middleware](https://web3py.readthedocs.io/en/stable/middleware.html){target=\_blank}
- - [:octicons-arrow-right-24: Filters & Events](https://web3py.readthedocs.io/en/stable/filters.html){target=\_blank}
- - [:octicons-arrow-right-24: ENS](https://web3py.readthedocs.io/en/stable/ens_overview.html){target=\_blank}
-
-
--
External __Testing Frameworks__
-
- ---
- Integrate Web3.py with Python testing frameworks:
-
-
- - [:octicons-arrow-right-24: Pytest](https://docs.pytest.org/){target=\_blank}
- - [:octicons-arrow-right-24: Brownie](https://eth-brownie.readthedocs.io/){target=\_blank}
-
-
--
External __Transaction Management__
+-
External __Web3.py Docs__
---
- Learn advanced transaction handling:
-
-
- - [:octicons-arrow-right-24: Gas Strategies](https://web3py.readthedocs.io/en/stable/gas_price.html){target=\_blank}
- - [:octicons-arrow-right-24: Account Management](https://web3py.readthedocs.io/en/stable/web3.eth.account.html){target=\_blank}
-
--
External __Building dApps__
-
- ---
- Combine Web3.py with these frameworks to create full-stack applications:
+ Explore the Web3.py documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
-
- - [:octicons-arrow-right-24: Flask](https://flask.palletsprojects.com/){target=\_blank}
- - [:octicons-arrow-right-24: Django](https://www.djangoproject.com/){target=\_blank}
- - [:octicons-arrow-right-24: FastAPI](https://fastapi.tiangolo.com/){target=\_blank}
-
+ [:octicons-arrow-right-24: Get Started](https://web3py.readthedocs.io/en/stable/){target=\_blank}
diff --git a/.ai/site-index.json b/.ai/site-index.json
index 2fe21850a..481655041 100644
--- a/.ai/site-index.json
+++ b/.ai/site-index.json
@@ -5401,12 +5401,12 @@
}
],
"stats": {
- "chars": 20325,
- "words": 2290,
+ "chars": 20077,
+ "words": 2252,
"headings": 12,
- "estimated_token_count_total": 4600
+ "estimated_token_count_total": 4530
},
- "hash": "sha256:7cf1e07d1b8ef4e7b893398976907159a932f23f708d4e1d7ac1d09b80881787",
+ "hash": "sha256:7e3d9a39fafd48ef71f23b07d20f7fb5572ba67e06fcbe6a199fe0468af6dbca",
"token_estimator": "heuristic-v1"
},
{
@@ -5419,7 +5419,7 @@
],
"raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md",
"html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-py/",
- "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction",
+ "preview": "Interacting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols.",
"outline": [
{
"depth": 2,
@@ -5436,6 +5436,11 @@
"title": "Set Up the Web3 Provider",
"anchor": "set-up-the-web3-provider"
},
+ {
+ "depth": 2,
+ "title": "Sample Storage Contract",
+ "anchor": "sample-storage-contract"
+ },
{
"depth": 2,
"title": "Contract Deployment",
@@ -5453,12 +5458,12 @@
}
],
"stats": {
- "chars": 11627,
- "words": 1333,
- "headings": 6,
- "estimated_token_count_total": 2509
+ "chars": 11372,
+ "words": 1282,
+ "headings": 7,
+ "estimated_token_count_total": 2355
},
- "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e",
+ "hash": "sha256:429ebcf91cf74b12b1e0981f1d75aefd13b6d94ebd08699e227ea91cddcb0e23",
"token_estimator": "heuristic-v1"
},
{
diff --git a/.snippets/code/smart-contracts/libraries/web3-py/connect_to_provider.py b/.snippets/code/smart-contracts/libraries/web3-py/connect_to_provider.py
index 4306128f6..8fffb3733 100644
--- a/.snippets/code/smart-contracts/libraries/web3-py/connect_to_provider.py
+++ b/.snippets/code/smart-contracts/libraries/web3-py/connect_to_provider.py
@@ -1,9 +1,4 @@
from web3 import Web3
-def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
-
-PROVIDER_RPC = 'INSERT_RPC_URL'
-
-create_provider(PROVIDER_RPC)
\ No newline at end of file
+PROVIDER_RPC = "INSERT_RPC_URL"
+web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
diff --git a/.snippets/code/smart-contracts/libraries/web3-py/deploy.py b/.snippets/code/smart-contracts/libraries/web3-py/deploy.py
index 9793d2f03..531908dea 100644
--- a/.snippets/code/smart-contracts/libraries/web3-py/deploy.py
+++ b/.snippets/code/smart-contracts/libraries/web3-py/deploy.py
@@ -1,73 +1,133 @@
from web3 import Web3
import json
+import time
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
def get_bytecode(contract_name):
try:
- with open(f"{contract_name}.polkavm", 'rb') as file:
- return '0x' + file.read().hex()
+ with open(f"{contract_name}.bin", "r") as file:
+ bytecode = file.read().strip()
+ return bytecode if bytecode.startswith("0x") else f"0x{bytecode}"
except Exception as error:
print(f"❌ Could not find bytecode for contract {contract_name}: {error}")
raise error
-async def deploy(config):
+
+def deploy_with_retry(config, max_retries=3):
+ """Deploy with retry logic for RPC errors"""
+ for attempt in range(max_retries):
+ try:
+ return deploy(config)
+ except Exception as error:
+ error_str = str(error)
+ if (
+ "500" in error_str
+ or "Internal Server Error" in error_str
+ or "Connection" in error_str
+ ):
+ if attempt < max_retries - 1:
+ wait_time = (attempt + 1) * 3
+ print(
+ f"RPC error, retrying in {wait_time} seconds... (attempt {attempt + 1}/{max_retries})"
+ )
+ time.sleep(wait_time)
+ continue
+ raise error
+
+
+def deploy(config):
try:
- # Initialize Web3 with RPC URL
- web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+ # Initialize Web3 with RPC URL and longer timeout
+ web3 = Web3(
+ Web3.HTTPProvider(config["rpc_url"], request_kwargs={"timeout": 120})
+ )
+
# Prepare account
- account = web3.eth.account.from_key(config["private_key"])
- print(f"address: {account.address}")
-
- # Load ABI
- abi = get_abi('Storage')
-
+ formatted_private_key = (
+ config["private_key"]
+ if config["private_key"].startswith("0x")
+ else f"0x{config['private_key']}"
+ )
+ account = web3.eth.account.from_key(formatted_private_key)
+ print(f"Deploying from address: {account.address}")
+
+ # Load ABI and bytecode
+ abi = get_abi("Storage")
+ bytecode = get_bytecode("Storage")
+ print(f"Bytecode length: {len(bytecode)}")
+
# Create contract instance
- contract = web3.eth.contract(abi=abi, bytecode=get_bytecode('Storage'))
-
- # Get current nonce
+ contract = web3.eth.contract(abi=abi, bytecode=bytecode)
+
+ # Get current nonce (this will test the connection)
+ print("Getting nonce...")
nonce = web3.eth.get_transaction_count(account.address)
-
- # Prepare deployment transaction
- transaction = {
- 'from': account.address,
- 'nonce': nonce,
- }
-
- # Build and sign transaction
- construct_txn = contract.constructor().build_transaction(transaction)
- signed_txn = web3.eth.account.sign_transaction(construct_txn, private_key=config["private_key"])
-
+ print(f"Nonce: {nonce}")
+
+ # Estimate gas
+ print("Estimating gas...")
+ gas_estimate = web3.eth.estimate_gas(
+ {"from": account.address, "data": bytecode}
+ )
+ print(f"Estimated gas: {gas_estimate}")
+
+ # Get gas price
+ print("Getting gas price...")
+ gas_price = web3.eth.gas_price
+ print(f"Gas price: {web3.from_wei(gas_price, 'gwei')} gwei")
+
+ # Build deployment transaction
+ print("Building transaction...")
+ construct_txn = contract.constructor().build_transaction(
+ {
+ "from": account.address,
+ "nonce": nonce,
+ "gas": gas_estimate,
+ "gasPrice": gas_price,
+ }
+ )
+
+ # Sign transaction
+ print("Signing transaction...")
+ signed_txn = web3.eth.account.sign_transaction(
+ construct_txn, private_key=formatted_private_key
+ )
+
# Send transaction
+ print("Sending transaction...")
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for transaction receipt
- tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
+ print("Waiting for transaction receipt...")
+ tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
contract_address = tx_receipt.contractAddress
-
- # Log and return contract details
- print(f"Contract deployed at: {contract_address}")
+
+ # Log results
+ print(f"✅ Contract deployed at: {contract_address}")
+ print(f"Gas used: {tx_receipt.gasUsed}")
+ print(f"Block number: {tx_receipt.blockNumber}")
+
return web3.eth.contract(address=contract_address, abi=abi)
-
+
except Exception as error:
- print('Deployment failed:', error)
+ print(f"❌ Deployment failed: {error}")
raise error
+
if __name__ == "__main__":
- # Example usage
- import asyncio
-
deployment_config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
}
-
- asyncio.run(deploy(deployment_config))
\ No newline at end of file
+
+ deploy_with_retry(deployment_config)
diff --git a/.snippets/code/smart-contracts/libraries/web3-py/fetch_last_block.py b/.snippets/code/smart-contracts/libraries/web3-py/fetch_last_block.py
index ff6ab63ed..c5fe6ea48 100644
--- a/.snippets/code/smart-contracts/libraries/web3-py/fetch_last_block.py
+++ b/.snippets/code/smart-contracts/libraries/web3-py/fetch_last_block.py
@@ -1,18 +1,15 @@
from web3 import Web3
-def create_provider(rpc_url):
- web3 = Web3(Web3.HTTPProvider(rpc_url))
- return web3
-
-PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
def main():
try:
- web3 = create_provider(PROVIDER_RPC)
+ PROVIDER_RPC = "https://testnet-passet-hub-eth-rpc.polkadot.io"
+ web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))
latest_block = web3.eth.block_number
- print('Last block: ' + str(latest_block))
+ print("Last block: " + str(latest_block))
except Exception as error:
- print('Error connecting to Polkadot Hub TestNet: ' + str(error))
+ print("Error connecting to Polkadot Hub TestNet: " + str(error))
+
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
diff --git a/.snippets/code/smart-contracts/libraries/web3-py/update_storage.py b/.snippets/code/smart-contracts/libraries/web3-py/update_storage.py
index afd047e0b..4d06bec26 100644
--- a/.snippets/code/smart-contracts/libraries/web3-py/update_storage.py
+++ b/.snippets/code/smart-contracts/libraries/web3-py/update_storage.py
@@ -1,69 +1,73 @@
from web3 import Web3
import json
+
def get_abi(contract_name):
try:
- with open(f"{contract_name}.json", 'r') as file:
+ with open(f"{contract_name}.json", "r") as file:
return json.load(file)
except Exception as error:
print(f"❌ Could not find ABI for contract {contract_name}: {error}")
raise error
+
async def update_storage(config):
try:
# Initialize Web3 with RPC URL
web3 = Web3(Web3.HTTPProvider(config["rpc_url"]))
-
+
# Prepare account
account = web3.eth.account.from_key(config["private_key"])
-
+
# Load ABI
- abi = get_abi('Storage')
-
+ abi = get_abi("Storage")
+
# Create contract instance
contract = web3.eth.contract(address=config["contract_address"], abi=abi)
-
+
# Get initial value
initial_value = contract.functions.storedNumber().call()
- print('Current stored value:', initial_value)
-
+ print("Current stored value:", initial_value)
+
# Get current nonce
nonce = web3.eth.get_transaction_count(account.address)
-
+
# Prepare transaction
- transaction = contract.functions.setNumber(1).build_transaction({
- 'from': account.address,
- 'nonce': nonce
- })
-
+ transaction = contract.functions.setNumber(1).build_transaction(
+ {"from": account.address, "nonce": nonce}
+ )
+
# Sign transaction
- signed_txn = web3.eth.account.sign_transaction(transaction, private_key=config["private_key"])
-
+ signed_txn = web3.eth.account.sign_transaction(
+ transaction, private_key=config["private_key"]
+ )
+
# Send transaction
tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(f"Transaction hash: {tx_hash.hex()}")
-
+
# Wait for receipt
receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
-
+
# Get updated value
new_value = contract.functions.storedNumber().call()
- print('New stored value:', new_value)
-
+ print("New stored value:", new_value)
+
return receipt
-
+
except Exception as error:
- print('Update failed:', error)
+ print("Update failed:", error)
raise error
+
if __name__ == "__main__":
# Example usage
import asyncio
-
+
config = {
"rpc_url": "INSERT_RPC_URL",
"private_key": "INSERT_PRIVATE_KEY",
"contract_address": "INSERT_CONTRACT_ADDRESS",
}
-
- asyncio.run(update_storage(config))
\ No newline at end of file
+
+ asyncio.run(update_storage(config))
diff --git a/llms-full.jsonl b/llms-full.jsonl
index c59e67fab..d646ea880 100644
--- a/llms-full.jsonl
+++ b/llms-full.jsonl
@@ -726,20 +726,21 @@
{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 857, "end_char": 1213, "estimated_token_count": 110, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have the following installed:\n\n- **Node.js**: v22.13.1 or later, check the [Node.js installation guide](https://nodejs.org/en/download/current/){target=\\_blank}.\n- **npm**: v6.13.4 or later (comes bundled with Node.js).\n- **Solidity**: This guide uses Solidity `^0.8.9` for smart contract development."}
{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 2, "depth": 2, "title": "Project Structure", "anchor": "project-structure", "start_char": 1213, "end_char": 1691, "estimated_token_count": 135, "token_estimator": "heuristic-v1", "text": "## Project Structure\n\nThis project organizes contracts, scripts, and compiled artifacts for easy development and deployment.\n\n```text\nweb3js-project\n├── contracts\n│ ├── Storage.sol\n├── scripts\n│ ├── connectToProvider.js\n│ ├── fetchLastBlock.js\n│ ├── compile.js\n│ ├── deploy.js\n│ ├── updateStorage.js\n├── abis\n│ ├── Storage.json\n├── artifacts\n│ ├── Storage.bin\n├── contract-address.json\n├── node_modules/\n├── package.json\n├── package-lock.json\n└── README.md\n```"}
{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 3, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 1691, "end_char": 1910, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\nTo start working with Web3.js, create a new folder and initialize your project by running the following commands in your terminal:\n\n```bash\nmkdir web3js-project\ncd web3js-project\nnpm init -y\n```"}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 4, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 1910, "end_char": 2323, "estimated_token_count": 107, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nNext, run the following command to install the Web3.js library:\n\n```bash\nnpm install web3\n```\n\nAdd the Solidity compiler so you can generate standard EVM bytecode:\n\n```bash\nnpm install --save-dev solc\n```\n\n!!! tip\n The sample scripts use ECMAScript modules. Add `\"type\": \"module\"` to your `package.json` (or rename the files to `.mjs`) so that `node` can run the `import` statements."}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 5, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 2323, "end_char": 4522, "estimated_token_count": 504, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.\n\nTo interact with Polkadot Hub, you must set up a Web3.js provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. In the `scripts` directory of your project, create a file named `connectToProvider.js` and add the following code:\n\n```js title=\"scripts/connectToProvider.js\"\nconst { Web3 } = require('web3');\n\nconst createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n};\n\nconst PROVIDER_RPC = {\n rpc: 'INSERT_RPC_URL',\n chainId: 'INSERT_CHAIN_ID',\n name: 'INSERT_CHAIN_NAME',\n};\n\ncreateProvider(PROVIDER_RPC.rpc);\n\n```\n\n!!! note\n Replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. For example, to connect to Polkadot Hub TestNet's Ethereum RPC instance, you can use the following parameters:\n\n ```js\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet'\n };\n ```\n\nTo connect to the provider, execute:\n\n```bash\nnode scripts/connectToProvider.js\n```\n\nWith the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number.\n\n??? code \"Fetch last block example\"\n\n ```js title=\"scripts/fetchLastBlock.js\"\n const { Web3 } = require('web3');\n\n const createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const main = async () => {\n try {\n const web3 = createProvider(PROVIDER_RPC.rpc);\n const latestBlock = await web3.eth.getBlockNumber();\n console.log('Last block: ' + latestBlock);\n } catch (error) {\n console.error('Error connecting to Polkadot Hub TestNet: ' + error.message);\n }\n };\n\n main();\n\n ```"}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 6, "depth": 2, "title": "Compile Contracts", "anchor": "compile-contracts", "start_char": 4522, "end_char": 4849, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "## Compile Contracts\n\nPolkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js."}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 7, "depth": 3, "title": "Sample Storage Smart Contract", "anchor": "sample-storage-smart-contract", "start_char": 4849, "end_char": 5554, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### Sample Storage Smart Contract\n\nThis example demonstrates compiling a `Storage.sol` Solidity contract for deployment to Polkadot Hub. The contract's functionality stores a number and permits users to update it with a new value.\n\n```solidity title=\"contracts/Storage.sol\"\n//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```"}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 8, "depth": 3, "title": "Compile the Smart Contract", "anchor": "compile-the-smart-contract", "start_char": 5554, "end_char": 9111, "estimated_token_count": 810, "token_estimator": "heuristic-v1", "text": "### Compile the Smart Contract\n\nTo compile this contract, use the following script:\n\n```js title=\"scripts/compile.js\"\nconst solc = require('solc');\nconst { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs');\nconst { basename, join } = require('path');\n\nconst ensureDir = (dirPath) => {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n};\n\nconst compileContract = (solidityFilePath, abiDir, artifactsDir) => {\n try {\n // Read the Solidity file\n const source = readFileSync(solidityFilePath, 'utf8');\n const fileName = basename(solidityFilePath);\n \n // Construct the input object for the Solidity compiler\n const input = {\n language: 'Solidity',\n sources: {\n [fileName]: {\n content: source,\n },\n },\n settings: {\n outputSelection: {\n '*': {\n '*': ['abi', 'evm.bytecode'],\n },\n },\n },\n };\n \n console.log(`Compiling contract: ${fileName}...`);\n \n // Compile the contract\n const output = JSON.parse(solc.compile(JSON.stringify(input)));\n \n // Check for errors\n if (output.errors) {\n const errors = output.errors.filter(error => error.severity === 'error');\n if (errors.length > 0) {\n console.error('Compilation errors:');\n errors.forEach(err => console.error(err.formattedMessage));\n return;\n }\n // Show warnings\n const warnings = output.errors.filter(error => error.severity === 'warning');\n warnings.forEach(warn => console.warn(warn.formattedMessage));\n }\n \n // Ensure output directories exist\n ensureDir(abiDir);\n ensureDir(artifactsDir);\n\n // Process compiled contracts\n for (const [sourceFile, contracts] of Object.entries(output.contracts)) {\n for (const [contractName, contract] of Object.entries(contracts)) {\n console.log(`Compiled contract: ${contractName}`);\n \n // Write the ABI\n const abiPath = join(abiDir, `${contractName}.json`);\n writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));\n console.log(`ABI saved to ${abiPath}`);\n \n // Write the bytecode\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n writeFileSync(bytecodePath, contract.evm.bytecode.object);\n console.log(`Bytecode saved to ${bytecodePath}`);\n }\n }\n } catch (error) {\n console.error('Error compiling contracts:', error);\n }\n};\n\nconst solidityFilePath = join(__dirname, '../contracts/Storage.sol');\nconst abiDir = join(__dirname, '../abis');\nconst artifactsDir = join(__dirname, '../artifacts');\n\ncompileContract(solidityFilePath, abiDir, artifactsDir);\n```\n\n!!! note \n The script above is tailored to the `Storage.sol` contract. It can be adjusted for other contracts by changing the file name or modifying the ABI and bytecode paths.\n\nThe ABI (Application Binary Interface) is a JSON representation of your contract's functions, events, and their parameters. It serves as the interface between your JavaScript code and the deployed smart contract, allowing your application to know how to format function calls and interpret returned data.\n\nExecute the script above by running:\n\n```bash\nnode scripts/compile.js\n```\n\nAfter executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section."}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 9, "depth": 2, "title": "Deploy the Compiled Contract", "anchor": "deploy-the-compiled-contract", "start_char": 9111, "end_char": 17195, "estimated_token_count": 1801, "token_estimator": "heuristic-v1", "text": "## Deploy the Compiled Contract\n\nTo deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction.\n\nYou can create a `deploy.js` script in the `scripts` directory of your project to achieve this. The deployment script can be divided into key components:\n\n1. Set up the required imports and utilities:\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n ```\n\n2. Create a provider to connect to Polkadot Hub:\n\n ```js title=\"scripts/deploy.js\"\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n ```\n\n3. Set up functions to read contract artifacts:\n\n ```js title=\"scripts/deploy.js\"\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n ```\n\n4. Create the main deployment function:\n\n ```js title=\"scripts/deploy.js\"\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n ```\n\n5. Configure and execute the deployment:\n\n ```js title=\"scripts/deploy.js\"\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n ```\n\n !!! note\n\n A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**.\n\n Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key.\n\n??? code \"View complete script\"\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadot-hub-testnet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n\n\n ```\n\nTo run the script, execute the following command:\n\n```bash\nnode scripts/deploy.js\n```\n\nAfter running this script, your contract will be deployed to Polkadot Hub, and its address will be saved in `contract-address.json` within your project directory. You can use this address for future contract interactions."}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 10, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 17195, "end_char": 19945, "estimated_token_count": 659, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nOnce the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:\n\n```js title=\"scripts/updateStorage.js\"\nconst { readFileSync } = require('fs');\nconst { join } = require('path');\nconst { Web3 } = require('web3');\n\nconst abisDir = join(__dirname, '../abis');\n\nconst getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n};\n\nconst updateStorage = async (config) => {\n try {\n const web3 = new Web3(config.rpcUrl);\n const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n\n const abi = getAbi('Storage');\n const contract = new web3.eth.Contract(abi, config.contractAddress);\n\n const initialValue = await contract.methods.storedNumber().call();\n console.log('Current stored value:', initialValue);\n\n const updateTransaction = contract.methods.setNumber(1);\n const gasEstimate = await updateTransaction.estimateGas({\n from: account.address,\n });\n const gasPrice = await web3.eth.getGasPrice();\n\n const receipt = await updateTransaction.send({\n from: account.address,\n gas: gasEstimate,\n gasPrice: gasPrice,\n });\n\n console.log(`Transaction hash: ${receipt.transactionHash}`);\n\n const newValue = await contract.methods.storedNumber().call();\n console.log('New stored value:', newValue);\n\n return receipt;\n } catch (error) {\n console.error('Update failed:', error);\n throw error;\n }\n};\n\nconst config = {\n rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n privateKey: 'INSERT_PRIVATE_KEY',\n contractAddress: 'INSERT_CONTRACT_ADDRESS',\n};\n\nupdateStorage(config)\n .then((receipt) => console.log('Update successful'))\n .catch((error) => console.error('Update error'));\n```\n\nEnsure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script prints the balance for `ADDRESS_TO_CHECK` before it writes and doubles the stored value, so pick any account you want to monitor.\n\nTo interact with the contract, run:\n\n```bash\nnode scripts/updateStorage.js\n```"}
-{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 11, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 19945, "end_char": 20325, "estimated_token_count": 103, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n\n\n- External __Web3.js Docs__\n\n ---\n\n Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, etc.\n\n [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/)\n\n
"}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 181, "end_char": 605, "estimated_token_count": 83, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteracting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. \n\nThis guide illustrates how to utilize Web3.py for interactions with Polkadot Hub."}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 1, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 605, "end_char": 986, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\n1. To start working with Web3.py, begin by initializing your project:\n\n ```bash\n mkdir web3py-project\n cd web3py-project\n ```\n\n2. Create and activate a virtual environment for your project:\n\n ```bash\n python -m venv venv\n source venv/bin/activate\n ```\n\n3. Next, install the Web3.py library:\n\n ```bash\n pip install web3\n ```"}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 2, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 986, "end_char": 3080, "estimated_token_count": 423, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:\n\n1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:\n\n ```python\n PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'\n ```\n\n The provider connection script should look something like this:\n\n ```python title=\"connect_to_provider.py\"\n from web3 import Web3\n\n def create_provider(rpc_url):\n web3 = Web3(Web3.HTTPProvider(rpc_url))\n return web3\n\n PROVIDER_RPC = 'INSERT_RPC_URL'\n\n create_provider(PROVIDER_RPC)\n ```\n\n1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:\n\n ```python title=\"fetch_last_block.py\"\n def main():\n try:\n web3 = create_provider(PROVIDER_RPC)\n latest_block = web3.eth.block_number\n print('Last block: ' + str(latest_block))\n except Exception as error:\n print('Error connecting to Polkadot Hub TestNet: ' + str(error))\n\n if __name__ == \"__main__\":\n main()\n ```\n\n ??? code \"View complete script\"\n\n ```python title=\"fetch_last_block.py\"\n from web3 import Web3\n\n def create_provider(rpc_url):\n web3 = Web3(Web3.HTTPProvider(rpc_url))\n return web3\n\n PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'\n\n def main():\n try:\n web3 = create_provider(PROVIDER_RPC)\n latest_block = web3.eth.block_number\n print('Last block: ' + str(latest_block))\n except Exception as error:\n print('Error connecting to Polkadot Hub TestNet: ' + str(error))\n\n if __name__ == \"__main__\":\n main()\n ```"}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 3, "depth": 2, "title": "Contract Deployment", "anchor": "contract-deployment", "start_char": 3080, "end_char": 7196, "estimated_token_count": 823, "token_estimator": "heuristic-v1", "text": "## Contract Deployment\n\nBefore deploying your contracts, make sure you've compiled them and obtained two key files:\n\n- An ABI (.json) file, which provides a JSON interface describing the contract's functions and how to interact with it.\n- A bytecode (.polkavm) file, which contains the low-level machine code executable on [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\\_blank} that represents the compiled smart contract ready for blockchain deployment.\n\nTo follow this guide, you can use the following solidity contract as an example:\n\n```solidity title=\"Storage.sol\"\n//SPDX-License-Identifier: MIT\n\n// Solidity files have to start with this pragma.\n// It will be used by the Solidity compiler to validate its version.\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```\n\nTo deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:\n\n```python title=\"deploy.py\"\nfrom web3 import Web3\nimport json\n\ndef get_abi(contract_name):\n try:\n with open(f\"{contract_name}.json\", 'r') as file:\n return json.load(file)\n except Exception as error:\n print(f\"❌ Could not find ABI for contract {contract_name}: {error}\")\n raise error\n\ndef get_bytecode(contract_name):\n try:\n with open(f\"{contract_name}.polkavm\", 'rb') as file:\n return '0x' + file.read().hex()\n except Exception as error:\n print(f\"❌ Could not find bytecode for contract {contract_name}: {error}\")\n raise error\n\nasync def deploy(config):\n try:\n # Initialize Web3 with RPC URL\n web3 = Web3(Web3.HTTPProvider(config[\"rpc_url\"]))\n \n # Prepare account\n account = web3.eth.account.from_key(config[\"private_key\"])\n print(f\"address: {account.address}\")\n \n # Load ABI\n abi = get_abi('Storage')\n \n # Create contract instance\n contract = web3.eth.contract(abi=abi, bytecode=get_bytecode('Storage'))\n \n # Get current nonce\n nonce = web3.eth.get_transaction_count(account.address)\n \n # Prepare deployment transaction\n transaction = {\n 'from': account.address,\n 'nonce': nonce,\n }\n \n # Build and sign transaction\n construct_txn = contract.constructor().build_transaction(transaction)\n signed_txn = web3.eth.account.sign_transaction(construct_txn, private_key=config[\"private_key\"])\n \n # Send transaction\n tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)\n print(f\"Transaction hash: {tx_hash.hex()}\")\n \n # Wait for transaction receipt\n tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)\n contract_address = tx_receipt.contractAddress\n \n # Log and return contract details\n print(f\"Contract deployed at: {contract_address}\")\n return web3.eth.contract(address=contract_address, abi=abi)\n \n except Exception as error:\n print('Deployment failed:', error)\n raise error\n\nif __name__ == \"__main__\":\n # Example usage\n import asyncio\n \n deployment_config = {\n \"rpc_url\": \"INSERT_RPC_URL\",\n \"private_key\": \"INSERT_PRIVATE_KEY\",\n }\n \n asyncio.run(deploy(deployment_config))\n```\n\n!!!warning\n Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead."}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 4, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 7196, "end_char": 9653, "estimated_token_count": 464, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nAfter deployment, interact with your contract using Web3.py methods. The example below demonstrates how to set and retrieve a number. Be sure to replace the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` placeholders with your specific values:\n\n```python title=\"update_storage.py\"\nfrom web3 import Web3\nimport json\n\ndef get_abi(contract_name):\n try:\n with open(f\"{contract_name}.json\", 'r') as file:\n return json.load(file)\n except Exception as error:\n print(f\"❌ Could not find ABI for contract {contract_name}: {error}\")\n raise error\n\nasync def update_storage(config):\n try:\n # Initialize Web3 with RPC URL\n web3 = Web3(Web3.HTTPProvider(config[\"rpc_url\"]))\n \n # Prepare account\n account = web3.eth.account.from_key(config[\"private_key\"])\n \n # Load ABI\n abi = get_abi('Storage')\n \n # Create contract instance\n contract = web3.eth.contract(address=config[\"contract_address\"], abi=abi)\n \n # Get initial value\n initial_value = contract.functions.storedNumber().call()\n print('Current stored value:', initial_value)\n \n # Get current nonce\n nonce = web3.eth.get_transaction_count(account.address)\n \n # Prepare transaction\n transaction = contract.functions.setNumber(1).build_transaction({\n 'from': account.address,\n 'nonce': nonce\n })\n \n # Sign transaction\n signed_txn = web3.eth.account.sign_transaction(transaction, private_key=config[\"private_key\"])\n \n # Send transaction\n tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)\n print(f\"Transaction hash: {tx_hash.hex()}\")\n \n # Wait for receipt\n receipt = web3.eth.wait_for_transaction_receipt(tx_hash)\n \n # Get updated value\n new_value = contract.functions.storedNumber().call()\n print('New stored value:', new_value)\n \n return receipt\n \n except Exception as error:\n print('Update failed:', error)\n raise error\n\nif __name__ == \"__main__\":\n # Example usage\n import asyncio\n \n config = {\n \"rpc_url\": \"INSERT_RPC_URL\",\n \"private_key\": \"INSERT_PRIVATE_KEY\",\n \"contract_address\": \"INSERT_CONTRACT_ADDRESS\",\n }\n \n asyncio.run(update_storage(config))\n```"}
-{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 9653, "end_char": 11627, "estimated_token_count": 628, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you have the foundation for using Web3.py with Polkadot Hub, consider exploring:\n\n\n\n-
External __Advanced Web3.py Features__\n \n ---\n Explore Web3.py's documentation:\n
\n - [:octicons-arrow-right-24: Middleware](https://web3py.readthedocs.io/en/stable/middleware.html){target=\\_blank}
\n - [:octicons-arrow-right-24: Filters & Events](https://web3py.readthedocs.io/en/stable/filters.html){target=\\_blank}
\n - [:octicons-arrow-right-24: ENS](https://web3py.readthedocs.io/en/stable/ens_overview.html){target=\\_blank}
\n
\n\n-
External __Testing Frameworks__\n\n ---\n Integrate Web3.py with Python testing frameworks:\n\n
\n - [:octicons-arrow-right-24: Pytest](https://docs.pytest.org/){target=\\_blank}
\n - [:octicons-arrow-right-24: Brownie](https://eth-brownie.readthedocs.io/){target=\\_blank}
\n
\n\n-
External __Transaction Management__\n\n ---\n Learn advanced transaction handling:\n\n
\n - [:octicons-arrow-right-24: Gas Strategies](https://web3py.readthedocs.io/en/stable/gas_price.html){target=\\_blank}
\n - [:octicons-arrow-right-24: Account Management](https://web3py.readthedocs.io/en/stable/web3.eth.account.html){target=\\_blank}
\n
\n\n-
External __Building dApps__\n\n ---\n Combine Web3.py with these frameworks to create full-stack applications:\n\n
\n - [:octicons-arrow-right-24: Flask](https://flask.palletsprojects.com/){target=\\_blank}
\n - [:octicons-arrow-right-24: Django](https://www.djangoproject.com/){target=\\_blank}
\n - [:octicons-arrow-right-24: FastAPI](https://fastapi.tiangolo.com/){target=\\_blank}
\n
\n\n
"}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 4, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 1910, "end_char": 2141, "estimated_token_count": 55, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nNext, run the following command to install the Web3.js library:\n\n```bash\nnpm install web3\n```\n\nAdd the Solidity compiler so you can generate standard EVM bytecode:\n\n```bash\nnpm install --save-dev solc\n```"}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 5, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 2141, "end_char": 4335, "estimated_token_count": 500, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe provider configuration is the foundation of any Web3.js application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.\n\nTo interact with Polkadot Hub, you must set up a Web3.js provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. In the `scripts` directory of your project, create a file named `connectToProvider.js` and add the following code:\n\n```js title=\"scripts/connectToProvider.js\"\nconst { Web3 } = require('web3');\n\nconst createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n};\n\nconst PROVIDER_RPC = {\n rpc: 'INSERT_RPC_URL',\n chainId: 'INSERT_CHAIN_ID',\n name: 'INSERT_CHAIN_NAME',\n};\n\ncreateProvider(PROVIDER_RPC.rpc);\n\n```\n\n!!! note\n Replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. For example, to connect to Polkadot Hub TestNet's Ethereum RPC instance, you can use the following parameters:\n\n ```js\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadot-hub-testnet'\n };\n ```\n\nTo connect to the provider, execute:\n\n```bash\nnode scripts/connectToProvider.js\n```\n\nWith the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number.\n\n??? code \"Fetch last block example\"\n\n ```js title=\"scripts/fetchLastBlock.js\"\n const { Web3 } = require('web3');\n\n const createProvider = (rpcUrl) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const PROVIDER_RPC = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n chainId: 420420422,\n name: 'polkadotTestNet',\n };\n\n const main = async () => {\n try {\n const web3 = createProvider(PROVIDER_RPC.rpc);\n const latestBlock = await web3.eth.getBlockNumber();\n console.log('Last block: ' + latestBlock);\n } catch (error) {\n console.error('Error connecting to Polkadot Hub TestNet: ' + error.message);\n }\n };\n\n main();\n\n ```"}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 6, "depth": 2, "title": "Compile Contracts", "anchor": "compile-contracts", "start_char": 4335, "end_char": 4662, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "## Compile Contracts\n\nPolkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the upstream [`solc`](https://www.npmjs.com/package/solc){target=\\_blank} compiler. The resulting artifacts work with any EVM-compatible toolchain and can be deployed through Web3.js."}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 7, "depth": 3, "title": "Sample Storage Smart Contract", "anchor": "sample-storage-smart-contract", "start_char": 4662, "end_char": 5367, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### Sample Storage Smart Contract\n\nThis example demonstrates compiling a `Storage.sol` Solidity contract for deployment to Polkadot Hub. The contract's functionality stores a number and permits users to update it with a new value.\n\n```solidity title=\"contracts/Storage.sol\"\n//SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```"}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 8, "depth": 3, "title": "Compile the Smart Contract", "anchor": "compile-the-smart-contract", "start_char": 5367, "end_char": 8924, "estimated_token_count": 810, "token_estimator": "heuristic-v1", "text": "### Compile the Smart Contract\n\nTo compile this contract, use the following script:\n\n```js title=\"scripts/compile.js\"\nconst solc = require('solc');\nconst { readFileSync, writeFileSync, mkdirSync, existsSync } = require('fs');\nconst { basename, join } = require('path');\n\nconst ensureDir = (dirPath) => {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n};\n\nconst compileContract = (solidityFilePath, abiDir, artifactsDir) => {\n try {\n // Read the Solidity file\n const source = readFileSync(solidityFilePath, 'utf8');\n const fileName = basename(solidityFilePath);\n \n // Construct the input object for the Solidity compiler\n const input = {\n language: 'Solidity',\n sources: {\n [fileName]: {\n content: source,\n },\n },\n settings: {\n outputSelection: {\n '*': {\n '*': ['abi', 'evm.bytecode'],\n },\n },\n },\n };\n \n console.log(`Compiling contract: ${fileName}...`);\n \n // Compile the contract\n const output = JSON.parse(solc.compile(JSON.stringify(input)));\n \n // Check for errors\n if (output.errors) {\n const errors = output.errors.filter(error => error.severity === 'error');\n if (errors.length > 0) {\n console.error('Compilation errors:');\n errors.forEach(err => console.error(err.formattedMessage));\n return;\n }\n // Show warnings\n const warnings = output.errors.filter(error => error.severity === 'warning');\n warnings.forEach(warn => console.warn(warn.formattedMessage));\n }\n \n // Ensure output directories exist\n ensureDir(abiDir);\n ensureDir(artifactsDir);\n\n // Process compiled contracts\n for (const [sourceFile, contracts] of Object.entries(output.contracts)) {\n for (const [contractName, contract] of Object.entries(contracts)) {\n console.log(`Compiled contract: ${contractName}`);\n \n // Write the ABI\n const abiPath = join(abiDir, `${contractName}.json`);\n writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2));\n console.log(`ABI saved to ${abiPath}`);\n \n // Write the bytecode\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n writeFileSync(bytecodePath, contract.evm.bytecode.object);\n console.log(`Bytecode saved to ${bytecodePath}`);\n }\n }\n } catch (error) {\n console.error('Error compiling contracts:', error);\n }\n};\n\nconst solidityFilePath = join(__dirname, '../contracts/Storage.sol');\nconst abiDir = join(__dirname, '../abis');\nconst artifactsDir = join(__dirname, '../artifacts');\n\ncompileContract(solidityFilePath, abiDir, artifactsDir);\n```\n\n!!! note \n The script above is tailored to the `Storage.sol` contract. It can be adjusted for other contracts by changing the file name or modifying the ABI and bytecode paths.\n\nThe ABI (Application Binary Interface) is a JSON representation of your contract's functions, events, and their parameters. It serves as the interface between your JavaScript code and the deployed smart contract, allowing your application to know how to format function calls and interpret returned data.\n\nExecute the script above by running:\n\n```bash\nnode scripts/compile.js\n```\n\nAfter executing the script, the Solidity contract is compiled into standard EVM bytecode. The ABI and bytecode are saved into files with `.json` and `.bin` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section."}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 9, "depth": 2, "title": "Deploy the Compiled Contract", "anchor": "deploy-the-compiled-contract", "start_char": 8924, "end_char": 16998, "estimated_token_count": 1793, "token_estimator": "heuristic-v1", "text": "## Deploy the Compiled Contract\n\nTo deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction.\n\nYou can create a `deploy.js` script in the `scripts` directory of your project to achieve this. The deployment script can be divided into key components:\n\n1. Set up the required imports and utilities:\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n ```\n\n2. Create a provider to connect to Polkadot Hub:\n\n ```js title=\"scripts/deploy.js\"\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n ```\n\n3. Set up functions to read contract artifacts:\n\n ```js title=\"scripts/deploy.js\"\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n ```\n\n4. Create the main deployment function:\n\n ```js title=\"scripts/deploy.js\"\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n ```\n\n5. Configure and execute the deployment:\n\n ```js title=\"scripts/deploy.js\"\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadotTestNet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n ```\n\n !!! note\n\n A private key is a hexadecimal string that is used to sign and pay for the deployment transaction. **Always keep your private key secure and never share it publicly**.\n\n Ensure to replace the `INSERT_PRIVATE_KEY` placeholder with your actual private key.\n\n??? code \"View complete script\"\n\n ```js title=\"scripts/deploy.js\"\n const { writeFileSync, existsSync, readFileSync } = require('fs');\n const { join } = require('path');\n const { Web3 } = require('web3');\n\n const scriptsDir = __dirname;\n const abisDir = join(__dirname, '../abis');\n const artifactsDir = join(__dirname, '../artifacts');\n\n const createProvider = (rpcUrl, chainId, chainName) => {\n const web3 = new Web3(rpcUrl);\n return web3;\n };\n\n const getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const getByteCode = (contractName) => {\n try {\n const bytecodePath = join(artifactsDir, `${contractName}.bin`);\n const bytecode = readFileSync(bytecodePath, 'utf8').trim();\n return bytecode.startsWith('0x') ? bytecode : `0x${bytecode}`;\n } catch (error) {\n console.error(\n `Could not find bytecode for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n };\n\n const deployContract = async (contractName, privateKey, providerConfig) => {\n console.log(`Deploying ${contractName}...`);\n try {\n const web3 = createProvider(\n providerConfig.rpc,\n providerConfig.chainId,\n providerConfig.name,\n );\n\n const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey : `0x${privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n web3.eth.defaultAccount = account.address;\n\n const abi = getAbi(contractName);\n const bytecode = getByteCode(contractName);\n const contract = new web3.eth.Contract(abi);\n const deployTx = contract.deploy({\n data: bytecode,\n });\n\n const gas = await deployTx.estimateGas();\n const gasPrice = await web3.eth.getGasPrice();\n\n console.log(`Estimated gas: ${gas}`);\n console.log(`Gas price: ${web3.utils.fromWei(gasPrice, 'gwei')} gwei`);\n\n const deployedContract = await deployTx.send({\n from: account.address,\n gas: gas,\n gasPrice: gasPrice,\n });\n\n const address = deployedContract.options.address;\n console.log(`Contract ${contractName} deployed at: ${address}`);\n\n const addressesFile = join(scriptsDir, 'contract-address.json');\n const addresses = existsSync(addressesFile)\n ? JSON.parse(readFileSync(addressesFile, 'utf8'))\n : {};\n\n addresses[contractName] = address;\n writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8');\n } catch (error) {\n console.error(`Failed to deploy contract ${contractName}:`, error);\n }\n };\n\n const providerConfig = {\n rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', // TODO: replace to `https://services.polkadothub-rpc.com/testnet` when ready\n chainId: 420420422,\n name: 'polkadotTestNet',\n };\n\n const privateKey = 'INSERT_PRIVATE_KEY';\n\n deployContract('Storage', privateKey, providerConfig);\n\n\n ```\n\nTo run the script, execute the following command:\n\n```bash\nnode scripts/deploy.js\n```\n\nAfter running this script, your contract will be deployed to Polkadot Hub, and its address will be saved in `contract-address.json` within your project directory. You can use this address for future contract interactions."}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 10, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 16998, "end_char": 19676, "estimated_token_count": 646, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nOnce the contract is deployed, you can interact with it by calling its functions. For example, to read the current stored value and then update it to a new value, you can create a file named `updateStorage.js` in the `scripts` directory of your project and add the following code:\n\n```js title=\"scripts/updateStorage.js\"\nconst { readFileSync } = require('fs');\nconst { join } = require('path');\nconst { Web3 } = require('web3');\n\nconst abisDir = join(__dirname, '../abis');\n\nconst getAbi = (contractName) => {\n try {\n const abiPath = join(abisDir, `${contractName}.json`);\n return JSON.parse(readFileSync(abiPath, 'utf8'));\n } catch (error) {\n console.error(\n `Could not find ABI for contract ${contractName}:`,\n error.message,\n );\n throw error;\n }\n};\n\nconst updateStorage = async (config) => {\n try {\n const web3 = new Web3(config.rpcUrl);\n const formattedPrivateKey = config.privateKey.startsWith('0x') ? config.privateKey : `0x${config.privateKey}`;\n const account = web3.eth.accounts.privateKeyToAccount(formattedPrivateKey);\n web3.eth.accounts.wallet.add(account);\n\n const abi = getAbi('Storage');\n const contract = new web3.eth.Contract(abi, config.contractAddress);\n\n const initialValue = await contract.methods.storedNumber().call();\n console.log('Current stored value:', initialValue);\n\n const updateTransaction = contract.methods.setNumber(1);\n const gasEstimate = await updateTransaction.estimateGas({\n from: account.address,\n });\n const gasPrice = await web3.eth.getGasPrice();\n\n const receipt = await updateTransaction.send({\n from: account.address,\n gas: gasEstimate,\n gasPrice: gasPrice,\n });\n\n console.log(`Transaction hash: ${receipt.transactionHash}`);\n\n const newValue = await contract.methods.storedNumber().call();\n console.log('New stored value:', newValue);\n\n return receipt;\n } catch (error) {\n console.error('Update failed:', error);\n throw error;\n }\n};\n\nconst config = {\n rpcUrl: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n privateKey: 'INSERT_PRIVATE_KEY',\n contractAddress: 'INSERT_CONTRACT_ADDRESS',\n};\n\nupdateStorage(config)\n .then((receipt) => console.log('Update successful'))\n .catch((error) => console.error('Update error'));\n```\n\nEnsure you replace the `INSERT_PRIVATE_KEY` and `INSERT_CONTRACT_ADDRESS` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. The script reads the current stored value, sets it to 1, and then displays the updated value.\n\nTo interact with the contract, run:\n\n```bash\nnode scripts/updateStorage.js\n```"}
+{"page_id": "smart-contracts-libraries-web3-js", "page_title": "Deploy Contracts to Polkadot Hub with Web3.js", "index": 11, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 19676, "end_char": 20077, "estimated_token_count": 110, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n\n\n- External __Web3.js Docs__\n\n ---\n\n Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.\n\n [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/){target=\\_blank}\n\n
"}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 11, "end_char": 435, "estimated_token_count": 83, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteracting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols. \n\nThis guide illustrates how to utilize Web3.py for interactions with Polkadot Hub."}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 1, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 435, "end_char": 816, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\n1. To start working with Web3.py, begin by initializing your project:\n\n ```bash\n mkdir web3py-project\n cd web3py-project\n ```\n\n2. Create and activate a virtual environment for your project:\n\n ```bash\n python -m venv venv\n source venv/bin/activate\n ```\n\n3. Next, install the Web3.py library:\n\n ```bash\n pip install web3\n ```"}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 2, "depth": 2, "title": "Set Up the Web3 Provider", "anchor": "set-up-the-web3-provider", "start_char": 816, "end_char": 2433, "estimated_token_count": 351, "token_estimator": "heuristic-v1", "text": "## Set Up the Web3 Provider\n\nThe [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\\_blank} configuration is the foundation of any Web3.py application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.\n\nTo interact with Polkadot Hub, you must set up a Web3.py provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. The following code sets up the provider configuration:\n\n```python\nfrom web3 import Web3\n\nPROVIDER_RPC = \"INSERT_RPC_URL\"\nweb3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))\n\n```\n\n!!! note\n Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:\n\n ```python\n PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'\n ```\n\nWith the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain.\n\n??? code \"Fetch last block example\"\n\n ```python title=\"fetch_last_block.py\"\n from web3 import Web3\n\n\n def main():\n try:\n PROVIDER_RPC = \"https://testnet-passet-hub-eth-rpc.polkadot.io\"\n web3 = Web3(Web3.HTTPProvider(PROVIDER_RPC))\n latest_block = web3.eth.block_number\n print(\"Last block: \" + str(latest_block))\n except Exception as error:\n print(\"Error connecting to Polkadot Hub TestNet: \" + str(error))\n\n\n if __name__ == \"__main__\":\n main()\n\n ```"}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 3, "depth": 2, "title": "Sample Storage Contract", "anchor": "sample-storage-contract", "start_char": 2433, "end_char": 3686, "estimated_token_count": 286, "token_estimator": "heuristic-v1", "text": "## Sample Storage Contract\n\nPolkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the [`py-solc-x`](https://solcx.readthedocs.io/en/latest/){target=\\_blank} compiler.\n\nTo follow this guide, you can use the following Solidity contract as an example:\n\n```solidity title=\"Storage.sol\"\n//SPDX-License-Identifier: MIT\n\n// Solidity files have to start with this pragma.\n// It will be used by the Solidity compiler to validate its version.\npragma solidity ^0.8.9;\n\ncontract Storage {\n // Public state variable to store a number\n uint256 public storedNumber;\n\n /**\n * Updates the stored number.\n *\n * The `public` modifier allows anyone to call this function.\n *\n * @param _newNumber - The new value to store.\n */\n function setNumber(uint256 _newNumber) public {\n storedNumber = _newNumber;\n }\n}\n```\n\n\n\nAfter you've compiled the `Storage.sol` contract, you should have:\n\n- **An ABI (`.json`) file**: Provides a JSON interface describing the contract's functions and how to interact with it.\n- **A bytecode (`.bin`) file**: Contains the low-level machine code executable on EVM that represents the compiled smart contract ready for blockchain deployment."}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 4, "depth": 2, "title": "Contract Deployment", "anchor": "contract-deployment", "start_char": 3686, "end_char": 8601, "estimated_token_count": 977, "token_estimator": "heuristic-v1", "text": "## Contract Deployment\n\nTo deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:\n\n```python title=\"deploy.py\"\nfrom web3 import Web3\nimport json\nimport time\n\n\ndef get_abi(contract_name):\n try:\n with open(f\"{contract_name}.json\", \"r\") as file:\n return json.load(file)\n except Exception as error:\n print(f\"❌ Could not find ABI for contract {contract_name}: {error}\")\n raise error\n\n\ndef get_bytecode(contract_name):\n try:\n with open(f\"{contract_name}.bin\", \"r\") as file:\n bytecode = file.read().strip()\n return bytecode if bytecode.startswith(\"0x\") else f\"0x{bytecode}\"\n except Exception as error:\n print(f\"❌ Could not find bytecode for contract {contract_name}: {error}\")\n raise error\n\n\ndef deploy_with_retry(config, max_retries=3):\n \"\"\"Deploy with retry logic for RPC errors\"\"\"\n for attempt in range(max_retries):\n try:\n return deploy(config)\n except Exception as error:\n error_str = str(error)\n if (\n \"500\" in error_str\n or \"Internal Server Error\" in error_str\n or \"Connection\" in error_str\n ):\n if attempt < max_retries - 1:\n wait_time = (attempt + 1) * 3\n print(\n f\"RPC error, retrying in {wait_time} seconds... (attempt {attempt + 1}/{max_retries})\"\n )\n time.sleep(wait_time)\n continue\n raise error\n\n\ndef deploy(config):\n try:\n # Initialize Web3 with RPC URL and longer timeout\n web3 = Web3(\n Web3.HTTPProvider(config[\"rpc_url\"], request_kwargs={\"timeout\": 120})\n )\n\n # Prepare account\n formatted_private_key = (\n config[\"private_key\"]\n if config[\"private_key\"].startswith(\"0x\")\n else f\"0x{config['private_key']}\"\n )\n account = web3.eth.account.from_key(formatted_private_key)\n print(f\"Deploying from address: {account.address}\")\n\n # Load ABI and bytecode\n abi = get_abi(\"Storage\")\n bytecode = get_bytecode(\"Storage\")\n print(f\"Bytecode length: {len(bytecode)}\")\n\n # Create contract instance\n contract = web3.eth.contract(abi=abi, bytecode=bytecode)\n\n # Get current nonce (this will test the connection)\n print(\"Getting nonce...\")\n nonce = web3.eth.get_transaction_count(account.address)\n print(f\"Nonce: {nonce}\")\n\n # Estimate gas\n print(\"Estimating gas...\")\n gas_estimate = web3.eth.estimate_gas(\n {\"from\": account.address, \"data\": bytecode}\n )\n print(f\"Estimated gas: {gas_estimate}\")\n\n # Get gas price\n print(\"Getting gas price...\")\n gas_price = web3.eth.gas_price\n print(f\"Gas price: {web3.from_wei(gas_price, 'gwei')} gwei\")\n\n # Build deployment transaction\n print(\"Building transaction...\")\n construct_txn = contract.constructor().build_transaction(\n {\n \"from\": account.address,\n \"nonce\": nonce,\n \"gas\": gas_estimate,\n \"gasPrice\": gas_price,\n }\n )\n\n # Sign transaction\n print(\"Signing transaction...\")\n signed_txn = web3.eth.account.sign_transaction(\n construct_txn, private_key=formatted_private_key\n )\n\n # Send transaction\n print(\"Sending transaction...\")\n tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)\n print(f\"Transaction hash: {tx_hash.hex()}\")\n\n # Wait for transaction receipt\n print(\"Waiting for transaction receipt...\")\n tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)\n contract_address = tx_receipt.contractAddress\n\n # Log results\n print(f\"✅ Contract deployed at: {contract_address}\")\n print(f\"Gas used: {tx_receipt.gasUsed}\")\n print(f\"Block number: {tx_receipt.blockNumber}\")\n\n return web3.eth.contract(address=contract_address, abi=abi)\n\n except Exception as error:\n print(f\"❌ Deployment failed: {error}\")\n raise error\n\n\nif __name__ == \"__main__\":\n deployment_config = {\n \"rpc_url\": \"INSERT_RPC_URL\",\n \"private_key\": \"INSERT_PRIVATE_KEY\",\n }\n\n deploy_with_retry(deployment_config)\n\n```\n\n!!!warning\n Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds."}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 5, "depth": 2, "title": "Interact with the Contract", "anchor": "interact-with-the-contract", "start_char": 8601, "end_char": 10972, "estimated_token_count": 464, "token_estimator": "heuristic-v1", "text": "## Interact with the Contract\n\nAfter deployment, interact with your contract using Web3.py methods. The example below demonstrates how to set and retrieve a number. Be sure to replace the `INSERT_RPC_URL`, `INSERT_PRIVATE_KEY`, and `INSERT_CONTRACT_ADDRESS` placeholders with your specific values:\n\n```python title=\"update_storage.py\"\nfrom web3 import Web3\nimport json\n\n\ndef get_abi(contract_name):\n try:\n with open(f\"{contract_name}.json\", \"r\") as file:\n return json.load(file)\n except Exception as error:\n print(f\"❌ Could not find ABI for contract {contract_name}: {error}\")\n raise error\n\n\nasync def update_storage(config):\n try:\n # Initialize Web3 with RPC URL\n web3 = Web3(Web3.HTTPProvider(config[\"rpc_url\"]))\n\n # Prepare account\n account = web3.eth.account.from_key(config[\"private_key\"])\n\n # Load ABI\n abi = get_abi(\"Storage\")\n\n # Create contract instance\n contract = web3.eth.contract(address=config[\"contract_address\"], abi=abi)\n\n # Get initial value\n initial_value = contract.functions.storedNumber().call()\n print(\"Current stored value:\", initial_value)\n\n # Get current nonce\n nonce = web3.eth.get_transaction_count(account.address)\n\n # Prepare transaction\n transaction = contract.functions.setNumber(1).build_transaction(\n {\"from\": account.address, \"nonce\": nonce}\n )\n\n # Sign transaction\n signed_txn = web3.eth.account.sign_transaction(\n transaction, private_key=config[\"private_key\"]\n )\n\n # Send transaction\n tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction)\n print(f\"Transaction hash: {tx_hash.hex()}\")\n\n # Wait for receipt\n receipt = web3.eth.wait_for_transaction_receipt(tx_hash)\n\n # Get updated value\n new_value = contract.functions.storedNumber().call()\n print(\"New stored value:\", new_value)\n\n return receipt\n\n except Exception as error:\n print(\"Update failed:\", error)\n raise error\n\n\nif __name__ == \"__main__\":\n # Example usage\n import asyncio\n\n config = {\n \"rpc_url\": \"INSERT_RPC_URL\",\n \"private_key\": \"INSERT_PRIVATE_KEY\",\n \"contract_address\": \"INSERT_CONTRACT_ADDRESS\",\n }\n\n asyncio.run(update_storage(config))\n\n```"}
+{"page_id": "smart-contracts-libraries-web3-py", "page_title": "Web3.py", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10972, "end_char": 11372, "estimated_token_count": 106, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n\n\n- External __Web3.py Docs__\n\n ---\n\n Explore the Web3.py documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.\n\n [:octicons-arrow-right-24: Get Started](https://web3py.readthedocs.io/en/stable/){target=\\_blank}\n\n
"}
{"page_id": "smart-contracts-overview", "page_title": "Smart Contracts Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 201, "end_char": 1423, "estimated_token_count": 238, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities.\n\nWhether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\\_blank}, [Astar](https://docs.astar.network/){target=\\_blank}, and [Acala](https://evmdocs.acala.network/){target=\\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\\_blank}, the Polkadot ecosystem accommodates a range of diverse developers.\n\nThese guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications."}
{"page_id": "smart-contracts-overview", "page_title": "Smart Contracts Overview", "index": 1, "depth": 2, "title": "Native Smart Contracts", "anchor": "native-smart-contracts", "start_char": 1423, "end_char": 1450, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Native Smart Contracts"}
{"page_id": "smart-contracts-overview", "page_title": "Smart Contracts Overview", "index": 2, "depth": 3, "title": "Introduction", "anchor": "introduction-2", "start_char": 1450, "end_char": 1811, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "### Introduction\n\nPolkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows."}
diff --git a/llms.txt b/llms.txt
index 844f73706..28cb43f37 100644
--- a/llms.txt
+++ b/llms.txt
@@ -6,7 +6,7 @@
This directory lists URLs for raw Markdown pages that complement the rendered pages on the documentation site. Use these Markdown files to retain semantic context when prompting models while avoiding passing HTML elements.
## Metadata
-- Documentation pages: 87
+- Documentation pages: 86
- Categories: 11
## Docs
@@ -120,6 +120,7 @@ Docs: Tooling
- [Zero to Hero Smart Contract DApp](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md): Learn how to build a decentralized application on Polkadot Hub using Viem and Next.js by creating a simple dApp that interacts with a smart contract.
- [Deploying Uniswap V2 on Polkadot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md): Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem.
- [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub.
+- [Troubleshooting Hardhat](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting-faq.md): Common issues related to developing, compiling, and deploying smart contracts using Hardhat on Polkadot Hub, paired with troubleshooting suggestions.
- [Deploy Contracts Using Remix IDE](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md): Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state.
- [Use the Remix IDE on Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md): Explore the smart contract development and deployment process on Polkadot Hub using Remix IDE, a visual IDE for blockchain developers.
- [Troubleshooting Remix IDE](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md): Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions.
@@ -148,8 +149,6 @@ Docs: Uncategorized
- [smart-contracts-dev-environments-hardhat-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md): No description available.
- [smart-contracts-dev-environments-hardhat-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md): No description available.
- [smart-contracts-dev-environments-hardhat-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md): No description available.
-- [smart-contracts-dev-environments-hardhat-troubleshooting](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md): No description available.
-- [smart-contracts-dev-environments-hardhat-verify-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md): No description available.
- [Gas Model on the Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md): Learn how gas estimation, pricing, and weight mapping work in the Polkadot Hub.
- [smart-contracts-integrations-.indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.indexers.md): No description available.
- [smart-contracts-integrations-.oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.oracles.md): No description available.
diff --git a/smart-contracts/libraries/web3-js.md b/smart-contracts/libraries/web3-js.md
index 33138fd66..18f3ce166 100644
--- a/smart-contracts/libraries/web3-js.md
+++ b/smart-contracts/libraries/web3-js.md
@@ -220,8 +220,8 @@ node scripts/updateStorage.js
---
- Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, etc.
+ Explore the Web3.js documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
- [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/)
+ [:octicons-arrow-right-24: Get Started](https://web3js.readthedocs.io/en/v1.10.0/){target=\_blank}
diff --git a/smart-contracts/libraries/web3-py.md b/smart-contracts/libraries/web3-py.md
index 72964143b..06638c735 100644
--- a/smart-contracts/libraries/web3-py.md
+++ b/smart-contracts/libraries/web3-py.md
@@ -6,8 +6,6 @@ categories: Smart Contracts, Tooling
# Web3.py
---8<-- 'text/smart-contracts/polkaVM-warning.md'
-
## Introduction
Interacting with blockchains typically requires an interface between your application and the network. [Web3.py](https://web3py.readthedocs.io/en/stable/index.html){target=\_blank} offers this interface through a collection of libraries, facilitating seamless interaction with the nodes using HTTP or WebSocket protocols.
@@ -38,45 +36,48 @@ This guide illustrates how to utilize Web3.py for interactions with Polkadot Hub
## Set Up the Web3 Provider
-The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. The following example establishes a connection to Polkadot Hub. Follow these steps to use the provider configuration:
+The [provider](https://web3py.readthedocs.io/en/stable/providers.html){target=\_blank} configuration is the foundation of any Web3.py application. It serves as a bridge between your application and the blockchain, allowing you to query blockchain data and interact with smart contracts.
+
+To interact with Polkadot Hub, you must set up a Web3.py provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. The following code sets up the provider configuration:
+
+```python
+--8<-- "code/smart-contracts/libraries/web3-py/connect_to_provider.py"
+```
-1. Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
+!!! note
+ Replace `INSERT_RPC_URL` with the appropriate value. For instance, to connect to Polkadot Hub TestNet, use the following parameter:
```python
PROVIDER_RPC = 'https://testnet-passet-hub-eth-rpc.polkadot.io'
```
- The provider connection script should look something like this:
+With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain.
- ```python title="connect_to_provider.py"
- --8<-- "code/smart-contracts/libraries/web3-py/connect_to_provider.py"
- ```
-
-1. With the Web3 provider set up, start querying the blockchain. For instance, you can use the following code snippet to fetch the latest block number of the chain:
+??? code "Fetch last block example"
```python title="fetch_last_block.py"
- --8<-- "code/smart-contracts/libraries/web3-py/fetch_last_block.py:9:18"
+ --8<-- "code/smart-contracts/libraries/web3-py/fetch_last_block.py"
```
- ??? code "View complete script"
+## Sample Storage Contract
- ```python title="fetch_last_block.py"
- --8<-- "code/smart-contracts/libraries/web3-py/fetch_last_block.py"
- ```
+Polkadot Hub exposes an Ethereum JSON-RPC endpoint, so you can compile Solidity contracts to familiar EVM bytecode with the [`py-solc-x`](https://solcx.readthedocs.io/en/latest/){target=\_blank} compiler.
-## Contract Deployment
-
-Before deploying your contracts, make sure you've compiled them and obtained two key files:
-
-- An ABI (.json) file, which provides a JSON interface describing the contract's functions and how to interact with it.
-- A bytecode (.polkavm) file, which contains the low-level machine code executable on [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\_blank} that represents the compiled smart contract ready for blockchain deployment.
-
-To follow this guide, you can use the following solidity contract as an example:
+To follow this guide, you can use the following Solidity contract as an example:
```solidity title="Storage.sol"
--8<-- "code/smart-contracts/libraries/web3-py/Storage.sol"
```
+
+
+After you've compiled the `Storage.sol` contract, you should have:
+
+- **An ABI (`.json`) file**: Provides a JSON interface describing the contract's functions and how to interact with it.
+- **A bytecode (`.bin`) file**: Contains the low-level machine code executable on EVM that represents the compiled smart contract ready for blockchain deployment.
+
+## Contract Deployment
+
To deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an account with a private key to sign the deployment transaction. The deployment process is exactly the same as for any Ethereum-compatible chain, involving creating a contract instance, estimating gas, and sending a deployment transaction. Here's how to deploy the contract. Replace `INSERT_RPC_URL` and `INSERT_PRIVATE_KEY` with the appropriate values:
```python title="deploy.py"
@@ -84,7 +85,7 @@ To deploy your compiled contract to Polkadot Hub using Web3.py, you'll need an a
```
!!!warning
- Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds. Use environment variables instead.
+ Never commit or share your private key. Exposed keys can lead to immediate theft of all associated funds.
## Interact with the Contract
@@ -96,49 +97,14 @@ After deployment, interact with your contract using Web3.py methods. The example
## Where to Go Next
-Now that you have the foundation for using Web3.py with Polkadot Hub, consider exploring:
-
--
External __Advanced Web3.py Features__
-
- ---
- Explore Web3.py's documentation:
-
- - [:octicons-arrow-right-24: Middleware](https://web3py.readthedocs.io/en/stable/middleware.html){target=\_blank}
- - [:octicons-arrow-right-24: Filters & Events](https://web3py.readthedocs.io/en/stable/filters.html){target=\_blank}
- - [:octicons-arrow-right-24: ENS](https://web3py.readthedocs.io/en/stable/ens_overview.html){target=\_blank}
-
-
--
External __Testing Frameworks__
-
- ---
- Integrate Web3.py with Python testing frameworks:
-
-
- - [:octicons-arrow-right-24: Pytest](https://docs.pytest.org/){target=\_blank}
- - [:octicons-arrow-right-24: Brownie](https://eth-brownie.readthedocs.io/){target=\_blank}
-
-
--
External __Transaction Management__
+-
External __Web3.py Docs__
---
- Learn advanced transaction handling:
-
- - [:octicons-arrow-right-24: Gas Strategies](https://web3py.readthedocs.io/en/stable/gas_price.html){target=\_blank}
- - [:octicons-arrow-right-24: Account Management](https://web3py.readthedocs.io/en/stable/web3.eth.account.html){target=\_blank}
-
-
--
External __Building dApps__
-
- ---
- Combine Web3.py with these frameworks to create full-stack applications:
+ Explore the Web3.py documentation to learn how to use additional features, such as wallet management, signing messages, subscribing to events, and more.
-
- - [:octicons-arrow-right-24: Flask](https://flask.palletsprojects.com/){target=\_blank}
- - [:octicons-arrow-right-24: Django](https://www.djangoproject.com/){target=\_blank}
- - [:octicons-arrow-right-24: FastAPI](https://fastapi.tiangolo.com/){target=\_blank}
-
+ [:octicons-arrow-right-24: Get Started](https://web3py.readthedocs.io/en/stable/){target=\_blank}