Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
support identity types (#384)
Browse files Browse the repository at this point in the history
* support identity types

* updates + fix tests

* fix charfield bug

* rebuild wasm

Co-authored-by: Rashad Alston <[email protected]>
  • Loading branch information
ra0x3 and Rashad Alston authored Dec 2, 2022
1 parent ec2ed01 commit d731016
Show file tree
Hide file tree
Showing 36 changed files with 343 additions and 114 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/src/examples/block-explorer.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ mod explorer_index {
id: tx.id,
value: tx_amount,
status: tx.status.clone().into(),
tokens_transferred: Jsonb(
tokens_transferred: Json(
serde_json::to_value(tokens_transferred)
.unwrap()
.to_string(),
Expand Down
2 changes: 1 addition & 1 deletion docs/src/examples/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ mod hello_world_index {
}
None => {
// If we did not already have this Saluation stored in the database. Here we
// show how you can use the String255 type to store strings with length <= 255
// show how you can use the Charfield type to store strings with length <= 255
let message =
format!("{} 👋, my name is {}", &event.greeting, &event.person.name);

Expand Down
6 changes: 3 additions & 3 deletions docs/src/quickstart/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type QueryRoot {
# Calling this `Greeter` so as to not clash with `Person` in the contract
type Greeter {
id: ID!
name: String255!
name: Charfield!
first_seen: UInt8!
last_seen: UInt8!
}
Expand All @@ -103,7 +103,7 @@ type Greeter {
type Salutation {
id: ID!
message_hash: Bytes32!
message: String255!
message: Charfield!
greeter: Greeter!
first_seen: UInt8!
last_seen: UInt8!
Expand Down Expand Up @@ -201,7 +201,7 @@ mod hello_world_index {
}
None => {
// If we did not already have this Saluation stored in the database. Here we
// show how you can use the String255 type to store strings with length <= 255
// show how you can use the Charfield type to store strings with length <= 255
let message =
format!("{} 👋, my name is {}", &event.greeting, &event.person.name);

Expand Down
2 changes: 1 addition & 1 deletion examples/block-explorer/explorer-index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ mod explorer_index {
id: tx.id,
value: tx_amount,
status: tx.status.clone().into(),
tokens_transferred: Jsonb(
tokens_transferred: Json(
serde_json::to_value(tokens_transferred)
.unwrap()
.to_string(),
Expand Down
4 changes: 2 additions & 2 deletions examples/block-explorer/schema/explorer_index.schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ type Tx {
id: Bytes32! @unique
block: Block!
timestamp: Int8!
status: Jsonb!
status: Json!
value: UInt8!
tokens_transferred: Jsonb!
tokens_transferred: Json!
}

type Account {
Expand Down
4 changes: 2 additions & 2 deletions examples/hello-world/hello-index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
extern crate alloc;
use fuel_indexer_macros::indexer;
use fuel_indexer_plugin::{types::Bytes32, utils::sha256_digest};
use fuel_indexer_plugin::prelude::*;

// A utility function used to convert an arbitrarily sized string into Bytes32
// using the first 32 bytes of the String. This might be provided by a standard-ish
Expand Down Expand Up @@ -66,7 +66,7 @@ mod hello_world_index {
}
None => {
// If we did not already have this Saluation stored in the database. Here we
// show how you can use the String255 type to store strings with length <= 255
// show how you can use the Charfield type to store strings with length <= 255
let message =
format!("{} 👋, my name is {}", &event.greeting, &event.person.name);

Expand Down
4 changes: 2 additions & 2 deletions examples/hello-world/schema/hello_index.schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type QueryRoot {
# Calling this `Greeter` so as to not clash with `Person` in the contract
type Greeter {
id: ID!
name: String255!
name: Charfield!
first_seen: UInt8!
last_seen: UInt8!
}
Expand All @@ -19,7 +19,7 @@ type Greeter {
type Salutation {
id: ID!
message_hash: Bytes32!
message: String255!
message: Charfield!
greeter: Greeter!
first_seen: UInt8!
last_seen: UInt8!
Expand Down
25 changes: 15 additions & 10 deletions packages/fuel-indexer-database/database-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ impl NewColumn {
ColumnType::ForeignKey => {
panic!("ForeignKey ColumnType is a reference type only.")
}
ColumnType::Jsonb => "jsonb",
ColumnType::Json => "Json",
ColumnType::MessageId => "varchar(64)",
ColumnType::String255 => "varchar(255)",
ColumnType::Charfield => "varchar(255)",
ColumnType::Identity => "varchar(66)",
}
}
}
Expand Down Expand Up @@ -142,9 +143,10 @@ pub enum ColumnType {
Timestamp = 12,
Blob = 13,
ForeignKey = 14,
Jsonb = 15,
Json = 15,
MessageId = 16,
String255 = 17,
Charfield = 17,
Identity = 18,
}

impl From<ColumnType> for i32 {
Expand All @@ -165,9 +167,10 @@ impl From<ColumnType> for i32 {
ColumnType::Timestamp => 12,
ColumnType::Blob => 13,
ColumnType::ForeignKey => 14,
ColumnType::Jsonb => 15,
ColumnType::Json => 15,
ColumnType::MessageId => 16,
ColumnType::String255 => 17,
ColumnType::Charfield => 17,
ColumnType::Identity => 18,
}
}
}
Expand Down Expand Up @@ -196,9 +199,10 @@ impl From<i32> for ColumnType {
12 => ColumnType::Timestamp,
13 => ColumnType::Blob,
14 => ColumnType::ForeignKey,
15 => ColumnType::Jsonb,
15 => ColumnType::Json,
16 => ColumnType::MessageId,
17 => ColumnType::String255,
17 => ColumnType::Charfield,
18 => ColumnType::Identity,
_ => panic!("Invalid column type."),
}
}
Expand All @@ -222,9 +226,10 @@ impl From<&str> for ColumnType {
"Timestamp" => ColumnType::Timestamp,
"Blob" => ColumnType::Blob,
"ForeignKey" => ColumnType::ForeignKey,
"Jsonb" => ColumnType::Jsonb,
"Json" => ColumnType::Json,
"MessageId" => ColumnType::MessageId,
"String255" => ColumnType::String255,
"Charfield" => ColumnType::Charfield,
"Identity" => ColumnType::Identity,
_ => panic!("Invalid column type: '{}'", name),
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/fuel-indexer-macros/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ fn rust_type(ty: &TypeDeclaration) -> proc_macro2::TokenStream {
"u64" => quote! { u64 },
"b256" => quote! { B256 },
"Log" => quote! { fuel::Log },
"Identity" => quote! { fuel::Identity },
"BlockData" => quote! { BlockData },
"LogData" => quote! { fuel::LogData },
"Transfer" => quote! { fuel::Transfer },
Expand Down
3 changes: 2 additions & 1 deletion packages/fuel-indexer-macros/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ use std::io::Read;
use std::path::{Path, PathBuf};

lazy_static! {
static ref COPY_TYPES: HashSet<&'static str> = HashSet::from(["Jsonb", "String255"]);
static ref COPY_TYPES: HashSet<&'static str> =
HashSet::from(["Json", "Charfield", "Identity"]);
}

fn process_type<'a>(
Expand Down
6 changes: 6 additions & 0 deletions packages/fuel-indexer-plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ pub mod utils {
pub use fuel_indexer_lib::utils::sha256_digest;
}

pub mod prelude {
pub use super::types::*;

pub use super::utils::*;
}

extern "C" {
// TODO: error codes? or just panic and let the runtime handle it?
fn ff_get_object(type_id: u64, ptr: *const u8, len: *mut u8) -> *mut u8;
Expand Down
5 changes: 3 additions & 2 deletions packages/fuel-indexer-schema/src/base.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ scalar Timestamp
scalar Color
scalar ContractId
scalar Salt
scalar Jsonb
scalar Json
scalar MessageId
scalar String255
scalar Charfield
scalar Identity

enum IndexType {
Btree,
Expand Down
12 changes: 6 additions & 6 deletions packages/fuel-indexer-schema/src/explorer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,28 @@
# timestamp: Int8!
# from: Address!
# to: Address!
# tokens_transferred: Jsonb!
# tokens_transferred: Json!
# value: UInt8!
# transaction_fee: UInt8!
# gas_limit: UInt8!
# gas_used: UInt8!
# gas_price: UInt8!
# nonce: Int8!
# input_data: Jsonb!
# input_data: Json!
# }

# type Account {
# address: Address!
# balance: UInt8!
# tokens: Jsonb!
# tokens: Json!
# }


# type Contract {
# creator: Address!
# creation_transaction: Transaction!
# source_code: Jsonb!
# abi: Jsonb!
# creation_code: Jsonb!
# source_code: Json!
# abi: Json!
# creation_code: Json!
# events: Bytes32!
# }
63 changes: 36 additions & 27 deletions packages/fuel-indexer-schema/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@ extern crate alloc;
use crate::sql_types::ColumnType;
use core::convert::TryInto;
use fuel_indexer_types::{
Address, AssetId, Bytes32, Bytes4, Bytes8, ContractId, Jsonb, MessageId, Salt,
Address, AssetId, Bytes32, Bytes4, Bytes8, ContractId, Identity, Json, MessageId,
Salt,
};
use serde::{Deserialize, Serialize};

pub use fuel_indexer_database_types as sql_types;

pub const BASE_SCHEMA: &str = include_str!("./base.graphql");
pub const JOIN_DIRECTIVE_NAME: &str = "foreign_key";
pub const UNIQUE_DIRECTIVE_NAME: &str = "unique";

#[cfg(feature = "db-models")]
pub mod db;

pub mod directives;
pub mod utils;

const MAX_STRING_LEN: usize = 255;
pub const BASE_SCHEMA: &str = include_str!("./base.graphql");
pub const UNIQUE_DIRECTIVE_NAME: &str = "unique";
const MAX_CHARFIELD_LENGTH: usize = 255;

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone, Hash)]
pub enum FtColumn {
Expand All @@ -35,9 +33,10 @@ pub enum FtColumn {
UInt8(u64),
Timestamp(i64),
Salt(Salt),
Jsonb(Jsonb),
Json(Json),
MessageId(MessageId),
String255(String),
Charfield(String),
Identity(Identity),
}

impl FtColumn {
Expand Down Expand Up @@ -119,24 +118,27 @@ impl FtColumn {
ColumnType::ForeignKey => {
panic!("ForeignKey not supported for FtColumn.");
}
ColumnType::Jsonb => FtColumn::Jsonb(Jsonb(
String::from_utf8_lossy(&bytes[..size]).to_string(),
)),
ColumnType::Json => {
FtColumn::Json(Json(String::from_utf8_lossy(&bytes[..size]).to_string()))
}
ColumnType::MessageId => {
let message_id =
MessageId::try_from(&bytes[..size]).expect("Invalid slice length");
FtColumn::MessageId(message_id)
}
ColumnType::String255 => {
let trimmed: Vec<u8> = bytes[..size]
.iter()
.filter_map(|x| if *x != b' ' { Some(*x) } else { None })
.collect();

let s = String::from_utf8_lossy(&trimmed).to_string();
ColumnType::Charfield => {
let s = String::from_utf8_lossy(&bytes[..size]).trim().to_string();

assert!(s.len() <= MAX_STRING_LEN, "String255 exceeds max length.");
FtColumn::String255(s)
assert!(
s.len() <= MAX_CHARFIELD_LENGTH,
"Charfield exceeds max length."
);
FtColumn::Charfield(s)
}
ColumnType::Identity => {
let identity =
Identity::try_from(&bytes[..size]).expect("Invalid slice length");
FtColumn::Identity(identity)
}
}
}
Expand Down Expand Up @@ -182,15 +184,19 @@ impl FtColumn {
FtColumn::Salt(value) => {
format!("'{:x}'", value)
}
FtColumn::Jsonb(value) => {
FtColumn::Json(value) => {
format!("'{}'", value.0)
}
FtColumn::MessageId(value) => {
format!("'{:x}'", value)
}
FtColumn::String255(value) => {
FtColumn::Charfield(value) => {
format!("'{}'", value)
}
FtColumn::Identity(value) => match value {
Identity::Address(v) => format!("'00{:x}'", v),
Identity::ContractId(v) => format!("'01{:x}'", v),
},
}
}
}
Expand Down Expand Up @@ -218,8 +224,10 @@ mod tests {
let salt = FtColumn::Salt(Salt::try_from([0x31; 32]).expect("Bad bytes"));
let message_id =
FtColumn::MessageId(MessageId::try_from([0x0F; 32]).expect("Bad bytes"));
let string255 = FtColumn::String255(String::from("hello world"));
let jsonb = FtColumn::Jsonb(Jsonb(r#"{"hello":"world"}"#.to_string()));
let charfield = FtColumn::Charfield(String::from("hello world"));
let json = FtColumn::Json(Json(r#"{"hello":"world"}"#.to_string()));
let identity =
FtColumn::Identity(Identity::Address(Address::try_from([0x12; 32]).unwrap()));

insta::assert_yaml_snapshot!(id.query_fragment());
insta::assert_yaml_snapshot!(addr.query_fragment());
Expand All @@ -235,7 +243,8 @@ mod tests {
insta::assert_yaml_snapshot!(uint8.query_fragment());
insta::assert_yaml_snapshot!(int64.query_fragment());
insta::assert_yaml_snapshot!(message_id.query_fragment());
insta::assert_yaml_snapshot!(string255.query_fragment());
insta::assert_yaml_snapshot!(jsonb.query_fragment())
insta::assert_yaml_snapshot!(charfield.query_fragment());
insta::assert_yaml_snapshot!(json.query_fragment());
insta::assert_yaml_snapshot!(identity.query_fragment());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
source: fuel-indexer-schema/src/lib.rs
assertion_line: 234
expression: string255.query_fragment()
expression: Charfield.query_fragment()
---
"'hello world'"

Loading

0 comments on commit d731016

Please sign in to comment.