diff --git a/SUPPORTED_APIS.md b/SUPPORTED_APIS.md index 5cf4f405..66b8ecf0 100644 --- a/SUPPORTED_APIS.md +++ b/SUPPORTED_APIS.md @@ -14,6 +14,7 @@ The `status` options are: | Namespace | API |
Status
| Description | | --- | --- | --- | --- | +| `ANVIL` | `anvil_setRpcUrl` | `SUPPORTED` | Sets the fork RPC url. Assumes the underlying chain is the same as before | | `ANVIL` | `anvil_setNextBlockBaseFeePerGas` | `SUPPORTED` | Sets the base fee of the next block | | `ANVIL` | `anvil_dropTransaction` | `SUPPORTED` | Removes a transaction from the pool | | `ANVIL` | `anvil_dropAllTransactions` | `SUPPORTED` | Remove all transactions from the pool | diff --git a/src/fork.rs b/src/fork.rs index dc7c2526..691bfc25 100644 --- a/src/fork.rs +++ b/src/fork.rs @@ -729,6 +729,11 @@ impl ForkDetails { } } } + + /// Sets fork's internal URL. Assumes the underlying chain is the same as before. + pub fn set_rpc_url(&mut self, url: String) { + self.fork_source = Box::new(HttpForkSource::new(url, self.cache_config.clone())); + } } #[cfg(test)] diff --git a/src/namespaces/anvil.rs b/src/namespaces/anvil.rs index 8a20480f..deb24f07 100644 --- a/src/namespaces/anvil.rs +++ b/src/namespaces/anvil.rs @@ -6,6 +6,14 @@ use crate::utils::Numeric; #[rpc] pub trait AnvilNamespaceT { + /// Sets the fork RPC url. Assumes the underlying chain is the same as before. + /// + /// # Arguments + /// + /// * `url` - Fork's new URL + #[rpc(name = "anvil_setRpcUrl")] + fn set_rpc_url(&self, url: String) -> RpcResult<()>; + /// Sets the base fee of the next block. /// /// # Arguments diff --git a/src/node/anvil.rs b/src/node/anvil.rs index 1837da4e..f5fdc821 100644 --- a/src/node/anvil.rs +++ b/src/node/anvil.rs @@ -12,6 +12,15 @@ use crate::{ impl AnvilNamespaceT for InMemoryNode { + fn set_rpc_url(&self, url: String) -> RpcResult<()> { + self.set_rpc_url(url) + .map_err(|err| { + tracing::error!("failed setting RPC url: {:?}", err); + into_jsrpc_error(Web3Error::InternalError(err)) + }) + .into_boxed_future() + } + fn set_next_block_base_fee_per_gas(&self, base_fee: U256) -> RpcResult<()> { self.set_next_block_base_fee_per_gas(base_fee) .map_err(|err| { diff --git a/src/node/in_memory_ext.rs b/src/node/in_memory_ext.rs index 24202d32..b1b81c61 100644 --- a/src/node/in_memory_ext.rs +++ b/src/node/in_memory_ext.rs @@ -423,6 +423,31 @@ impl InMemoryNo .set_base_fee(base_fee.as_u64()); Ok(()) } + + pub fn set_rpc_url(&self, url: String) -> Result<()> { + let inner = self + .inner + .read() + .map_err(|err| anyhow!("failed acquiring lock: {:?}", err))?; + let mut fork_storage = inner + .fork_storage + .inner + .write() + .map_err(|err| anyhow!("failed acquiring lock: {:?}", err))?; + if let Some(fork) = &mut fork_storage.fork { + let old_url = fork.fork_source.get_fork_url().map_err(|e| { + anyhow::anyhow!( + "failed to resolve current fork's RPC URL: {}", + e.to_string() + ) + })?; + fork.set_rpc_url(url.clone()); + tracing::info!("Updated fork rpc from \"{}\" to \"{}\"", old_url, url); + } else { + tracing::info!("Non-forking node tried to switch RPC URL to '{url}'. Call `anvil_reset` instead if you wish to switch to forking mode"); + } + Ok(()) + } } #[cfg(test)]