Skip to content
This repository has been archived by the owner on Aug 28, 2023. It is now read-only.

Commit

Permalink
Add tags to SafeApp (#851)
Browse files Browse the repository at this point in the history
- Enables serialisation and deserialisation of tags for a SafeApp
- Serialisation is enabled IFF SAFE_APPS_TAGS_FEATURE_ENABLED is set to true
  • Loading branch information
fmrsabino authored Apr 13, 2022
1 parent 2e5a71f commit 8922d05
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/
FEATURE_FLAG_NESTED_DECODING=true
FEATURE_FLAG_BALANCES_RATE_IMPLEMENTATION=false

# Enables the tags feature for Safe Apps
SAFE_APPS_TAGS_FEATURE_ENABLED=false

# Random string (generated with openssl rand -base64 32)
# [string] a 256-bit base64 encoded string (44 characters) to use as the secret key
ROCKET_SECRET_KEY=Qt6DPFUU8qO4BKTCQnKAgt9FBBJxIWAYUGyHuruVfpE=
Expand Down
5 changes: 5 additions & 0 deletions src/common/converters/tests/safe_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ fn safe_apps_several_apps() {
chain_ids: vec!["1".to_string(), "137".to_string()],
provider: None,
access_control: SafeAppAccessControlPolicies::NoRestrictions,
tags: vec![]
},
SafeApp {
id: 24,
Expand All @@ -49,6 +50,7 @@ fn safe_apps_several_apps() {
chain_ids: vec!["1".to_string(), "4".to_string(),"10".to_string(),"56".to_string(),"100".to_string(),"137".to_string(),"246".to_string(), "42161".to_string(), "43114".to_string(), "73799".to_string()],
provider: None,
access_control: SafeAppAccessControlPolicies::NoRestrictions,
tags: vec![]
},
SafeApp {
id: 11,
Expand All @@ -64,6 +66,7 @@ fn safe_apps_several_apps() {
access_control: SafeAppAccessControlPolicies::DomainAllowlist(SafeAppDomainAllowlistPolicy {
value: vec!["https://gnosis-safe.io".to_string(), "https://dev.gnosis-safe.io".to_string()],
}),
tags: vec![]
},
SafeApp {
id: 30,
Expand All @@ -74,6 +77,7 @@ fn safe_apps_several_apps() {
chain_ids: vec!["1".to_string(),"56".to_string(),"137".to_string()],
provider: None,
access_control: SafeAppAccessControlPolicies::NoRestrictions,
tags: vec![]
},
SafeApp {
id: 25,
Expand All @@ -84,6 +88,7 @@ fn safe_apps_several_apps() {
chain_ids: vec!["1".to_string(), "4".to_string(), "10".to_string(),"56".to_string(),"100".to_string(),"137".to_string(),"246".to_string(), "73799".to_string(), "42161".to_string(), "43114".to_string()],
provider: None,
access_control: SafeAppAccessControlPolicies::NoRestrictions,
tags: vec![]
},
];

Expand Down
3 changes: 3 additions & 0 deletions src/common/models/backend/safe_apps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub struct SafeApp {
pub chain_ids: Vec<u64>,
pub provider: Option<SafeAppProvider>,
pub access_control: SafeAppAccessControlPolicies,
// We set this value as a default since this feature might not be enabled yet. See SAFE_APPS_TAGS_FEATURE_ENABLED
#[serde(default)]
pub tags: Vec<String>,
}

#[derive(Deserialize, Debug, PartialEq, Clone)]
Expand Down
4 changes: 4 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ pub fn feature_flag_balances_rate_implementation() -> bool {
env_with_default("FEATURE_FLAG_BALANCES_RATE_IMPLEMENTATION", false)
}

pub fn is_safe_apps_tags_feature_enabled() -> bool {
env_with_default("SAFE_APPS_TAGS_FEATURE_ENABLED", false)
}

pub fn vpc_transaction_service_uri() -> bool {
env_with_default("VPC_TRANSACTION_SERVICE_URI", true)
}
Expand Down
1 change: 1 addition & 0 deletions src/routes/safe_apps/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl From<BackendSafeApp> for SafeApp {
}
_ => SafeAppAccessControlPolicies::Unknown,
},
tags: safe_app.tags,
}
}
}
10 changes: 10 additions & 0 deletions src/routes/safe_apps/models.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use serde::Serialize;

use crate::config::is_safe_apps_tags_feature_enabled;

