Skip to content

Commit

Permalink
feat: add blockchain API provider
Browse files Browse the repository at this point in the history
  • Loading branch information
chris13524 committed Jan 31, 2024
1 parent 16797b6 commit 19eca03
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 192 deletions.
2 changes: 1 addition & 1 deletion relay_rpc/src/auth/cacao.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use {
self::{
header::Header,
payload::Payload,
signature::{GetRpcUrl, Signature},
signature::{eip1271::get_rpc_url::GetRpcUrl, Signature},
},
core::fmt::Debug,
serde::{Deserialize, Serialize},
Expand Down
190 changes: 0 additions & 190 deletions relay_rpc/src/auth/cacao/signature.rs

This file was deleted.

58 changes: 58 additions & 0 deletions relay_rpc/src/auth/cacao/signature/eip1271/blockchain_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use {super::get_rpc_url::GetRpcUrl, crate::domain::ProjectId, url::Url};

// https://github.com/WalletConnect/blockchain-api/blob/master/SUPPORTED_CHAINS.md
const SUPPORTED_CHAINS: [&str; 26] = [
"eip155:1",
"eip155:5",
"eip155:11155111",
"eip155:10",
"eip155:420",
"eip155:42161",
"eip155:421613",
"eip155:137",
"eip155:80001",
"eip155:1101",
"eip155:42220",
"eip155:1313161554",
"eip155:1313161555",
"eip155:56",
"eip155:56",
"eip155:43114",
"eip155:43113",
"eip155:324",
"eip155:280",
"near",
"eip155:100",
"solana:4sgjmw1sunhzsxgspuhpqldx6wiyjntz",
"eip155:8453",
"eip155:84531",
"eip155:7777777",
"eip155:999",
];

pub struct BlockchainApiProvider {
project_id: ProjectId,
}

impl BlockchainApiProvider {
pub fn new(project_id: ProjectId) -> Self {
Self { project_id }
}
}

impl GetRpcUrl for BlockchainApiProvider {
fn get_rpc_url(&self, chain_id: String) -> Option<Url> {
if SUPPORTED_CHAINS.contains(&chain_id.as_str()) {
Some(
format!(
"https://rpc.walletconnect.com/v1?chainId={chain_id}&projectId={}",
self.project_id
)
.parse()
.expect("Provider URL should be valid"),
)
} else {
None
}
}
}
5 changes: 5 additions & 0 deletions relay_rpc/src/auth/cacao/signature/eip1271/get_rpc_url.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use url::Url;

pub trait GetRpcUrl {
fn get_rpc_url(&self, chain_id: String) -> Option<Url>;
}
98 changes: 98 additions & 0 deletions relay_rpc/src/auth/cacao/signature/eip1271/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use {
super::CacaoError,
alloy_primitives::{Address, FixedBytes},
alloy_providers::provider::{Provider, TempProvider},
alloy_rpc_types::{CallInput, CallRequest},
alloy_sol_types::{sol, SolCall},
alloy_transport_http::Http,
url::Url,
};

pub mod blockchain_api;
pub mod get_rpc_url;

pub const EIP1271: &str = "eip1271";

// https://eips.ethereum.org/EIPS/eip-1271
const MAGIC_VALUE: u32 = 0x1626ba7e;
sol! {
function isValidSignature(
bytes32 _hash,
bytes memory _signature)
public
view
returns (bytes4 magicValue);
}

pub async fn verify_eip1271(
signature: Vec<u8>,
address: Address,
hash: &[u8; 32],
provider: Url,
) -> Result<bool, CacaoError> {
let provider = Provider::new(Http::new(provider));

let call_request = CallRequest {
to: Some(address),
input: CallInput::new(
isValidSignatureCall {
_hash: FixedBytes::from(hash),
_signature: signature,
}
.abi_encode()
.into(),
),
..Default::default()
};

let result = provider.call(call_request, None).await.map_err(|e| {
if let Some(error_response) = e.as_error_resp() {
if error_response.message.starts_with("execution reverted:") {
CacaoError::Verification
} else {
CacaoError::Eip1271Internal(e)
}
} else {
CacaoError::Eip1271Internal(e)
}
})?;

if result[..4] == MAGIC_VALUE.to_be_bytes().to_vec() {
Ok(true)
} else {
Err(CacaoError::Verification)
}
}

#[cfg(test)]
mod test {
use {
super::*,
crate::auth::cacao::signature::{eip191::eip191_bytes, strip_hex_prefix},
alloy_primitives::address,
sha3::{Digest, Keccak256},
};

// Manual test. Paste address, signature, message, and project ID to verify
// function
#[tokio::test]
#[ignore]
async fn test_eip1271() {
let address = address!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
let signature = "xxx";
let signature = data_encoding::HEXLOWER_PERMISSIVE
.decode(strip_hex_prefix(signature).as_bytes())
.map_err(|_| CacaoError::Verification)
.unwrap();
let message = "xxx";
let hash = &Keccak256::new_with_prefix(eip191_bytes(message)).finalize()[..]
.try_into()
.unwrap();
let provider = "https://rpc.walletconnect.com/v1?chainId=eip155:1&projectId=xxx"
.parse()
.unwrap();
assert!(verify_eip1271(signature, address, hash, provider)
.await
.unwrap());
}
}
Loading

0 comments on commit 19eca03

Please sign in to comment.