From 8b9f51c88c2a51a9cf600c121e68b6df38fe41eb Mon Sep 17 00:00:00 2001 From: nhussein11 Date: Mon, 6 Jan 2025 14:16:45 -0300 Subject: [PATCH] fix: snippets --- .../smart-contracts/ether-js/Storage.sol | 21 ++ .../smart-contracts/ether-js/checkStorage.js | 84 ++++++ .../smart-contracts/ether-js/compile.js | 46 +++ .../ether-js/connectToProvider.js | 18 ++ .../smart-contracts/ether-js/deploy.js | 92 ++++++ .../ether-js/fetchLastBlock.js | 32 +++ .../api-libraries/smart-contracts/ether-js.md | 271 +----------------- 7 files changed, 299 insertions(+), 265 deletions(-) create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/Storage.sol create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/checkStorage.js create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/compile.js create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/connectToProvider.js create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/deploy.js create mode 100644 .snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/fetchLastBlock.js diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/Storage.sol b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/Storage.sol new file mode 100644 index 000000000..411398c84 --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/Storage.sol @@ -0,0 +1,21 @@ +//SPDX-License-Identifier: MIT + +// Solidity files have to start with this pragma. +// It will be used by the Solidity compiler to validate its version. +pragma solidity ^0.8.9; + +contract Storage { + // Public state variable to store a number + uint256 public storedNumber; + + /** + * Updates the stored number. + * + * The `public` modifier allows anyone to call this function. + * + * @param _newNumber - The new value to store. + */ + function setNumber(uint256 _newNumber) public { + storedNumber = _newNumber; + } +} \ No newline at end of file diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/checkStorage.js b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/checkStorage.js new file mode 100644 index 000000000..e03c03d15 --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/checkStorage.js @@ -0,0 +1,84 @@ +const { ethers } = require('ethers'); +const { readFileSync } = require('fs'); +const { join } = require('path'); + +const createProvider = (providerConfig) => { + return new ethers.JsonRpcProvider(providerConfig.rpc, { + chainId: providerConfig.chainId, + name: providerConfig.name, + }); +}; + +const createWallet = (mnemonic, provider) => { + return ethers.Wallet.fromPhrase(mnemonic).connect(provider); +}; + +const loadContractAbi = (contractName, directory = __dirname) => { + const contractPath = join(directory, `${contractName}.json`); + const contractJson = JSON.parse(readFileSync(contractPath, 'utf8')); + return contractJson.abi || contractJson; // Depending on JSON structure +}; + +const createContract = (contractAddress, abi, wallet) => { + return new ethers.Contract(contractAddress, abi, wallet); +}; + +const interactWithStorageContract = async ( + contractName, + contractAddress, + mnemonic, + providerConfig, + numberToSet, +) => { + try { + console.log(`Setting new number in Storage contract: ${numberToSet}`); + + // Create provider and wallet + const provider = createProvider(providerConfig); + const wallet = createWallet(mnemonic, provider); + + // Load the contract ABI and create the contract instance + const abi = loadContractAbi(contractName); + const contract = createContract(contractAddress, abi, wallet); + + // Send a transaction to set the stored number + const tx1 = await contract.setNumber(numberToSet); + await tx1.wait(); // Wait for the transaction to be mined + console.log(`Number successfully set to ${numberToSet}`); + + // Retrieve the updated number + const storedNumber = await contract.storedNumber(); + console.log(`Retrieved stored number:`, storedNumber.toString()); + + // Send a transaction to set the stored number + const tx2 = await contract.setNumber(numberToSet * 2); + await tx2.wait(); // Wait for the transaction to be mined + console.log(`Number successfully set to ${numberToSet * 2}`); + + // Retrieve the updated number + const updatedNumber = await contract.storedNumber(); + console.log(`Retrieved stored number:`, updatedNumber.toString()); + } catch (error) { + console.error('Error interacting with Storage contract:', error.message); + } +}; + +const providerConfig = { + name: 'asset-hub-smart-contracts', + rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', + chainId: 420420421, +}; + +const mnemonic = 'INSERT_MNEMONIC'; +const contractName = 'Storage'; +const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +const checkAddress = 'INSERT_ADDRESS_TO_CHECK'; +const newNumber = 42; + +interactWithStorageContract( + contractName, + contractAddress, + mnemonic, + providerConfig, + newNumber, +); diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/compile.js b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/compile.js new file mode 100644 index 000000000..cb1bdcbce --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/compile.js @@ -0,0 +1,46 @@ +const { compile } = require('@parity/revive'); +const { readFileSync, writeFileSync } = require('fs'); +const { basename, join } = require('path'); + +const compileContract = async (solidityFilePath, outputDir) => { + try { + // Read the Solidity file + const source = readFileSync(solidityFilePath, 'utf8'); + + // Construct the input object for the compiler + const input = { + [basename(solidityFilePath)]: { content: source }, + }; + + console.log(`Compiling contract: ${basename(solidityFilePath)}...`); + + // Compile the contract + const out = await compile(input); + + for (const contracts of Object.values(out.contracts)) { + for (const [name, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${name}`); + + // Write the ABI + const abiPath = join(outputDir, `${name}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); + + // Write the bytecode + const bytecodePath = join(outputDir, `${name}.polkavm`); + writeFileSync( + bytecodePath, + Buffer.from(contract.evm.bytecode.object, 'hex'), + ); + console.log(`Bytecode saved to ${bytecodePath}`); + } + } + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; + +const solidityFilePath = './Storage.sol'; +const outputDir = '.'; + +compileContract(solidityFilePath, outputDir); diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/connectToProvider.js b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/connectToProvider.js new file mode 100644 index 000000000..893b5fd6c --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/connectToProvider.js @@ -0,0 +1,18 @@ +const { JsonRpcProvider } = require('ethers'); + +const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + + return provider; +}; + +const PROVIDER_RPC = { + rpc: 'INSERT_RPC_URL', + chainId: 'INSERT_CHAIN_ID', + name: 'INSERT_CHAIN_NAME', +}; + +createProvider(PROVIDER_RPC.rpc, PROVIDER_RPC.chainId, PROVIDER_RPC.name); diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/deploy.js b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/deploy.js new file mode 100644 index 000000000..a9501de73 --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/deploy.js @@ -0,0 +1,92 @@ +const { writeFileSync, existsSync, readFileSync } = require('fs'); +const { join } = require('path'); +const { ethers, JsonRpcProvider } = require('ethers'); + +const codegenDir = join(__dirname); + +const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + + return provider; +}; + +const getAbi = (contractName) => { + try { + return JSON.parse( + readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'), + ); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } +}; + +const getByteCode = (contractName) => { + try { + return `0x${readFileSync(join(codegenDir, `${contractName}.polkavm`)).toString('hex')}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } +}; + +const deployContract = async (contractName, mnemonic, providerConfig) => { + console.log(`Deploying ${contractName}...`); + + try { + // Create a provider + const provider = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + + // Derive the wallet from the mnemonic + const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); + const wallet = walletMnemonic.connect(provider); + + // Create the contract factory + const factory = new ethers.ContractFactory( + getAbi(contractName), + getByteCode(contractName), + wallet, + ); + + // Deploy the contract + const contract = await factory.deploy(); + await contract.waitForDeployment(); + + const address = await contract.getAddress(); + console.log(`Contract ${contractName} deployed at: ${address}`); + + // Save the deployed address + const addressesFile = join(codegenDir, 'contract-address.json'); + const addresses = existsSync(addressesFile) + ? JSON.parse(readFileSync(addressesFile, 'utf8')) + : {}; + addresses[contractName] = address; + + writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); + } catch (error) { + console.error(`Failed to deploy contract ${contractName}:`, error); + } +}; + +const providerConfig = { + rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', + chainId: 420420421, + name: 'westend-asset-hub', +}; + +const mnemonic = 'INSERT_MNEMONIC'; + +deployContract('Storage', mnemonic, providerConfig); diff --git a/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/fetchLastBlock.js b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/fetchLastBlock.js new file mode 100644 index 000000000..f5d73c299 --- /dev/null +++ b/.snippets/code/develop/toolkit/api-libraries/smart-contracts/ether-js/fetchLastBlock.js @@ -0,0 +1,32 @@ +const { JsonRpcProvider } = require('ethers'); + +const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + + return provider; +}; + +const PROVIDER_RPC = { + rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', + chainId: 420420421, + name: 'westend-asset-hub', +}; + +const main = async () => { + try { + const provider = createProvider( + PROVIDER_RPC.rpc, + PROVIDER_RPC.chainId, + PROVIDER_RPC.name, + ); + const latestBlock = await provider.getBlockNumber(); + console.log(`Latest block: ${latestBlock}`); + } catch (error) { + console.error('Error connecting to Asset Hub: ' + error.message); + } +}; + +main(); diff --git a/develop/toolkit/api-libraries/smart-contracts/ether-js.md b/develop/toolkit/api-libraries/smart-contracts/ether-js.md index 3bdfabc23..c6696ff76 100644 --- a/develop/toolkit/api-libraries/smart-contracts/ether-js.md +++ b/develop/toolkit/api-libraries/smart-contracts/ether-js.md @@ -30,24 +30,7 @@ npm install ethers To interact with the Asset Hub, you'll need to set up an Ethers.js provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. Here's how to configure it: ```js -const { JsonRpcProvider } = require('ethers'); - -const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - - return provider; -} - -const PROVIDER_RPC = { - rpc: 'INSERT_RPC_URL', - chainId: 'INSERT_CHAIN_ID', - name: 'INSERT_CHAIN_NAME', -}; - -createProvider(PROVIDER_RPC.rpc, PROVIDER_RPC.chainId, PROVIDER_RPC.name); +--8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/connectToProvider.js' ``` !!! note @@ -66,34 +49,7 @@ With the [`Provider`](https://docs.ethers.org/v6/api/providers/#Provider){target ??? code "Fetch Last Block code" ```js - const { JsonRpcProvider } = require('ethers'); - - const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - - return provider; - } - - const PROVIDER_RPC = { - rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', - chainId: 420420421, - name: 'westend-asset-hub' - }; - - const main = async () => { - try { - const provider = createProvider(PROVIDER_RPC.rpc, PROVIDER_RPC.chainId, PROVIDER_RPC.name); - const latestBlock = await provider.getBlockNumber(); - console.log(`Latest block: ${latestBlock}`); - } catch (error) { - console.error('Error connecting to Asset Hub: ' + error.message); - } - }; - - main(); + --8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/fetchLastBlock.js' ``` ## Compile Contracts @@ -112,78 +68,13 @@ Here's a sample Solidity contract (`Storage.sol`) to be compiled and deployed to ??? code "Storage.sol" ```solidity - //SPDX-License-Identifier: MIT - - // Solidity files have to start with this pragma. - // It will be used by the Solidity compiler to validate its version. - pragma solidity ^0.8.9; - - contract Storage { - // Public state variable to store a number - uint256 public storedNumber; - - /** - * Updates the stored number. - * - * The `public` modifier allows anyone to call this function. - * - * @param _newNumber - The new value to store. - */ - function setNumber(uint256 _newNumber) public { - storedNumber = _newNumber; - } - } + --8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/Storage.sol' ``` To compile this contract, use the following script: ```js -const { compile } = require('@parity/revive'); -const { readFileSync, writeFileSync } = require('fs'); -const { basename, join } = require('path'); - -const compileContract = async (solidityFilePath, outputDir) => { - try { - // Read the Solidity file - const source = readFileSync(solidityFilePath, 'utf8'); - - // Construct the input object for the compiler - const input = { - [basename(solidityFilePath)]: { content: source }, - }; - - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - - // Compile the contract - const out = await compile(input); - - for (const contracts of Object.values(out.contracts)) { - for (const [name, contract] of Object.entries(contracts)) { - console.log(`Compiled contract: ${name}`); - - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); - - // Write the bytecode - const bytecodePath = join(outputDir, `${name}.polkavm`); - writeFileSync( - bytecodePath, - Buffer.from(contract.evm.bytecode.object, 'hex') - ); - console.log(`Bytecode saved to ${bytecodePath}`); - } - } - } catch (error) { - console.error('Error compiling contracts:', error); - } -} - -const solidityFilePath = './Storage.sol'; -const outputDir = '.'; - -compileContract(solidityFilePath, outputDir); +--8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/compile.js' ``` Note that 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 accordingly. @@ -197,86 +88,7 @@ To deploy the compiled contract to the Asset Hub, you will need a wallet with a Here's the script to deploy the contract: ```js -const { writeFileSync, existsSync, readFileSync } = require('fs'); -const { join } = require('path'); -const { ethers, JsonRpcProvider } = require('ethers'); - -const codegenDir = join(__dirname); - -const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - - return provider; -} - -const getAbi = (contractName) => { - try { - return JSON.parse(readFileSync(join(codegenDir, `${contractName}.json`), 'utf8')); - } catch (error) { - console.error(`Could not find ABI for contract ${contractName}:`, error.message); - throw error; - } -} - -const getByteCode = (contractName) => { - try { - return `0x${readFileSync(join(codegenDir, `${contractName}.polkavm`)).toString('hex')}`; - } catch (error) { - console.error(`Could not find bytecode for contract ${contractName}:`, error.message); - throw error; - } -} - -const deployContract = async (contractName, mnemonic, providerConfig) => { - console.log(`Deploying ${contractName}...`); - - try { - // Create a provider - const provider = createProvider(providerConfig.rpc, providerConfig.chainId, providerConfig.name); - - // Derive the wallet from the mnemonic - const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); - const wallet = walletMnemonic.connect(provider); - - // Create the contract factory - const factory = new ethers.ContractFactory( - getAbi(contractName), - getByteCode(contractName), - wallet - ); - - // Deploy the contract - const contract = await factory.deploy(); - await contract.waitForDeployment(); - - const address = await contract.getAddress(); - console.log(`Contract ${contractName} deployed at: ${address}`); - - // Save the deployed address - const addressesFile = join(codegenDir, 'contract-address.json'); - const addresses = existsSync(addressesFile) - ? JSON.parse(readFileSync(addressesFile, 'utf8')) - : {}; - addresses[contractName] = address; - - writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); - } catch (error) { - console.error(`Failed to deploy contract ${contractName}:`, error); - } -} - -const providerConfig = { - rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', - chainId: 420420421, - name: 'westend-asset-hub' -}; - -const mnemonic = 'INSERT_MNEMONIC'; - -deployContract('Storage', mnemonic, providerConfig); +--8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/deploy.js' ``` !!! note @@ -289,78 +101,7 @@ After running the script above, the contract will be deployed to the Asset Hub n 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 use the following script: ```js -const { ethers } = require('ethers'); -const { readFileSync } = require('fs'); -const { join } = require('path'); - -const createProvider = (providerConfig) => { - return new ethers.JsonRpcProvider(providerConfig.rpc, { - chainId: providerConfig.chainId, - name: providerConfig.name, - }); -} - -const createWallet = (mnemonic, provider) => { - return ethers.Wallet.fromPhrase(mnemonic).connect(provider); -} - -const loadContractAbi = (contractName, directory = __dirname) => { - const contractPath = join(directory, `${contractName}.json`); - const contractJson = JSON.parse(readFileSync(contractPath, 'utf8')); - return contractJson.abi || contractJson; // Depending on JSON structure -} - -const createContract = (contractAddress, abi, wallet) => { - return new ethers.Contract(contractAddress, abi, wallet); -} - -const interactWithStorageContract = async (contractName, contractAddress, mnemonic, providerConfig, numberToSet) => { - try { - console.log(`Setting new number in Storage contract: ${numberToSet}`); - - // Create provider and wallet - const provider = createProvider(providerConfig); - const wallet = createWallet(mnemonic, provider); - - // Load the contract ABI and create the contract instance - const abi = loadContractAbi(contractName); - const contract = createContract(contractAddress, abi, wallet); - - // Send a transaction to set the stored number - const tx1 = await contract.setNumber(numberToSet); - await tx1.wait(); // Wait for the transaction to be mined - console.log(`Number successfully set to ${numberToSet}`); - - // Retrieve the updated number - const storedNumber = await contract.storedNumber(); - console.log(`Retrieved stored number:`, storedNumber.toString()); - - // Send a transaction to set the stored number - const tx2 = await contract.setNumber(numberToSet*2); - await tx2.wait(); // Wait for the transaction to be mined - console.log(`Number successfully set to ${numberToSet*2}`); - - // Retrieve the updated number - const updatedNumber = await contract.storedNumber(); - console.log(`Retrieved stored number:`, updatedNumber.toString()); - } catch (error) { - console.error('Error interacting with Storage contract:', error.message); - } -} - -const providerConfig = { - name: 'asset-hub-smart-contracts', - rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io', - chainId: 420420421, -}; - -const mnemonic = 'INSERT_MNEMONIC'; -const contractName = 'Storage'; -const contractAddress = 'INSERT_CONTRACT_ADDRESS'; -const checkAddress = 'INSERT_ADDRESS_TO_CHECK'; -const newNumber = 42; - -interactWithStorageContract(contractName, contractAddress, mnemonic, providerConfig, newNumber); +--8<-- 'code/develop/toolkit/api-libraries/smart-contracts/ether-js/checkStorage.js' ``` Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS` and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, the contract ABI file (`Storage.json`) should be correctly referenced.