Skip to content

Commit

Permalink
feat(torii-graphql): add erc1155 to union (#3057)
Browse files Browse the repository at this point in the history
* feat(torii-graphql): add erc1155 to union

* f
  • Loading branch information
Larkooo authored Feb 21, 2025
1 parent 467cad1 commit df7cec5
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 11 deletions.
2 changes: 2 additions & 0 deletions crates/torii/graphql/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub const TOKEN_UNION_TYPE_NAME: &str = "ERC__Token";

pub const ERC20_TYPE_NAME: &str = "ERC20__Token";
pub const ERC721_TYPE_NAME: &str = "ERC721__Token";
pub const ERC1155_TYPE_NAME: &str = "ERC1155__Token";

// objects' single and plural names
pub const ENTITY_NAMES: (&str, &str) = ("entity", "entities");
Expand All @@ -55,6 +56,7 @@ pub const PAGE_INFO_NAMES: (&str, &str) = ("pageInfo", "");

pub const ERC20_TOKEN_NAME: (&str, &str) = ("erc20Token", "");
pub const ERC721_TOKEN_NAME: (&str, &str) = ("erc721Token", "");
pub const ERC1155_TOKEN_NAME: (&str, &str) = ("erc1155Token", "");

pub const TOKEN_BALANCE_NAME: (&str, &str) = ("", "tokenBalances");
pub const TOKEN_TRANSFER_NAME: (&str, &str) = ("", "tokenTransfers");
Expand Down
13 changes: 13 additions & 0 deletions crates/torii/graphql/src/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,19 @@ lazy_static! {
(Name::new("imagePath"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
]);

pub static ref ERC1155_TOKEN_TYPE_MAPPING: TypeMapping = IndexMap::from([
(Name::new("name"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("symbol"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("tokenId"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("contractAddress"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("amount"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("metadata"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
(Name::new("metadataName"), TypeData::Simple(TypeRef::named(TypeRef::STRING))),
(Name::new("metadataDescription"), TypeData::Simple(TypeRef::named(TypeRef::STRING))),
(Name::new("metadataAttributes"), TypeData::Simple(TypeRef::named(TypeRef::STRING))),
(Name::new("imagePath"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))),
]);

pub static ref EMPTY_MAPPING: TypeMapping = IndexMap::from([
(Name::new("id"), TypeData::Simple(TypeRef::named(TypeRef::ID))),
]);
Expand Down
174 changes: 169 additions & 5 deletions crates/torii/graphql/src/object/erc/erc_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ use sqlx::{Pool, Row, Sqlite, SqliteConnection};
use tokio_stream::StreamExt;
use torii_sqlite::simple_broker::SimpleBroker;
use torii_sqlite::types::Token;
use tracing::warn;

use super::handle_cursor;
use crate::constants::{
DEFAULT_LIMIT, ERC20_TOKEN_NAME, ERC20_TYPE_NAME, ERC721_TOKEN_NAME, ERC721_TYPE_NAME,
ID_COLUMN,
DEFAULT_LIMIT, ERC1155_TOKEN_NAME, ERC1155_TYPE_NAME, ERC20_TOKEN_NAME, ERC20_TYPE_NAME,
ERC721_TOKEN_NAME, ERC721_TYPE_NAME, ID_COLUMN,
};
use crate::mapping::{
ERC1155_TOKEN_TYPE_MAPPING, ERC20_TOKEN_TYPE_MAPPING, ERC721_TOKEN_TYPE_MAPPING,
TOKEN_TYPE_MAPPING,
};
use crate::mapping::{ERC20_TOKEN_TYPE_MAPPING, ERC721_TOKEN_TYPE_MAPPING, TOKEN_TYPE_MAPPING};
use crate::object::connection::page_info::PageInfoObject;
use crate::object::connection::{
connection_arguments, cursor, parse_connection_arguments, ConnectionArguments,
Expand Down Expand Up @@ -58,10 +62,28 @@ impl BasicObject for Erc721TokenObject {
}
}

#[derive(Debug)]
pub struct Erc1155TokenObject;

impl BasicObject for Erc1155TokenObject {
fn name(&self) -> (&str, &str) {
ERC1155_TOKEN_NAME
}

fn type_name(&self) -> &str {
ERC1155_TYPE_NAME
}

fn type_mapping(&self) -> &TypeMapping {
&ERC1155_TOKEN_TYPE_MAPPING
}
}

#[derive(Debug, Clone)]
pub enum ErcTokenType {
Erc20(Erc20Token),
Erc721(Erc721Token),
Erc1155(Erc1155Token),
}

#[derive(Debug, Clone)]
Expand All @@ -86,6 +108,20 @@ pub struct Erc721Token {
pub image_path: String,
}

#[derive(Debug, Clone)]
pub struct Erc1155Token {
pub name: String,
pub symbol: String,
pub token_id: String,
pub contract_address: String,
pub amount: String,
pub metadata: String,
pub metadata_name: Option<String>,
pub metadata_description: Option<String>,
pub metadata_attributes: Option<String>,
pub image_path: String,
}

impl ErcTokenType {
pub fn to_field_value<'a>(self) -> FieldValue<'a> {
match self {
Expand Down Expand Up @@ -122,6 +158,30 @@ impl ErcTokenType {
]))),
ERC721_TYPE_NAME.to_string(),
),
ErcTokenType::Erc1155(token) => FieldValue::with_type(
FieldValue::value(Value::Object(ValueMapping::from([
(Name::new("name"), Value::String(token.name)),
(Name::new("symbol"), Value::String(token.symbol)),
(Name::new("tokenId"), Value::String(token.token_id)),
(Name::new("contractAddress"), Value::String(token.contract_address)),
(Name::new("amount"), Value::String(token.amount)),
(Name::new("metadata"), Value::String(token.metadata)),
(
Name::new("metadataName"),
token.metadata_name.map(Value::String).unwrap_or(Value::Null),
),
(
Name::new("metadataDescription"),
token.metadata_description.map(Value::String).unwrap_or(Value::Null),
),
(
Name::new("metadataAttributes"),
token.metadata_attributes.map(Value::String).unwrap_or(Value::Null),
),
(Name::new("imagePath"), Value::String(token.image_path)),
]))),
ERC1155_TYPE_NAME.to_string(),
),
}
}
}
Expand Down Expand Up @@ -446,7 +506,65 @@ impl ResolvableObject for TokenObject {
};
ErcTokenType::Erc721(token)
}
_ => return None,
"erc1155" => {
let id = row.get::<String, _>("id");
let token_id =
id.split(':').collect::<Vec<&str>>()[1].to_string();

let metadata_str: String = row.get("metadata");
let (
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
) = if metadata_str.is_empty() {
(String::new(), None, None, None, String::new())
} else {
let metadata: serde_json::Value =
serde_json::from_str(&metadata_str)
.expect("metadata is always json");
let metadata_name = metadata.get("name").map(|v| {
v.to_string().trim_matches('"').to_string()
});
let metadata_description =
metadata.get("description").map(|v| {
v.to_string().trim_matches('"').to_string()
});
let metadata_attributes =
metadata.get("attributes").map(|v| {
v.to_string().trim_matches('"').to_string()
});

let image_path =
format!("{}/image", id.replace(":", "/"));
(
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
)
};

let token = Erc1155Token {
name: row.get("name"),
metadata: metadata_str,
contract_address: row.get("contract_address"),
symbol: row.get("symbol"),
token_id,
amount: "0".to_string(),
metadata_name,
metadata_description,
metadata_attributes,
image_path,
};
ErcTokenType::Erc1155(token)
}
_ => {
warn!("Unknown contract type: {}", contract_type);
return None;
}
};

Some(Ok(FieldValue::owned_any(token_metadata)))
Expand Down Expand Up @@ -516,6 +634,52 @@ fn create_token_metadata_from_row(row: &SqliteRow) -> sqlx::Result<ErcTokenType>
};
ErcTokenType::Erc721(token)
}
_ => return Err(sqlx::Error::RowNotFound),
"erc1155" => {
// contract_address:token_id
let id = row.get::<String, _>("id");
let token_id = id.split(':').collect::<Vec<&str>>()[1].to_string();

let metadata_str: String = row.get("metadata");
let (
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
) = if metadata_str.is_empty() {
(String::new(), None, None, None, String::new())
} else {
let metadata: serde_json::Value =
serde_json::from_str(&metadata_str).expect("metadata is always json");
let metadata_name =
metadata.get("name").map(|v| v.to_string().trim_matches('"').to_string());
let metadata_description = metadata
.get("description")
.map(|v| v.to_string().trim_matches('"').to_string());
let metadata_attributes =
metadata.get("attributes").map(|v| v.to_string().trim_matches('"').to_string());

let image_path = format!("{}/image", id.replace(":", "/"));
(metadata_str, metadata_name, metadata_description, metadata_attributes, image_path)
};

let token = Erc1155Token {
name: row.get("name"),
metadata: metadata_str,
contract_address: row.get("contract_address"),
symbol: row.get("symbol"),
token_id,
amount: "0".to_string(),
metadata_name,
metadata_description,
metadata_attributes,
image_path,
};
ErcTokenType::Erc1155(token)
}
_ => {
warn!("Unknown contract type: {}", contract_type);
return Err(sqlx::Error::RowNotFound);
}
})
}
115 changes: 113 additions & 2 deletions crates/torii/graphql/src/object/erc/token_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::object::connection::page_info::PageInfoObject;
use crate::object::connection::{
connection_arguments, cursor, parse_connection_arguments, ConnectionArguments,
};
use crate::object::erc::erc_token::Erc721Token;
use crate::object::erc::erc_token::{Erc1155Token, Erc721Token};
use crate::object::{BasicObject, ResolvableObject};
use crate::query::data::count_rows;
use crate::query::filter::{Comparator, Filter, FilterValue};
Expand Down Expand Up @@ -213,7 +213,66 @@ impl ResolvableObject for ErcBalanceObject {
};
ErcTokenType::Erc721(token_metadata)
}
_ => return None,
"erc1155" => {
let token_id =
row.token_id.split(':').collect::<Vec<&str>>();
assert!(token_id.len() == 2);

let metadata_str = row.metadata;
let (
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
) = if metadata_str.is_empty() {
(String::new(), None, None, None, String::new())
} else {
let metadata: serde_json::Value =
serde_json::from_str(&metadata_str)
.expect("metadata is always json");
let metadata_name = metadata.get("name").map(|v| {
v.to_string().trim_matches('"').to_string()
});
let metadata_description =
metadata.get("description").map(|v| {
v.to_string().trim_matches('"').to_string()
});
let metadata_attributes =
metadata.get("attributes").map(|v| {
v.to_string().trim_matches('"').to_string()
});

let image_path =
format!("{}/{}", token_id.join("/"), "image");

(
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
)
};

let token_metadata = Erc1155Token {
name: row.name,
metadata: metadata_str,
contract_address: row.contract_address,
symbol: row.symbol,
token_id: token_id[1].to_string(),
amount: row.balance,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
};
ErcTokenType::Erc1155(token_metadata)
}
_ => {
warn!("Unknown contract type: {}", row.contract_type);
return None;
}
};