#[derive(Serialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(test, derive(serde::Deserialize))]
Expand All @@ -12,6 +14,14 @@ pub struct SafeApp {
pub chain_ids: Vec<String>,
pub provider: Option<SafeAppProvider>,
pub access_control: SafeAppAccessControlPolicies,
#[serde(skip_serializing_if = "should_skip_serializing_tags")]
// We deserialize this for testing so it would break since the value wouldn't be present
#[serde(default)]
pub tags: Vec<String>,
}

pub fn should_skip_serializing_tags(_tags: &Vec<String>) -> bool {
return !is_safe_apps_tags_feature_enabled();
}

#[derive(Serialize, Debug, PartialEq, Clone)]
Expand Down
91 changes: 91 additions & 0 deletions src/routes/safe_apps/tests/json/response_safe_apps_with_tags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
[
{
"id": 26,
"url": "https://curve.fi",
"name": "Curve",
"iconUrl": "https://curve.fi/logo-square.svg",
"description": "Decentralized exchange liquidity pool designed for extremely efficient stablecoin trading and low-risk income for liquidity providers",
"chainIds": ["1", "137"],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag1"]
},
{
"id": 24,
"url": "https://safe-apps.dev.gnosisdev.com/tx-builder",
"name": "Transaction Builder",
"iconUrl": "https://safe-apps.dev.gnosisdev.com/tx-builder/tx-builder.png",
"description": "A Safe app to compose custom transactions",
"chainIds": [
"1",
"4",
"10",
"56",
"100",
"137",
"246",
"42161",
"43114",
"73799"
],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag2"]
},
{
"id": 11,
"url": "https://app.1inch.io",
"name": "1inch.exchange",
"iconUrl": "https://app.1inch.io/assets/images/1inch.svg",
"description": "The most efficient defi aggregator",
"chainIds": ["1", "56", "137"],
"provider": {
"url": "https://1inch.exchange",
"name": "1inch corporation"
},
"accessControl": {
"type": "DOMAIN_ALLOWLIST",
"value": ["https://gnosis-safe.io", "https://dev.gnosis-safe.io"]
}
},
{
"id": 30,
"url": "https://paraswap.io",
"name": "ParaSwap",
"iconUrl": "https://paraswap.io/paraswap.svg",
"description": "ParaSwap allows dApps and traders to get the best DEX liquidity by aggregating multiple markets and offering the best rates",
"chainIds": ["1", "56", "137"],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
}
},
{
"id": 25,
"url": "https://safe-apps.dev.gnosisdev.com/wallet-connect",
"name": "WalletConnect",
"iconUrl": "https://safe-apps.dev.gnosisdev.com/wallet-connect/wallet-connect.svg",
"description": "Connect your Safe to any dApp that supports WalletConnect",
"chainIds": [
"1",
"4",
"10",
"56",
"100",
"137",
"246",
"73799",
"42161",
"43114"
],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag1", "tag2"]
}
]
2 changes: 2 additions & 0 deletions src/routes/safe_apps/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod routes;

pub(crate) const RESPONSE_SAFE_APPS: &str = include_str!("json/response_safe_apps.json");
pub(crate) const RESPONSE_SAFE_APPS_WITH_TAGS: &str =
include_str!("json/response_safe_apps_with_tags.json");
48 changes: 48 additions & 0 deletions src/routes/safe_apps/tests/routes.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
use crate::routes::safe_apps::models::SafeApp;
use crate::routes::safe_apps::tests::RESPONSE_SAFE_APPS_WITH_TAGS;
use crate::tests::main::setup_rocket;
use crate::utils::errors::{ApiError, ErrorDetails};
use crate::utils::http_client::{MockHttpClient, Request, Response};
use mockall::predicate::eq;
use rocket::http::{Header, Status};
use rocket::local::asynchronous::Client;
use serde_json::json;
use std::env;

use super::RESPONSE_SAFE_APPS;

