Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document "Web3.js" for asset hub smart contracts #358

Open
wants to merge 1 commit into
base: staging-ah-smart-contracts
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const interactWithStorageContract = async (
contractAddress,
mnemonic,
providerConfig,
numberToSet,
numberToSet
) => {
try {
console.log(`Setting new number in Storage contract: ${numberToSet}`);
Expand Down Expand Up @@ -79,5 +79,5 @@ interactWithStorageContract(
contractAddress,
mnemonic,
providerConfig,
newNumber,
newNumber
);
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const compileContract = async (solidityFilePath, outputDir) => {
const bytecodePath = join(outputDir, `${name}.polkavm`);
writeFileSync(
bytecodePath,
Buffer.from(contract.evm.bytecode.object, 'hex'),
Buffer.from(contract.evm.bytecode.object, 'hex')
);
console.log(`Bytecode saved to ${bytecodePath}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ const createProvider = (rpcUrl, chainId, chainName) => {
const getAbi = (contractName) => {
try {
return JSON.parse(
readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'),
readFileSync(join(codegenDir, `${contractName}.json`), 'utf8')
);
} catch (error) {
console.error(
`Could not find ABI for contract ${contractName}:`,
error.message,
error.message
);
throw error;
}
Expand All @@ -31,11 +31,13 @@ const getAbi = (contractName) => {
// Reads the compiled bytecode for a given contract
const getByteCode = (contractName) => {
try {
return `0x${readFileSync(join(codegenDir, `${contractName}.polkavm`)).toString('hex')}`;
return `0x${readFileSync(
join(codegenDir, `${contractName}.polkavm`)
).toString('hex')}`;
} catch (error) {
console.error(
`Could not find bytecode for contract ${contractName}:`,
error.message,
error.message
);
throw error;
}
Expand All @@ -49,7 +51,7 @@ const deployContract = async (contractName, mnemonic, providerConfig) => {
const provider = createProvider(
providerConfig.rpc,
providerConfig.chainId,
providerConfig.name,
providerConfig.name
);
const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic);
const wallet = walletMnemonic.connect(provider);
Expand All @@ -58,7 +60,7 @@ const deployContract = async (contractName, mnemonic, providerConfig) => {
const factory = new ethers.ContractFactory(
getAbi(contractName),
getByteCode(contractName),
wallet,
wallet
);
const contract = await factory.deploy();
await contract.waitForDeployment();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const main = async () => {
const provider = createProvider(
PROVIDER_RPC.rpc,
PROVIDER_RPC.chainId,
PROVIDER_RPC.name,
PROVIDER_RPC.name
);
const latestBlock = await provider.getBlockNumber();
console.log(`Latest block: ${latestBlock}`);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//SPDX-License-Identifier: MIT
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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const { Web3 } = require('web3');

const createProvider = (rpcUrl) => {
const web3 = new Web3(rpcUrl);
return web3;
};

const PROVIDER_RPC = {
rpc: 'INSERT_RPC_URL',
chainId: 'INSERT_CHAIN_ID',
name: 'INSERT_CHAIN_NAME',
};

createProvider(PROVIDER_RPC.rpc);
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { readFileSync } from 'fs';
import { Web3 } from 'web3';

const getAbi = (contractName) => {
try {
return JSON.parse(readFileSync(`${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(`${contractName}.polkavm`).toString('hex')}`;
} catch (error) {
console.error(
`❌ Could not find bytecode for contract ${contractName}:`,
error.message
);
throw error;
}
};

export const deploy = async (config) => {
try {
// Initialize Web3 with RPC URL
const web3 = new Web3(config.rpcUrl);

// Prepare account
const account = web3.eth.accounts.privateKeyToAccount(config.privateKey);
web3.eth.accounts.wallet.add(account);

// Load abi
const abi = getAbi('Storage');

// Create contract instance
const contract = new web3.eth.Contract(abi);

// Prepare deployment
const deployTransaction = contract.deploy({
data: getByteCode('Storage'),
arguments: [], // Add constructor arguments if needed
});

// Estimate gas
const gasEstimate = await deployTransaction.estimateGas({
from: account.address,
});

// Get current gas price
const gasPrice = await web3.eth.getGasPrice();

// Send deployment transaction
const deployedContract = await deployTransaction.send({
from: account.address,
gas: gasEstimate,
gasPrice: gasPrice,
});

// Log and return contract details
console.log(`Contract deployed at: ${deployedContract.options.address}`);
return deployedContract;
} catch (error) {
console.error('Deployment failed:', error);
throw error;
}
};

// Example usage
const deploymentConfig = {
rpcUrl: 'INSERT_RPC_URL',
privateKey: 'INSERT_PRIVATE_KEY',
contractName: 'INSERT_CONTRACT_NAME',
};

deploy(deploymentConfig)
.then((contract) => console.log('Deployment successful'))
.catch((error) => console.error('Deployment error'));
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const { Web3 } = require('web3');

const createProvider = (rpcUrl) => {
const web3 = new Web3(rpcUrl);
return web3;
};

const PROVIDER_RPC = {
rpc: 'https://westend-asset-hub-eth-rpc.polkadot.io',
chainId: 420420421,
name: 'westend-asset-hub',
};

const main = async () => {
try {
const web3 = createProvider(PROVIDER_RPC.rpc);
const latestBlock = await web3.eth.getBlockNumber();
console.log('Last block: ' + latestBlock);
} catch (error) {
console.error('Error connecting to Asset Hub: ' + error.message);
}
};

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { readFileSync } from 'fs';
import { Web3 } from 'web3';

const getAbi = (contractName) => {
try {
return JSON.parse(readFileSync(`${contractName}.json`), 'utf8');
} catch (error) {
console.error(
`❌ Could not find ABI for contract ${contractName}:`,
error.message
);
throw error;
}
};

const updateStorage = async (config) => {
try {
// Initialize Web3 with RPC URL
const web3 = new Web3(config.rpcUrl);

// Prepare account
const account = web3.eth.accounts.privateKeyToAccount(config.privateKey);
web3.eth.accounts.wallet.add(account);

// Load abi
const abi = getAbi('Storage');

// Create contract instance
const contract = new web3.eth.Contract(abi, config.contractAddress);

// Get initial value
const initialValue = await contract.methods.storedNumber().call();
console.log('Current stored value:', initialValue);

// Prepare transaction
const updateTransaction = contract.methods.setNumber(1);

// Estimate gas
const gasEstimate = await updateTransaction.estimateGas({
from: account.address,
});

// Get current gas price
const gasPrice = await web3.eth.getGasPrice();

// Send update transaction
const receipt = await updateTransaction.send({
from: account.address,
gas: gasEstimate,
gasPrice: gasPrice,
});

// Log transaction details
console.log(`Transaction hash: ${receipt.transactionHash}`);

// Get updated value
const newValue = await contract.methods.storedNumber().call();
console.log('New stored value:', newValue);

return receipt;
} catch (error) {
console.error('Update failed:', error);
throw error;
}
};

// Example usage
const config = {
rpcUrl: 'INSERT_RPC_URL',
privateKey: 'INSERT_PRIVATE_KEY',
contractAddress: 'INSERT_CONTRACT_ADDRESS',
};

updateStorage(config)
.then((receipt) => console.log('Update successful'))
.catch((error) => console.error('Update error'));
Loading