diff --git a/config/example.toml b/config/example.toml index 04159743..c8e00c61 100644 --- a/config/example.toml +++ b/config/example.toml @@ -13,6 +13,8 @@ db_replica_url = "mysql://root:dev_web3_proxy@127.0.0.1:13306/dev_web3_proxy" deposit_factory_contract = "0x4e3BC2054788De923A04936C6ADdB99A05B0Ea36" +free_subscriptions = true + kafka_urls = "127.0.0.1:19092" kafka_protocol = "plaintext" diff --git a/web3_proxy/src/app/ws.rs b/web3_proxy/src/app/ws.rs index e824c464..0ac99493 100644 --- a/web3_proxy/src/app/ws.rs +++ b/web3_proxy/src/app/ws.rs @@ -31,6 +31,22 @@ impl Web3ProxyApp { // TODO: taking a sender for Message instead of the exact json we are planning to send feels wrong, but its easier for now response_sender: mpsc::Sender, ) -> Web3ProxyResult<(AbortHandle, JsonRpcForwardedResponse)> { + let subscribe_to = jsonrpc_request + .params + .get(0) + .and_then(|x| x.as_str()) + .ok_or_else(|| { + Web3ProxyError::BadRequest("unable to subscribe using these params".into()) + })?; + + // anyone can subscribe to newHeads + // only premium users are allowed to subscribe to the other things + if !(subscribe_to == "newHeads" || authorization.active_premium().await) { + return Err(Web3ProxyError::AccessDenied( + "eth_subscribe for this event requires an active premium account".into(), + )); + } + let request_metadata = RequestMetadata::new( self, authorization.clone(), @@ -49,14 +65,6 @@ impl Web3ProxyApp { // save the id so we can use it in the response let id = jsonrpc_request.id.clone(); - let subscribe_to = jsonrpc_request - .params - .get(0) - .and_then(|x| x.as_str()) - .ok_or_else(|| { - Web3ProxyError::BadRequest("unable to subscribe using these params".into()) - })?; - // TODO: calling `json!` on every request is probably not fast. but it works for now // TODO: i think we need a stricter EthSubscribeRequest type that JsonRpcRequest can turn into // TODO: DRY This up. lots of duplication between newHeads and newPendingTransactions diff --git a/web3_proxy/src/config.rs b/web3_proxy/src/config.rs index 0eda0c3e..5bbd13fc 100644 --- a/web3_proxy/src/config.rs +++ b/web3_proxy/src/config.rs @@ -122,6 +122,11 @@ pub struct AppConfig { /// Default ERC address for out deposit contract pub deposit_factory_contract: Option
, + /// True if anonymous users should be able to eth_subscribe + /// newHeads is always allowed because that is cheap to send + #[serde_inline_default(false)] + pub free_subscriptions: bool, + /// minimum amount to increase eth_estimateGas results pub gas_increase_min: Option, diff --git a/web3_proxy/src/frontend/authorization.rs b/web3_proxy/src/frontend/authorization.rs index 7d40c281..46a599c3 100644 --- a/web3_proxy/src/frontend/authorization.rs +++ b/web3_proxy/src/frontend/authorization.rs @@ -676,6 +676,13 @@ impl From for Uuid { } impl Authorization { + /// this acquires a read lock on the latest balance. Be careful not to deadlock! + pub async fn active_premium(&self) -> bool { + let user_balance = self.checks.latest_balance.read().await; + + user_balance.active_premium() + } + pub fn internal() -> Web3ProxyResult { let authorization_checks = AuthorizationChecks { // any error logs on a local (internal) query are likely problems. log them all