#[rocket::async_test]
async fn safe_apps() {
env::set_var("SAFE_APPS_TAGS_FEATURE_ENABLED", "false");
let chain_id = "137";
let client_url = "https://gnosis-safe.io";

Expand Down Expand Up @@ -58,6 +61,7 @@ async fn safe_apps() {

#[rocket::async_test]
async fn safe_apps_not_found() {
env::set_var("SAFE_APPS_TAGS_FEATURE_ENABLED", "false");
let chain_id = "4";
let backend_error_json = json!({"details": "Not found"}).to_string();
let error = ErrorDetails {
Expand Down Expand Up @@ -105,3 +109,47 @@ async fn safe_apps_not_found() {
serde_json::to_string(&error).unwrap()
);
}

#[rocket::async_test]
async fn safe_apps_tags() {
env::set_var("SAFE_APPS_TAGS_FEATURE_ENABLED", "true");
let chain_id = "137";
let client_url = "https://gnosis-safe.io";
let mut mock_http_client = MockHttpClient::new();
let safe_apps_request = Request::new(config_uri!(
"/v1/safe-apps/?chainId={}&clientUrl={}",
chain_id,
client_url
));
mock_http_client
.expect_get()
.times(1)
.with(eq(safe_apps_request))
.return_once(move |_| {
Ok(Response {
status_code: 200,
body: String::from(crate::tests::json::POLYGON_SAFE_APPS_WITH_TAGS),
})
});
let client = Client::tracked(
setup_rocket(
mock_http_client,
routes![super::super::routes::get_safe_apps],
)
.await,
)
.await
.expect("valid rocket instance");
let response = {
let mut response = client.get("/v1/chains/137/safe-apps?client_url=https://gnosis-safe.io");
response.add_header(Header::new("Host", "test.gnosis.io"));
response.dispatch().await
};
let actual_status = response.status();
let actual_body = response.into_string().await.unwrap();
let actual: Vec<SafeApp> = serde_json::from_str(&actual_body).unwrap();
let expected: Vec<SafeApp> = serde_json::from_str(RESPONSE_SAFE_APPS_WITH_TAGS).unwrap();

assert_eq!(actual_status, Status::Ok);
assert_eq!(actual, expected);
}
2 changes: 2 additions & 0 deletions src/tests/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ pub const CHAIN_INFO_RINKEBY_ENABLED_FEATURES: &str =
include_str!("chains/rinkeby_enabled_features.json");

pub const POLYGON_SAFE_APPS: &str = include_str!("safe_apps/polygon_safe_apps.json");
pub const POLYGON_SAFE_APPS_WITH_TAGS: &str =
include_str!("safe_apps/polygon_safe_apps_with_tags.json");
pub const UNISWAP_SAFE_APP_MANIFEST: &str = include_str!("safe_apps/uniswap_manifest.json");

pub const POLYGON_MASTER_COPIES: &str = include_str!("master_copies/polygon_master_copies.json");
Expand Down
69 changes: 69 additions & 0 deletions src/tests/json/safe_apps/polygon_safe_apps_with_tags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[
{
"id": 26,
"url": "https://curve.fi",
"name": "Curve",
"iconUrl": "https://curve.fi/logo-square.svg",
"description": "Decentralized exchange liquidity pool designed for extremely efficient stablecoin trading and low-risk income for liquidity providers",
"chainIds": [1, 137],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag1"]
},
{
"id": 24,
"url": "https://safe-apps.dev.gnosisdev.com/tx-builder",
"name": "Transaction Builder",
"iconUrl": "https://safe-apps.dev.gnosisdev.com/tx-builder/tx-builder.png",
"description": "A Safe app to compose custom transactions",
"chainIds": [1, 4, 10, 56, 100, 137, 246, 42161, 43114, 73799],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag2"]
},
{
"id": 11,
"url": "https://app.1inch.io",
"name": "1inch.exchange",
"iconUrl": "https://app.1inch.io/assets/images/1inch.svg",
"description": "The most efficient defi aggregator",
"chainIds": [1, 56, 137],
"provider": {
"url": "https://1inch.exchange",
"name": "1inch corporation"
},
"accessControl": {
"type": "DOMAIN_ALLOWLIST",
"value": ["https://gnosis-safe.io", "https://dev.gnosis-safe.io"]
}
},
{
"id": 30,
"url": "https://paraswap.io",
"name": "ParaSwap",
"iconUrl": "https://paraswap.io/paraswap.svg",
"description": "ParaSwap allows dApps and traders to get the best DEX liquidity by aggregating multiple markets and offering the best rates",
"chainIds": [1, 56, 137],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
}
},
{
"id": 25,
"url": "https://safe-apps.dev.gnosisdev.com/wallet-connect",
"name": "WalletConnect",
"iconUrl": "https://safe-apps.dev.gnosisdev.com/wallet-connect/wallet-connect.svg",
"description": "Connect your Safe to any dApp that supports WalletConnect",
"chainIds": [1, 4, 10, 56, 100, 137, 246, 73799, 42161, 43114],
"provider": null,
"accessControl": {
"type": "NO_RESTRICTIONS"
},
"tags": ["tag1", "tag2"]
}
]

0 comments on commit 8922d05

Please sign in to comment.