diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..7bdd06a --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,33 @@ +FROM rust:1.82-bullseye + +# Update and install necessary packages, including libc6-dev for libresolv +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + wget \ + curl \ + libpq-dev \ + pkg-config \ + clang \ + build-essential \ + libc6-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Ensure CA certificates are installed +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates + +WORKDIR /app + +#Install go +COPY scripts/install-go.sh install-go.sh +RUN ./install-go.sh +ENV PATH=$PATH:/usr/local/go/bin + +# Set Rust flags to link against libresolv +ENV RUSTFLAGS="-C link-arg=-lresolv" + +# Download and install dev environment deps +RUN cargo install --locked cargo-binstall + +# Install nextest for tests... +RUN cargo binstall cargo-nextest --secure diff --git a/README.md b/README.md index 690f3f9..21dc99a 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,12 @@ We recommend using [nextest](https://nexte.st/) as your test runner. Once you ha cargo nextest run ``` +Alternatively, to run graphcast-sdk tests using docker to avoid local dependency issues: +``` +./scripts/docker-run-tests.sh +``` + + ## How does the Graphcast SDK work? The SDK is essentially a base layer that Radio developers can use to build their applications without needing to worry about starting everything from scratch. The components that are included in the SDK are: diff --git a/scripts/docker-run-tests.sh b/scripts/docker-run-tests.sh new file mode 100755 index 0000000..c384de6 --- /dev/null +++ b/scripts/docker-run-tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# NOTE: Run from project root ./scripts/docker-run-tests.sh + +docker build -t graphcast-sdk-dev -f Dockerfile.dev . +docker run --rm -v .:/app graphcast-sdk-dev cargo nextest run diff --git a/scripts/install-go.sh b/scripts/install-go.sh new file mode 100755 index 0000000..42f8d36 --- /dev/null +++ b/scripts/install-go.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +if [ $(uname -m) = "aarch64" ]; then + wget https://golang.org/dl/go1.20.13.linux-arm64.tar.gz && + tar -C /usr/local -xzf go1.20.13.linux-arm64.tar.gz +else + wget https://golang.org/dl/go1.20.13.linux-amd64.tar.gz && + tar -C /usr/local -xzf go1.20.13.linux-amd64.tar.gz +fi diff --git a/src/graphcast_agent/message_typing.rs b/src/graphcast_agent/message_typing.rs index 78a705b..9481086 100644 --- a/src/graphcast_agent/message_typing.rs +++ b/src/graphcast_agent/message_typing.rs @@ -434,46 +434,6 @@ mod tests { Wallet::new(&mut thread_rng()) } - // Signature generated from goerli main indexer account - fn graph_account_message() -> GraphcastMessage { - GraphcastMessage { - identifier: String::from("ping-pong-content-topic"), - nonce: 1688744240, - graph_account: String::from("0xe9a1cabd57700b17945fd81feefba82340d9568f"), - payload: - SimpleMessage { - identifier: String::from("table"), - content: String::from("Ping") }, - signature: String::from("a68733f919065a7eab215add3b0dc9cfb2d63b00fcd310803e8ee2dc9cf034af03f6fa4ba431e3d6167156d604e1dea2136bb3fea6d290ac6db980b30f790acb1c") - } - } - - // Signature generated from goerli secondary indexer account - fn indexer_message() -> GraphcastMessage { - GraphcastMessage { - identifier: String::from("ping-pong-content-topic"), - nonce: 1688743340, - graph_account: String::from("0x6121d1036d7016b125f019268b0406a4c15bb99d"), - payload: - SimpleMessage { identifier: String::from("table"), content: String::from("Ping") }, - signature: String::from("de8b176cb78aa2ec0bc9e163374423309cba10947fed04b5544bd9db81f54ded66328486e959771372ea5e8c093fe80dea64b7d3004bc59cd14712721208fab01b"), - } - } - - // Signature generated from goerli third graph account - fn graphcast_id_message() -> GraphcastMessage { - GraphcastMessage { - identifier: String::from("ping-pong-content-topic"), - nonce: 1688742308, - graph_account: String::from("0xe9a1cabd57700b17945fd81feefba82340d9568f"), - payload: - SimpleMessage { - identifier: String::from("table"), - content: String::from("Ping") }, - signature: String::from("60a4b735acaf0c2490a51e34e0b799080c5c144ee2fe5dc9499465c490a4c5e946609c7d27d3b39cf4110d4f9402bac7f89cf2bd3850ae816506e638cde1a3c11c") - } - } - #[tokio::test] async fn test_signature() { let wallet = dummy_wallet(); @@ -536,213 +496,4 @@ mod tests { format!("{:#x}", wallet.address()) ); } - - #[tokio::test] - async fn test_validate_graph_network() { - let registry_subgraph = - "https://api.thegraph.com/subgraphs/name/hopeyen/gossip-registry-test"; - let network_subgraph = - "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"; - // graph_account_message is by a valid eth address that is not registered as a graphcast_id but is a graph account and valid indexer - let msg = graph_account_message(); - assert_eq!( - msg.recover_sender_address().unwrap(), - String::from("0xe9a1cabd57700b17945fd81feefba82340d9568f") - ); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::NoCheck - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::ValidAddress - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphNetworkAccount - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::Indexer - ) - .await - .is_ok()); - - // Message should fail to validate if registry is required - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphcastRegistered - ) - .await - .is_err()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::RegisteredIndexer - ) - .await - .is_err()); - } - - #[tokio::test] - async fn test_validate_indexer() { - let registry_subgraph = - "https://thegraph.com/hosted-service/subgraph/hopeyen/graphcast-registry-goerli"; - let network_subgraph = - "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"; - // graph_account_message is by a valid eth address that is not registered as a graphcast_id but is a graph account and valid indexer - let msg = indexer_message(); - assert_eq!( - msg.recover_sender_address().unwrap(), - String::from("0x6121d1036d7016b125f019268b0406a4c15bb99d") - ); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::NoCheck - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::ValidAddress - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphNetworkAccount - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::Indexer - ) - .await - .is_ok()); - - // Message should fail to validate if registry is required - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphcastRegistered - ) - .await - .is_err()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::RegisteredIndexer - ) - .await - .is_err()); - } - - #[tokio::test] - async fn test_validate_registry() { - let registry_subgraph = - "https://api.thegraph.com/subgraphs/name/hopeyen/gossip-registry-test"; - let network_subgraph = - "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"; - // graph_account_message is by a valid eth address that is not registered as a graphcast_id but is a graph account and valid indexer - let msg = graphcast_id_message(); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::NoCheck - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::ValidAddress - ) - .await - .is_ok()); - - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::Indexer - ) - .await - .is_ok()); - - // Message should fail to validate if only Graph network account is checked - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphNetworkAccount - ) - .await - .is_err()); - - // Should success for checks at Graphcast registry - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::GraphcastRegistered - ) - .await - .is_ok()); - assert!(msg - .valid_sender( - registry_subgraph, - network_subgraph, - "".to_string(), - &IdentityValidation::RegisteredIndexer - ) - .await - .is_ok()); - } } diff --git a/src/graphql/client_graph_account.rs b/src/graphql/client_graph_account.rs index 30cafe5..32d5870 100644 --- a/src/graphql/client_graph_account.rs +++ b/src/graphql/client_graph_account.rs @@ -199,36 +199,3 @@ pub async fn subgraph_hash_by_id( Ok(hash) } - -#[cfg(test)] -mod tests { - - use super::*; - - #[tokio::test] - async fn test_owned_subgraphs() { - let network_subgraph = - "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"; - let account = "0xe9a1cabd57700b17945fd81feefba82340d9568f"; - let owned_subgraphs = owned_subgraphs(network_subgraph, account).await; - - assert!(owned_subgraphs.is_ok()); - // Current subgraph number - assert!(owned_subgraphs.unwrap().len() > 5); - } - - #[tokio::test] - async fn test_subgraph_current_hash() { - let network_subgraph = - "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-goerli"; - let account = "0xe9a1cabd57700b17945fd81feefba82340d9568f"; - let subgraph_id = "CnJMdCkW3pr619gsJVtUPAWxspALPdCMw6o7obzYBNp3"; - let hash = subgraph_hash_by_id(network_subgraph, account, subgraph_id) - .await - .unwrap(); - - assert!(hash.contains(&String::from( - "QmacQnSgia4iDPWHpeY6aWxesRFdb8o5DKZUx96zZqEWrB" - ))); - } -}