Skip to content

Commit

Permalink
rpc updates
Browse files Browse the repository at this point in the history
  • Loading branch information
pgherveou committed Oct 10, 2024
1 parent ed4c0d0 commit de0b0ef
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 94 deletions.
130 changes: 39 additions & 91 deletions substrate/frame/revive/rpc/demo/demo.ts
Original file line number Diff line number Diff line change
@@ -1,96 +1,44 @@

import { Contract, ContractFactory, JsonRpcSigner, parseEther, encodeRlp, AddressLike, getBytes, JsonRpcProvider } from 'ethers';
//! Run with bun run demo.ts
import { Contract, ContractFactory, encodeRlp, getBytes, JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('http://localhost:9090');
const signer = await provider.getSigner();
console.log(`Signer address: ${await signer.getAddress()}, Nonce: ${await signer.getNonce()}`);


const code = getBytes('0x50564d0001010424009000022363616c6cdeadbeef63616c6c5f6e657665726465706c6f797365616c5f72657475726e041001000000007365616c5f72657475726e051b03000a63616c6c5f6e6576657204066465706c6f79060463616c6c062c06011f000406081b1c06100408130013000211fc03100408040001040904040706100a05004e13005129a4b800');
const args = new Uint8Array()
const bytecode = encodeRlp([ code, args ]);

const contractFactory = new ContractFactory([], bytecode, signer);
const contract = await contractFactory.deploy();
await contract.waitForDeployment();
const address = await contract.getAddress();
console.log(`Contract deployed: ${address}`);

//main().catch(console.error);



// const nonce = await signer.getNonce();
// console.log(`Nonce: ${nonce}`);
//
// document.getElementById('transferButton')?.addEventListener('click', async () => {
// const address = (document.getElementById('transferInput') as HTMLInputElement).value;
// await transfer(address);
// });
//
// document.getElementById('deployButton')?.addEventListener('click', async () => {
// await deploy();
// });
// document.getElementById('deployAndCallButton')?.addEventListener('click', async () => {
// const nonce = await signer.getNonce();
// console.log(`deploy with nonce: ${nonce}`);
//
// const address = await deploy();
// if (address) {
// const nonce = await signer.getNonce();
// console.log(`call with nonce: ${nonce}`);
// await call(address);
// }
//
// });
// document.getElementById('callButton')?.addEventListener('click', async () => {
// const address = (document.getElementById('callInput') as HTMLInputElement).value;
// await call(address);
// });
//
// async function deploy() {
// console.log('Deploying contract...');
//
// const code = getBytes('0x50564d0001010424009000022363616c6cdeadbeef63616c6c5f6e657665726465706c6f797365616c5f72657475726e041001000000007365616c5f72657475726e051b03000a63616c6c5f6e6576657204066465706c6f79060463616c6c062c06011f000406081b1c06100408130013000211fc03100408040001040904040706100a05004e13005129a4b800');
// const args = new Uint8Array()
// const bytecode = encodeRlp([ code, args ]);
//
// const contractFactory = new ContractFactory([], bytecode, signer);
//
// try {
// const contract = await contractFactory.deploy();
// await contract.waitForDeployment();
// const address = await contract.getAddress();
// console.log(`Contract deployed: ${address}`);
// return address;
// } catch (e) {
// console.error('Failed to deploy contract', e);
// return;
// }
// }
//
// async function call(address: string) {
// const abi = ['function getValue() view returns (uint256)', 'function setValue(uint256 _value)'];
//
// const contract = new Contract(address, abi, signer);
// const tx = await contract.setValue(42);
//
// console.log('Transaction hash:', tx.hash);
// }
//
// async function transfer(to: AddressLike) {
// console.log(`transferring 1 DOT to ${to}...`);
// try {
// const tx = await signer.sendTransaction({
// to,
// value: parseEther('1.0'),
// });
//
// const receipt = await tx.wait();
// console.log(`Transaction hash: ${receipt?.hash}`);
// } catch (e) {
// console.error('Failed to send transaction', e);
// return;
// }
// }
//});
function str_to_bytes(str: string): Uint8Array {
return new TextEncoder().encode(str);
}
debugger
// deploy
async function deploy() {
console.log(`Deploying Contract...`);
const code = getBytes('0x50564d000101041c009000021c6465706c6f7963616c6c696e7075746465706f7369745f6576656e74041b02000000000d0000006465706f7369745f6576656e74696e707574050f0203066465706c6f79560463616c6c0681661b02810a0000030020002f003a00470055005600720081008c009a00a800a900af00ba00bd00c500d100e300eb00f100f300f800fc00040106014e1300021174ff03108800031584005217040980000405800004080610068e0003158000521702188000061008dc00011a800004078100297a1e04070000015219040806100cbd011088000115840002118c00130000021174ff03108800031584005217040980000405800004080610123b031580005217021880000610148a00011a800004078100297a1f0407000001521904080610186bff011088000115840002118c00130000040a102fa947287a12aa0308a70b070a0e527c1110c802cc012fbcfb14a909129cfc08cb0a2e0c1d128cff0004020000010102220101222c0c1103bc02bb042fabfb1299030f090a0513527a07090f089a091110a802aa012f9afb13004e0113008b88220a518488848a8868441451441122122a44449392b4244922882c492a5952fd00');

const args = str_to_bytes('ssh');
const bytecode = encodeRlp([ code, new Uint8Array() ]);
console.log(`Bytecode length: ${bytecode.length}`, );
const contractFactory = new ContractFactory([
"constructor(bytes memory _data)",
], bytecode, signer);

console.log('Deploying contract with args:', args);
const contract = await contractFactory.deploy(args);
await contract.waitForDeployment();
const address = await contract.getAddress();
console.log(`Contract deployed: ${address}`);
return address;
}

async function call(address: string) {
console.log(`Calling Contract at ${address}...`);

const abi = ['function call(bytes data)'];
const contract = new Contract(address, abi, signer);
const tx = await contract.call(str_to_bytes('world'));
console.log('Call transaction hash:', tx.hash);
}

const address = await deploy()
if (Deno.env.get('CALL') ) {
await call(address)
}
1 change: 0 additions & 1 deletion substrate/frame/revive/rpc/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"devDependencies": {
"@types/node": "^14.14.6",
"prettier": "^3.3.3",
"ts-node": "^10.9.2",
"typescript": "^4.1.2",
"vite": "^2.5.0"
}
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/revive/rpc/demo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"compilerOptions": {
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
Expand Down
44 changes: 44 additions & 0 deletions substrate/frame/revive/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ pub enum EthRpcError {
/// The account was not found at the given address
#[error("Account not found for address {0:?}")]
AccountNotFound(H160),
/// Received an invalid transaction
#[error("Invalid transaction")]
InvalidTransaction,
/// Received an invalid transaction
#[error("Invalid transaction {0:?}")]
TransactionTypeNotSupported(Byte),
}

impl From<EthRpcError> for ErrorObjectOwned {
Expand Down Expand Up @@ -147,6 +153,44 @@ impl EthRpcServer for EthRpcServerImpl {
Ok(hash)
}

async fn send_transaction(&self, transaction: GenericTransaction) -> RpcResult<H256> {
log::debug!(target: LOG_TARGET, "{transaction:#?}");
let GenericTransaction { from, gas, gas_price, input, to, value, r#type, .. } = transaction;

let Some(from) = from else {
log::debug!(target: LOG_TARGET, "Transaction must have a sender");
return Err(EthRpcError::InvalidTransaction.into());
};

let account = self
.accounts
.iter()
.find(|account| account.address() == from)
.ok_or(EthRpcError::AccountNotFound(from))?;

let gas_price = gas_price.unwrap_or_else(|| U256::from(GAS_PRICE));
let chain_id = Some(self.client.chain_id().into());
let input = input.unwrap_or_default();
let value = value.unwrap_or_default();
let r#type = r#type.unwrap_or_default();

let Some(gas) = gas else {
log::debug!(target: LOG_TARGET, "Transaction must have a gas limit");
return Err(EthRpcError::InvalidTransaction.into());
};

let r#type = Type0::try_from_byte(r#type.clone())
.map_err(|_| EthRpcError::TransactionTypeNotSupported(r#type))?;

let nonce = self.get_transaction_count(from, BlockTag::Latest.into()).await?;

let tx =
TransactionLegacyUnsigned { chain_id, gas, gas_price, input, nonce, to, value, r#type };
let tx = account.sign_transaction(tx);
let rlp_bytes = rlp::encode(&tx).to_vec();
self.send_raw_transaction(Bytes(rlp_bytes)).await
}

async fn get_block_by_hash(
&self,
block_hash: H256,
Expand Down
4 changes: 4 additions & 0 deletions substrate/frame/revive/rpc/src/rpc_methods_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ pub trait EthRpc {
#[method(name = "eth_sendRawTransaction")]
async fn send_raw_transaction(&self, transaction: Bytes) -> RpcResult<H256>;

/// Signs and submits a transaction.
#[method(name = "eth_sendTransaction")]
async fn send_transaction(&self, transaction: GenericTransaction) -> RpcResult<H256>;

/// The string value of current network id
#[method(name = "net_version")]
async fn net_version(&self) -> RpcResult<String>;
Expand Down
1 change: 0 additions & 1 deletion substrate/frame/transaction-payment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,6 @@ impl<T: Config> Pallet<T> {
where
T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
{
log::info!(target: "evm", "compute_fee: len: {len:?}, info: {info:?}, tip: {tip:?}");
Self::compute_fee_details(len, info, tip).final_fee()
}

Expand Down

0 comments on commit de0b0ef

Please sign in to comment.