Some(Ok(FieldValue::owned_any(balance_value)))
Expand Down Expand Up @@ -427,6 +486,58 @@ fn token_balances_connection_output<'a>(

ErcTokenType::Erc721(token_metadata)
}
"erc1155" => {
// contract_address:token_id
let token_id = row.token_id.split(':').collect::<Vec<&str>>();
assert!(token_id.len() == 2);

let metadata_str = row.metadata;
let (
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
) = if metadata_str.is_empty() {
(String::new(), None, None, None, String::new())
} else {
let metadata: serde_json::Value =
serde_json::from_str(&metadata_str).expect("metadata is always json");
let metadata_name =
metadata.get("name").map(|v| v.to_string().trim_matches('"').to_string());
let metadata_description = metadata
.get("description")
.map(|v| v.to_string().trim_matches('"').to_string());
let metadata_attributes = metadata
.get("attributes")
.map(|v| v.to_string().trim_matches('"').to_string());

let image_path = format!("{}/{}", token_id.join("/"), "image");

(
metadata_str,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
)
};

let token_metadata = Erc1155Token {
name: row.name,
metadata: metadata_str.to_owned(),
contract_address: row.contract_address,
symbol: row.symbol,
token_id: token_id[1].to_string(),
amount: row.balance,
metadata_name,
metadata_description,
metadata_attributes,
image_path,
};

ErcTokenType::Erc1155(token_metadata)
}
_ => {
warn!("Unknown contract type: {}", row.contract_type);
continue;
Expand Down
Loading

0 comments on commit df7cec5

Please sign in to comment.