From 50be87281d4882aaa3c7ca827db9274e7ff6ad75 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 13:09:18 +0200 Subject: [PATCH 01/21] add owned message ids --- fuel-core/src/database.rs | 4 +- fuel-core/src/database/message.rs | 63 +++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/fuel-core/src/database.rs b/fuel-core/src/database.rs index d0f3bef991f..cef2cc1a891 100644 --- a/fuel-core/src/database.rs +++ b/fuel-core/src/database.rs @@ -76,10 +76,12 @@ pub mod columns { pub const STAKING_DIFFS: u32 = 16; /// Maps delegate address with validator_set_diff index where last delegate change happened pub const DELEGATES_INDEX: u32 = 17; + // (Owner, MessageId) => true + pub const OWNED_MESSAGE_IDS: u32 = 18; // Number of columns #[cfg(feature = "rocksdb")] - pub const COLUMN_NUM: u32 = 18; + pub const COLUMN_NUM: u32 = 19; } #[derive(Clone, Debug)] diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index 4cb8fe4e81b..d11758d580f 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -1,6 +1,12 @@ -use crate::database::{columns, Database, KvStoreError}; +use crate::{ + database::{columns, Database, KvStoreError}, + state::{Error, IterDirection}, +}; use fuel_core_interfaces::{ - common::{fuel_storage::Storage, fuel_types::MessageId}, + common::{ + fuel_storage::Storage, + fuel_types::{Address, Bytes32, MessageId}, + }, model::DaMessage, }; use std::borrow::Cow; @@ -13,12 +19,31 @@ impl Storage for Database { key: &MessageId, value: &DaMessage, ) -> Result, KvStoreError> { + // insert secondary record by owner + Database::insert( + self, + owner_msg_id_key(&value.owner, key), + columns::OWNED_MESSAGE_IDS, + true, + )?; + + // insert primary record Database::insert(self, key.as_ref(), columns::DA_MESSAGES, value.clone()) .map_err(Into::into) } fn remove(&mut self, key: &MessageId) -> Result, KvStoreError> { - Database::remove(self, key.as_ref(), columns::DA_MESSAGES).map_err(Into::into) + let result: Option = Database::remove(self, key.as_ref(), columns::DA_MESSAGES)?; + + if let Some(da_msg) = &result { + Database::remove::( + self, + &owner_msg_id_key(&da_msg.owner, key), + columns::OWNED_MESSAGE_IDS, + )?; + } + + Ok(result) } fn get(&self, key: &MessageId) -> Result>, KvStoreError> { @@ -29,3 +54,35 @@ impl Storage for Database { Database::exists(self, key.as_ref(), columns::DA_MESSAGES).map_err(Into::into) } } + +impl Database { + pub fn owned_message_ids( + &self, + owner: Address, + start_message_id: Option, + direction: Option, + ) -> impl Iterator> + '_ { + self.iter_all::, bool>( + columns::OWNED_MESSAGE_IDS, + Some(owner.as_ref().to_vec()), + start_message_id.map(|msg_id| owner_msg_id_key(&owner, &msg_id)), + direction, + ) + // Safety: key is always 64 bytes + .map(|res| { + res.map(|(key, _)| { + MessageId::new(unsafe { *Bytes32::from_slice_unchecked(&key[32..64]) }) + }) + }) + } +} + +/// Get a Key by chaining Owner + MessageId +fn owner_msg_id_key(owner: &Address, msg_id: &MessageId) -> Vec { + owner + .as_ref() + .iter() + .chain(msg_id.as_ref().iter()) + .copied() + .collect() +} From 6e0f876c25fd933f30cf8017530b40a31eed154c Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 14:00:50 +0200 Subject: [PATCH 02/21] add a test for owned message ids --- fuel-core/src/database/message.rs | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index d11758d580f..72e0e355252 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -86,3 +86,39 @@ fn owner_msg_id_key(owner: &Address, msg_id: &MessageId) -> Vec { .copied() .collect() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn owned_message_ids() { + let mut db = Database::default(); + let da_msg = DaMessage::default(); + + // insert a message with the first id + let first_id = MessageId::new([1; 32]); + let _ = Storage::::insert(&mut db, &first_id, &da_msg).unwrap(); + + // insert a message with the second id with the same Owner + let second_id = MessageId::new([2; 32]); + let _ = Storage::::insert(&mut db, &second_id, &da_msg).unwrap(); + + // verify that 2 message IDs are associated with a single Owner + let owned_msg_ids: Vec<_> = db.owned_message_ids(da_msg.owner, None, None).collect(); + assert_eq!(owned_msg_ids.len(), 2); + + // remove the first message with its given id + let _ = Storage::::remove(&mut db, &first_id).unwrap(); + + // verify that only second ID is left + let owned_msg_ids: Vec<_> = db.owned_message_ids(da_msg.owner, None, None).collect(); + assert_eq!(owned_msg_ids.first().unwrap().as_ref().unwrap(), &second_id); + assert_eq!(owned_msg_ids.len(), 1); + + // remove the second message with its given id + let _ = Storage::::remove(&mut db, &second_id).unwrap(); + let owned_msg_ids: Vec<_> = db.owned_message_ids(da_msg.owner, None, None).collect(); + assert_eq!(owned_msg_ids.len(), 0); + } +} From f0f5fa39eb1befe8bb235548fcf50ba520f366bd Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 14:20:14 +0200 Subject: [PATCH 03/21] don't collect the iterator --- fuel-core/src/database/message.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index 72e0e355252..a2dadc3ae51 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -89,6 +89,8 @@ fn owner_msg_id_key(owner: &Address, msg_id: &MessageId) -> Vec { #[cfg(test)] mod tests { + use tracing::log::kv::Source; + use super::*; #[test] @@ -118,7 +120,7 @@ mod tests { // remove the second message with its given id let _ = Storage::::remove(&mut db, &second_id).unwrap(); - let owned_msg_ids: Vec<_> = db.owned_message_ids(da_msg.owner, None, None).collect(); - assert_eq!(owned_msg_ids.len(), 0); + let owned_msg_ids = db.owned_message_ids(da_msg.owner, None, None); + assert_eq!(owned_msg_ids.count(), 0); } } From 4261c27e38372a5c4384a9175c8e62c62c763c8c Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 14:25:32 +0200 Subject: [PATCH 04/21] remove accidently imported type --- fuel-core/src/database/message.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index a2dadc3ae51..926275751ab 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -89,8 +89,6 @@ fn owner_msg_id_key(owner: &Address, msg_id: &MessageId) -> Vec { #[cfg(test)] mod tests { - use tracing::log::kv::Source; - use super::*; #[test] From 086a4e62f5f6dd8ea0078342cc2aaf08bb17c979 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 15:04:44 +0200 Subject: [PATCH 05/21] remove collect) --- fuel-core/src/database/message.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index 926275751ab..f660694f002 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -105,8 +105,8 @@ mod tests { let _ = Storage::::insert(&mut db, &second_id, &da_msg).unwrap(); // verify that 2 message IDs are associated with a single Owner - let owned_msg_ids: Vec<_> = db.owned_message_ids(da_msg.owner, None, None).collect(); - assert_eq!(owned_msg_ids.len(), 2); + let owned_msg_ids = db.owned_message_ids(da_msg.owner, None, None); + assert_eq!(owned_msg_ids.count(), 2); // remove the first message with its given id let _ = Storage::::remove(&mut db, &first_id).unwrap(); From 73a9034fdb3ae8971e867c83164a071f19b32728 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Thu, 4 Aug 2022 21:27:13 +0200 Subject: [PATCH 06/21] primary record insertion first --- fuel-core/src/database/message.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index f660694f002..edb6a65c5be 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -19,6 +19,9 @@ impl Storage for Database { key: &MessageId, value: &DaMessage, ) -> Result, KvStoreError> { + // insert primary record + let result = Database::insert(self, key.as_ref(), columns::DA_MESSAGES, value.clone())?; + // insert secondary record by owner Database::insert( self, @@ -27,9 +30,7 @@ impl Storage for Database { true, )?; - // insert primary record - Database::insert(self, key.as_ref(), columns::DA_MESSAGES, value.clone()) - .map_err(Into::into) + Ok(result) } fn remove(&mut self, key: &MessageId) -> Result, KvStoreError> { From adf2e2ddbeff3cdaa74ec119edc87c064b6a73a8 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Fri, 5 Aug 2022 18:15:41 +0200 Subject: [PATCH 07/21] add messages() and messages_by_owner() to the MessageQuery --- fuel-client/assets/schema.sdl | 42 +++++ fuel-core/src/database/message.rs | 24 +++ fuel-core/src/schema.rs | 4 +- fuel-core/src/schema/message.rs | 257 ++++++++++++++++++++++++++++++ fuel-core/src/schema/scalars.rs | 22 +++ fuel-tests/tests/lib.rs | 1 + 6 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 fuel-core/src/schema/message.rs diff --git a/fuel-client/assets/schema.sdl b/fuel-client/assets/schema.sdl index 25cb40c84f7..bace3c23f6c 100644 --- a/fuel-client/assets/schema.sdl +++ b/fuel-client/assets/schema.sdl @@ -243,6 +243,46 @@ type ContractOutput { stateRoot: Bytes32! } +type DaMessage { + amount: U64! + sender: Address! + recipient: Address! + owner: Address! + nonce: U64! + data: [Int!]! + daHeight: U64! + fuelBlockSpend: Int +} + +type DaMessageConnection { + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + """ + A list of edges. + """ + edges: [DaMessageEdge!]! + """ + A list of nodes. + """ + nodes: [DaMessage!]! +} + +""" +An edge in a connection. +""" +type DaMessageEdge { + """ + A cursor for use in pagination + """ + cursor: String! + """ + The item at the end of the edge + """ + node: DaMessage! +} + """ Implement the DateTime scalar @@ -399,6 +439,8 @@ type Query { contractBalance(contract: ContractId!, asset: AssetId!): ContractBalance! contractBalances(filter: ContractBalanceFilterInput!, first: Int, after: String, last: Int, before: String): ContractBalanceConnection! nodeInfo: NodeInfo! + messagesByOwner(owner: Address!, first: Int, after: String, last: Int, before: String): DaMessageConnection! + messages(first: Int, after: String, last: Int, before: String): DaMessageConnection! } type Receipt { diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index edb6a65c5be..62fe2cc2948 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -1,5 +1,6 @@ use crate::{ database::{columns, Database, KvStoreError}, + schema::scalars::OwnerAndMessageIdCursor, state::{Error, IterDirection}, }; use fuel_core_interfaces::{ @@ -76,6 +77,29 @@ impl Database { }) }) } + + pub fn all_owners_and_message_ids( + &self, + start: Option, + direction: Option, + ) -> impl Iterator> + '_ { + let start = start.map(|v| owner_msg_id_key(&v.owner.into(), &v.message_id.into())); + self.iter_all::, bool>(columns::OWNED_MESSAGE_IDS, None, start, direction) + .map(|res| { + res.map(|(key, _)| { + // Safety: key is always 64 bytes + unsafe { + OwnerAndMessageIdCursor { + owner: Address::from_slice_unchecked(&key[0..32]).into(), + message_id: MessageId::new(*Bytes32::from_slice_unchecked( + &key[32..64], + )) + .into(), + } + } + }) + }) + } } /// Get a Key by chaining Owner + MessageId diff --git a/fuel-core/src/schema.rs b/fuel-core/src/schema.rs index 8aba43b9b39..6c5726aa62d 100644 --- a/fuel-core/src/schema.rs +++ b/fuel-core/src/schema.rs @@ -7,6 +7,7 @@ pub mod coin; pub mod contract; pub mod dap; pub mod health; +pub mod message; pub mod node_info; pub mod scalars; pub mod tx; @@ -23,6 +24,7 @@ pub struct Query( contract::ContractQuery, contract::ContractBalanceQuery, node_info::NodeQuery, + message::MessageQuery, ); #[derive(MergedObject, Default)] @@ -39,6 +41,6 @@ pub fn build_schema() -> SchemaBuilder { Query::default(), Mutation::default(), EmptySubscription::default(), - ["TransactionConnection"], + ["TransactionConnection", "DaMessageConnection"], ) } diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs new file mode 100644 index 00000000000..1ed8f712b3e --- /dev/null +++ b/fuel-core/src/schema/message.rs @@ -0,0 +1,257 @@ +use anyhow::anyhow; +use async_graphql::{ + connection::{self, Connection, Edge, EmptyFields}, + Context, Object, +}; +use fuel_core_interfaces::{ + common::{fuel_storage::Storage, fuel_types}, + db::KvStoreError, + model, +}; +use itertools::Itertools; +use std::borrow::Cow; + +use crate::{database::Database, state::IterDirection}; + +use super::scalars::{Address, MessageId, OwnerAndMessageIdCursor, U64}; + +pub struct DaMessage(pub(crate) model::DaMessage); + +#[Object] +impl DaMessage { + async fn amount(&self) -> U64 { + self.0.amount.into() + } + + async fn sender(&self) -> Address { + self.0.sender.into() + } + + async fn recipient(&self) -> Address { + self.0.recipient.into() + } + + async fn owner(&self) -> Address { + self.0.owner.into() + } + + async fn nonce(&self) -> U64 { + self.0.nonce.into() + } + + async fn data(&self) -> &Vec { + &self.0.data + } + + async fn da_height(&self) -> U64 { + self.0.da_height.into() + } + + async fn fuel_block_spend(&self) -> Option { + self.0.fuel_block_spend.map(|v| v.into()) + } +} + +#[derive(Default)] +pub struct MessageQuery {} + +#[Object] +impl MessageQuery { + async fn messages_by_owner( + &self, + ctx: &Context<'_>, + owner: Address, + first: Option, + after: Option, + last: Option, + before: Option, + ) -> async_graphql::Result> { + let db = ctx.data_unchecked::().clone(); + + connection::query( + after, + before, + first, + last, + |after: Option, before: Option, first, last| async move { + let (records_to_fetch, direction) = if let Some(first) = first { + (first, IterDirection::Forward) + } else if let Some(last) = last { + (last, IterDirection::Reverse) + } else { + (0, IterDirection::Forward) + }; + + if (first.is_some() && before.is_some()) + || (after.is_some() && before.is_some()) + || (last.is_some() && after.is_some()) + { + return Err(anyhow!("Wrong argument combination")); + } + + let start; + let end; + + if direction == IterDirection::Forward { + start = after; + end = before; + } else { + start = before; + end = after; + } + + let mut message_ids = + db.owned_message_ids(owner.into(), start.map(Into::into), Some(direction)); + let mut started = None; + if start.is_some() { + // skip initial result + started = message_ids.next(); + } + + let compare_end = end.map(|v| v.into()); + + let message_ids = message_ids + .map(|msg_id| msg_id.into()) + .take_while(|r| { + if let (Ok(next), Some(end)) = (r, &compare_end) { + if next == end { + return false; + } + } + true + }) + .take(records_to_fetch); + + let mut message_ids: Vec = message_ids.try_collect()?; + if direction == IterDirection::Forward { + message_ids.reverse(); + } + + let messages: Vec> = message_ids + .iter() + .map(|msg_id| { + Storage::::get(&db, msg_id.into()) + .transpose() + .ok_or(KvStoreError::NotFound)? + }) + .try_collect()?; + + let mut connection = + Connection::new(started.is_some(), records_to_fetch <= messages.len()); + + connection + .edges + .extend( + messages + .into_iter() + .zip(message_ids) + .map(|(message, msg_id)| { + Edge::new(msg_id.into(), DaMessage(message.into_owned())) + }), + ); + + Ok::, anyhow::Error>(connection) + }, + ) + .await + } + + async fn messages( + &self, + ctx: &Context<'_>, + first: Option, + after: Option, + last: Option, + before: Option, + ) -> async_graphql::Result< + Connection, + > { + let db = ctx.data_unchecked::().clone(); + + connection::query( + after, + before, + first, + last, + |after: Option, + before: Option, + first, + last| async move { + let (records_to_fetch, direction) = if let Some(first) = first { + (first, IterDirection::Forward) + } else if let Some(last) = last { + (last, IterDirection::Reverse) + } else { + (0, IterDirection::Forward) + }; + + if (first.is_some() && before.is_some()) + || (after.is_some() && before.is_some()) + || (last.is_some() && after.is_some()) + { + return Err(anyhow!("Wrong argument combination")); + } + + let start; + let end; + + if direction == IterDirection::Forward { + start = after; + end = before; + } else { + start = before; + end = after; + } + + let mut message_ids = db.all_owners_and_message_ids(start.clone(), Some(direction)); + let mut started = None; + if start.is_some() { + // skip initial result + started = message_ids.next(); + } + + let message_ids = message_ids + .take_while(|r| { + if let (Ok(next), Some(end)) = (r, &end) { + if next.message_id.0 == end.message_id.0 { + return false; + } + } + true + }) + .take(records_to_fetch); + + let mut message_ids: Vec = message_ids.try_collect()?; + if direction == IterDirection::Forward { + message_ids.reverse(); + } + + let messages: Vec> = message_ids + .iter() + .map(|value| { + Storage::::get( + &db, + &value.message_id.into(), + ) + .transpose() + .ok_or(KvStoreError::NotFound)? + }) + .try_collect()?; + + let mut connection = + Connection::new(started.is_some(), records_to_fetch <= messages.len()); + + connection + .edges + .extend(messages.into_iter().zip(message_ids).map( + |(message, owner_msg_id)| { + Edge::new(owner_msg_id, DaMessage(message.into_owned())) + }, + )); + + Ok::, anyhow::Error>(connection) + }, + ) + .await + } +} diff --git a/fuel-core/src/schema/scalars.rs b/fuel-core/src/schema/scalars.rs index c70b3a06382..99350b4ee90 100644 --- a/fuel-core/src/schema/scalars.rs +++ b/fuel-core/src/schema/scalars.rs @@ -56,6 +56,28 @@ impl SortedTxCursor { } } } +#[derive(Clone, Debug)] +pub struct OwnerAndMessageIdCursor { + pub owner: Address, + pub message_id: MessageId, +} + +impl CursorType for OwnerAndMessageIdCursor { + type Error = String; + + fn decode_cursor(s: &str) -> Result { + let (owner, msg_id) = s.split_once('#').ok_or("Incorrect format provided")?; + + Ok(OwnerAndMessageIdCursor { + owner: Address::from_str(owner)?, + message_id: MessageId::from_str(msg_id)?, + }) + } + + fn encode_cursor(&self) -> String { + format!("{}#{}", self.owner, self.message_id) + } +} impl CursorType for SortedTxCursor { type Error = String; diff --git a/fuel-tests/tests/lib.rs b/fuel-tests/tests/lib.rs index f05bef1889b..ae464ff9fa1 100644 --- a/fuel-tests/tests/lib.rs +++ b/fuel-tests/tests/lib.rs @@ -7,6 +7,7 @@ mod dap; mod debugger; mod health; mod helpers; +mod messages; mod node_info; mod snapshot; mod tx; From 817af1878f80330ff873879375669d016f7827b1 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Fri, 5 Aug 2022 18:15:50 +0200 Subject: [PATCH 08/21] initial test setup for messages and messages_by_owner --- fuel-tests/tests/messages.rs | 43 ++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 fuel-tests/tests/messages.rs diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs new file mode 100644 index 00000000000..5aaf1a61f7a --- /dev/null +++ b/fuel-tests/tests/messages.rs @@ -0,0 +1,43 @@ +use fuel_core::{config::Config, database::Database, service::FuelService}; +use fuel_core_interfaces::common::fuel_storage::Storage; +use fuel_core_interfaces::model::DaMessage; +use fuel_crypto::fuel_types::{Address, MessageId}; +use fuel_gql_client::client::FuelClient; + +#[tokio::test] +async fn messages() { + // setup server & client + let mut db = Database::default(); + let srv = FuelService::from_database(db.clone(), Config::local_node()) + .await + .unwrap(); + let _client = FuelClient::from(srv.bound_address); + + // create some owners + let owner_a = Address::new([1; 32]); + let owner_b = Address::new([2; 32]); + + // create some messages for owner A + let mut first_msg = DaMessage::default(); + first_msg.owner = owner_a; + let mut second_msg = DaMessage::default(); + second_msg.owner = owner_a; + + // create a message for owner B + let mut third_msg = DaMessage::default(); + third_msg.owner = owner_b; + + // store the messaages + let first_id = MessageId::new([1; 32]); + let _ = Storage::::insert(&mut db, &first_id, &first_msg).unwrap(); + + let second_id = MessageId::new([2; 32]); + let _ = Storage::::insert(&mut db, &second_id, &second_msg).unwrap(); + + let third_id = MessageId::new([3; 32]); + let _ = Storage::::insert(&mut db, &third_id, &third_msg).unwrap(); + + // get the messages + + // get the messages by owner +} From eb641085112de4fe5a77cec4a6ce25781232d1a1 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Fri, 5 Aug 2022 18:32:15 +0200 Subject: [PATCH 09/21] remove map() --- fuel-core/src/schema/message.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 1ed8f712b3e..98a14452885 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -111,7 +111,6 @@ impl MessageQuery { let compare_end = end.map(|v| v.into()); let message_ids = message_ids - .map(|msg_id| msg_id.into()) .take_while(|r| { if let (Ok(next), Some(end)) = (r, &compare_end) { if next == end { From a9b2f9c2f4aa008fac9db7f6bdb1bda4061c9c22 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Fri, 5 Aug 2022 18:33:26 +0200 Subject: [PATCH 10/21] rename struct --- fuel-core/src/database/message.rs | 8 ++++---- fuel-core/src/schema/message.rs | 15 +++++++-------- fuel-core/src/schema/scalars.rs | 6 +++--- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index 62fe2cc2948..3955edbe3b5 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -1,6 +1,6 @@ use crate::{ database::{columns, Database, KvStoreError}, - schema::scalars::OwnerAndMessageIdCursor, + schema::scalars::OwnerAndMessageId, state::{Error, IterDirection}, }; use fuel_core_interfaces::{ @@ -80,16 +80,16 @@ impl Database { pub fn all_owners_and_message_ids( &self, - start: Option, + start: Option, direction: Option, - ) -> impl Iterator> + '_ { + ) -> impl Iterator> + '_ { let start = start.map(|v| owner_msg_id_key(&v.owner.into(), &v.message_id.into())); self.iter_all::, bool>(columns::OWNED_MESSAGE_IDS, None, start, direction) .map(|res| { res.map(|(key, _)| { // Safety: key is always 64 bytes unsafe { - OwnerAndMessageIdCursor { + OwnerAndMessageId { owner: Address::from_slice_unchecked(&key[0..32]).into(), message_id: MessageId::new(*Bytes32::from_slice_unchecked( &key[32..64], diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 98a14452885..caa7f92c094 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; use crate::{database::Database, state::IterDirection}; -use super::scalars::{Address, MessageId, OwnerAndMessageIdCursor, U64}; +use super::scalars::{Address, MessageId, OwnerAndMessageId, U64}; pub struct DaMessage(pub(crate) model::DaMessage); @@ -162,9 +162,8 @@ impl MessageQuery { after: Option, last: Option, before: Option, - ) -> async_graphql::Result< - Connection, - > { + ) -> async_graphql::Result> + { let db = ctx.data_unchecked::().clone(); connection::query( @@ -172,8 +171,8 @@ impl MessageQuery { before, first, last, - |after: Option, - before: Option, + |after: Option, + before: Option, first, last| async move { let (records_to_fetch, direction) = if let Some(first) = first { @@ -220,7 +219,7 @@ impl MessageQuery { }) .take(records_to_fetch); - let mut message_ids: Vec = message_ids.try_collect()?; + let mut message_ids: Vec = message_ids.try_collect()?; if direction == IterDirection::Forward { message_ids.reverse(); } @@ -248,7 +247,7 @@ impl MessageQuery { }, )); - Ok::, anyhow::Error>(connection) + Ok::, anyhow::Error>(connection) }, ) .await diff --git a/fuel-core/src/schema/scalars.rs b/fuel-core/src/schema/scalars.rs index 99350b4ee90..0736315bcf1 100644 --- a/fuel-core/src/schema/scalars.rs +++ b/fuel-core/src/schema/scalars.rs @@ -57,18 +57,18 @@ impl SortedTxCursor { } } #[derive(Clone, Debug)] -pub struct OwnerAndMessageIdCursor { +pub struct OwnerAndMessageId { pub owner: Address, pub message_id: MessageId, } -impl CursorType for OwnerAndMessageIdCursor { +impl CursorType for OwnerAndMessageId { type Error = String; fn decode_cursor(s: &str) -> Result { let (owner, msg_id) = s.split_once('#').ok_or("Incorrect format provided")?; - Ok(OwnerAndMessageIdCursor { + Ok(OwnerAndMessageId { owner: Address::from_str(owner)?, message_id: MessageId::from_str(msg_id)?, }) From c783ed5082945d7dc69129411f5f09f42a6afc44 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 5 Aug 2022 20:23:10 -0400 Subject: [PATCH 11/21] Fix clippy --- fuel-core/src/schema/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index caa7f92c094..3d88aa9a3e9 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -129,7 +129,7 @@ impl MessageQuery { let messages: Vec> = message_ids .iter() .map(|msg_id| { - Storage::::get(&db, msg_id.into()) + Storage::::get(&db, msg_id) .transpose() .ok_or(KvStoreError::NotFound)? }) From 28f7029cc950751180d20e2313988e67932ee872 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 5 Aug 2022 21:33:02 -0400 Subject: [PATCH 12/21] Fix more clippy --- fuel-tests/tests/messages.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index 5aaf1a61f7a..9d288dbf311 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -18,14 +18,20 @@ async fn messages() { let owner_b = Address::new([2; 32]); // create some messages for owner A - let mut first_msg = DaMessage::default(); - first_msg.owner = owner_a; - let mut second_msg = DaMessage::default(); - second_msg.owner = owner_a; + let mut first_msg = DaMessage { + owner: owner_a, + ..Default::default() + }; + let mut second_msg = DaMessage { + owner: owner_a, + ..Default::default() + }; // create a message for owner B - let mut third_msg = DaMessage::default(); - third_msg.owner = owner_b; + let mut third_msg = DaMessage { + owner: owner_b, + ..Default::default() + }; // store the messaages let first_id = MessageId::new([1; 32]); From 064f146eb6c0859fe185c2d67be253b2aa03b7ba Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 5 Aug 2022 21:38:48 -0400 Subject: [PATCH 13/21] Fix more clippy --- fuel-client/src/client.rs | 4 ++++ fuel-tests/tests/messages.rs | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fuel-client/src/client.rs b/fuel-client/src/client.rs index 3879b29ebb5..2070884ade9 100644 --- a/fuel-client/src/client.rs +++ b/fuel-client/src/client.rs @@ -446,6 +446,10 @@ impl FuelClient { Ok(balances) } + + // pub async fn messages( + // &self + // ) -> io::Result> } #[cfg(any(test, feature = "test-helpers"))] diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index 9d288dbf311..f2f21a12460 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -18,17 +18,17 @@ async fn messages() { let owner_b = Address::new([2; 32]); // create some messages for owner A - let mut first_msg = DaMessage { + let first_msg = DaMessage { owner: owner_a, ..Default::default() }; - let mut second_msg = DaMessage { + let second_msg = DaMessage { owner: owner_a, ..Default::default() }; // create a message for owner B - let mut third_msg = DaMessage { + let third_msg = DaMessage { owner: owner_b, ..Default::default() }; From e856efc58f4fa18120fee14a94cdab4da1a6b104 Mon Sep 17 00:00:00 2001 From: Brandon Kite Date: Fri, 5 Aug 2022 19:41:55 -0700 Subject: [PATCH 14/21] fix has_next_page --- fuel-core/src/schema/message.rs | 34 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 3d88aa9a3e9..a59e8022dd7 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -90,14 +90,11 @@ impl MessageQuery { } let start; - let end; if direction == IterDirection::Forward { start = after; - end = before; } else { start = before; - end = after; } let mut message_ids = @@ -108,26 +105,14 @@ impl MessageQuery { started = message_ids.next(); } - let compare_end = end.map(|v| v.into()); + let message_ids = message_ids.take(records_to_fetch + 1); - let message_ids = message_ids - .take_while(|r| { - if let (Ok(next), Some(end)) = (r, &compare_end) { - if next == end { - return false; - } - } - true - }) - .take(records_to_fetch); + let message_ids: Vec = message_ids.try_collect()?; + let has_next_page = message_ids.len() > records_to_fetch; - let mut message_ids: Vec = message_ids.try_collect()?; - if direction == IterDirection::Forward { - message_ids.reverse(); - } - - let messages: Vec> = message_ids + let mut messages: Vec> = message_ids .iter() + .take(records_to_fetch) .map(|msg_id| { Storage::::get(&db, msg_id) .transpose() @@ -135,8 +120,13 @@ impl MessageQuery { }) .try_collect()?; - let mut connection = - Connection::new(started.is_some(), records_to_fetch <= messages.len()); + // reverse after filtering next page test record to maintain consistent ordering + // in the response regardless of whether first or last was used. + if direction == IterDirection::Forward { + messages.reverse(); + } + + let mut connection = Connection::new(started.is_some(), has_next_page); connection .edges From feaa3e6337c86b9e9653a0ab571f5191037e0e1d Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Sat, 6 Aug 2022 00:24:07 -0400 Subject: [PATCH 15/21] Refactor all messages next_page --- fuel-core/src/schema/message.rs | 32 ++++++++++---------------------- fuel-tests/tests/messages.rs | 2 +- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index a59e8022dd7..77c9f461ca3 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -106,7 +106,6 @@ impl MessageQuery { } let message_ids = message_ids.take(records_to_fetch + 1); - let message_ids: Vec = message_ids.try_collect()?; let has_next_page = message_ids.len() > records_to_fetch; @@ -181,14 +180,11 @@ impl MessageQuery { } let start; - let end; if direction == IterDirection::Forward { start = after; - end = before; } else { start = before; - end = after; } let mut message_ids = db.all_owners_and_message_ids(start.clone(), Some(direction)); @@ -198,24 +194,13 @@ impl MessageQuery { started = message_ids.next(); } - let message_ids = message_ids - .take_while(|r| { - if let (Ok(next), Some(end)) = (r, &end) { - if next.message_id.0 == end.message_id.0 { - return false; - } - } - true - }) - .take(records_to_fetch); - - let mut message_ids: Vec = message_ids.try_collect()?; - if direction == IterDirection::Forward { - message_ids.reverse(); - } + let message_ids = message_ids.take(records_to_fetch + 1); + let message_ids: Vec = message_ids.try_collect()?; + let has_next_page = message_ids.len() > records_to_fetch; - let messages: Vec> = message_ids + let mut messages: Vec> = message_ids .iter() + .take(records_to_fetch) .map(|value| { Storage::::get( &db, @@ -226,8 +211,11 @@ impl MessageQuery { }) .try_collect()?; - let mut connection = - Connection::new(started.is_some(), records_to_fetch <= messages.len()); + if direction == IterDirection::Forward { + messages.reverse(); + } + + let mut connection = Connection::new(started.is_some(), has_next_page); connection .edges diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index f2f21a12460..4da44ed5498 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -33,7 +33,7 @@ async fn messages() { ..Default::default() }; - // store the messaages + // store the messages let first_id = MessageId::new([1; 32]); let _ = Storage::::insert(&mut db, &first_id, &first_msg).unwrap(); From 996f0ac5b585fa88f7db2f1fdf1ce7f01f28f11a Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Mon, 8 Aug 2022 15:31:30 +0200 Subject: [PATCH 16/21] update schema field to U64 --- fuel-client/assets/schema.sdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuel-client/assets/schema.sdl b/fuel-client/assets/schema.sdl index bace3c23f6c..87ce1803a4f 100644 --- a/fuel-client/assets/schema.sdl +++ b/fuel-client/assets/schema.sdl @@ -251,7 +251,7 @@ type DaMessage { nonce: U64! data: [Int!]! daHeight: U64! - fuelBlockSpend: Int + fuelBlockSpend: U64 } type DaMessageConnection { From 3871a26074fbfd8bbcf55224626210e24154ea26 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Mon, 8 Aug 2022 15:32:24 +0200 Subject: [PATCH 17/21] expose messages API --- fuel-client/src/client.rs | 13 +++- fuel-client/src/client/schema.rs | 3 +- fuel-client/src/client/schema/message.rs | 64 +++++++++++++++++++ ...e__tests__da_message_query_gql_output.snap | 28 ++++++++ fuel-core/src/schema/message.rs | 2 +- fuel-tests/tests/messages.rs | 15 ++++- 6 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 fuel-client/src/client/schema/message.rs create mode 100644 fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap diff --git a/fuel-client/src/client.rs b/fuel-client/src/client.rs index 2070884ade9..ea993b8d498 100644 --- a/fuel-client/src/client.rs +++ b/fuel-client/src/client.rs @@ -447,9 +447,16 @@ impl FuelClient { Ok(balances) } - // pub async fn messages( - // &self - // ) -> io::Result> + pub async fn messages( + &self, + request: PaginationRequest, + ) -> io::Result> { + let query = schema::message::DaMessageQuery::build(&request.into()); + + let messages = self.query(query).await?.messages.into(); + + Ok(messages) + } } #[cfg(any(test, feature = "test-helpers"))] diff --git a/fuel-client/src/client/schema.rs b/fuel-client/src/client/schema.rs index 7793b6907dc..92b7c9b6567 100644 --- a/fuel-client/src/client/schema.rs +++ b/fuel-client/src/client/schema.rs @@ -18,6 +18,7 @@ pub mod block; pub mod chain; pub mod coin; pub mod contract; +pub mod message; pub mod node_info; pub mod primitives; pub mod tx; @@ -221,7 +222,7 @@ pub struct OutputBreakpoint { } /// Generic graphql pagination query args -#[derive(cynic::FragmentArguments, Debug)] +#[derive(cynic::FragmentArguments, Debug, Default)] pub struct ConnectionArgs { /// Skip until cursor (forward pagination) pub after: Option, diff --git a/fuel-client/src/client/schema/message.rs b/fuel-client/src/client/schema/message.rs new file mode 100644 index 00000000000..004b12d9f91 --- /dev/null +++ b/fuel-client/src/client/schema/message.rs @@ -0,0 +1,64 @@ +use crate::client::schema::{schema, Address, ConnectionArgs, U64}; + +use super::{PageInfo, PaginatedResult}; + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(schema_path = "./assets/schema.sdl")] +pub struct DaMessage { + pub amount: U64, + pub sender: Address, + pub recipient: Address, + pub owner: Address, + pub nonce: U64, + pub data: Vec, + pub da_height: U64, + pub fuel_block_spend: Option, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic( + schema_path = "./assets/schema.sdl", + graphql_type = "Query", + argument_struct = "ConnectionArgs" +)] +pub struct DaMessageQuery { + #[arguments(after = &args.after, before = &args.before, first = &args.first, last = &args.last)] + pub messages: DaMessageConnection, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(schema_path = "./assets/schema.sdl")] +pub struct DaMessageConnection { + pub edges: Vec, + pub page_info: PageInfo, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(schema_path = "./assets/schema.sdl")] +pub struct DaMessageEdge { + pub cursor: String, + pub node: DaMessage, +} + +impl From for PaginatedResult { + fn from(conn: DaMessageConnection) -> Self { + PaginatedResult { + cursor: conn.page_info.end_cursor, + has_next_page: conn.page_info.has_next_page, + has_previous_page: conn.page_info.has_previous_page, + results: conn.edges.into_iter().map(|e| e.node).collect(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn da_message_query_gql_output() { + use cynic::QueryBuilder; + let operation = DaMessageQuery::build(ConnectionArgs::default()); + insta::assert_snapshot!(operation.query) + } +} diff --git a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap new file mode 100644 index 00000000000..ea4ea5109cb --- /dev/null +++ b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap @@ -0,0 +1,28 @@ +--- +source: fuel-client/src/client/schema/message.rs +expression: operation.query +--- +query Query($_0: Int, $_1: String, $_2: Int, $_3: String) { + messages(first: $_0, after: $_1, last: $_2, before: $_3) { + edges { + cursor + node { + amount + sender + recipient + owner + nonce + data + daHeight + fuelBlockSpend + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } +} + diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 77c9f461ca3..3abe425545c 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -47,7 +47,7 @@ impl DaMessage { self.0.da_height.into() } - async fn fuel_block_spend(&self) -> Option { + async fn fuel_block_spend(&self) -> Option { self.0.fuel_block_spend.map(|v| v.into()) } } diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index 4da44ed5498..db0f6579633 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -2,7 +2,7 @@ use fuel_core::{config::Config, database::Database, service::FuelService}; use fuel_core_interfaces::common::fuel_storage::Storage; use fuel_core_interfaces::model::DaMessage; use fuel_crypto::fuel_types::{Address, MessageId}; -use fuel_gql_client::client::FuelClient; +use fuel_gql_client::client::{FuelClient, PageDirection, PaginationRequest}; #[tokio::test] async fn messages() { @@ -11,7 +11,7 @@ async fn messages() { let srv = FuelService::from_database(db.clone(), Config::local_node()) .await .unwrap(); - let _client = FuelClient::from(srv.bound_address); + let client = FuelClient::from(srv.bound_address); // create some owners let owner_a = Address::new([1; 32]); @@ -44,6 +44,17 @@ async fn messages() { let _ = Storage::::insert(&mut db, &third_id, &third_msg).unwrap(); // get the messages + let result = client + .messages(PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }) + .await + .unwrap(); + + // verify that there are 3 messages stored in total + assert_eq!(result.results.len(), 3); // get the messages by owner } From b3698245af810b4ec6d9ebbde937d27f9fa0149e Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Mon, 8 Aug 2022 15:35:51 +0200 Subject: [PATCH 18/21] clippy cleaner --- fuel-core/src/schema/message.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 3abe425545c..d04fddbfbee 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -89,13 +89,11 @@ impl MessageQuery { return Err(anyhow!("Wrong argument combination")); } - let start; - - if direction == IterDirection::Forward { - start = after; + let start = if direction == IterDirection::Forward { + after } else { - start = before; - } + before + }; let mut message_ids = db.owned_message_ids(owner.into(), start.map(Into::into), Some(direction)); @@ -179,13 +177,11 @@ impl MessageQuery { return Err(anyhow!("Wrong argument combination")); } - let start; - - if direction == IterDirection::Forward { - start = after; + let start = if direction == IterDirection::Forward { + after } else { - start = before; - } + before + }; let mut message_ids = db.all_owners_and_message_ids(start.clone(), Some(direction)); let mut started = None; From 938b3cf926d9653a3c6c57923e467d72fc06cc31 Mon Sep 17 00:00:00 2001 From: leviathanbeak88 Date: Mon, 8 Aug 2022 17:15:16 +0200 Subject: [PATCH 19/21] add messages by owner logic --- fuel-client/src/client.rs | 13 ++++ fuel-client/src/client/schema/message.rs | 65 ++++++++++++++++++- ...ts__owned_da_message_query_gql_output.snap | 28 ++++++++ fuel-core/src/schema/message.rs | 3 +- fuel-tests/tests/messages.rs | 32 ++++++++- 5 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap diff --git a/fuel-client/src/client.rs b/fuel-client/src/client.rs index ea993b8d498..ec0262447b8 100644 --- a/fuel-client/src/client.rs +++ b/fuel-client/src/client.rs @@ -457,6 +457,19 @@ impl FuelClient { Ok(messages) } + + pub async fn messages_by_owner( + &self, + owner: &str, + request: PaginationRequest, + ) -> io::Result> { + let owner: schema::Address = owner.parse()?; + let query = schema::message::OwnedDaMessageQuery::build(&(owner, request).into()); + + let messages = self.query(query).await?.messages_by_owner.into(); + + Ok(messages) + } } #[cfg(any(test, feature = "test-helpers"))] diff --git a/fuel-client/src/client/schema/message.rs b/fuel-client/src/client/schema/message.rs index 004b12d9f91..78d13313d4b 100644 --- a/fuel-client/src/client/schema/message.rs +++ b/fuel-client/src/client/schema/message.rs @@ -1,7 +1,6 @@ +use super::{PageDirection, PageInfo, PaginatedResult, PaginationRequest}; use crate::client::schema::{schema, Address, ConnectionArgs, U64}; -use super::{PageInfo, PaginatedResult}; - #[derive(cynic::QueryFragment, Debug)] #[cynic(schema_path = "./assets/schema.sdl")] pub struct DaMessage { @@ -26,6 +25,17 @@ pub struct DaMessageQuery { pub messages: DaMessageConnection, } +#[derive(cynic::QueryFragment, Debug)] +#[cynic( + schema_path = "./assets/schema.sdl", + graphql_type = "Query", + argument_struct = "OwnedMessagesConnectionArgs" +)] +pub struct OwnedDaMessageQuery { + #[arguments(owner = &args.owner, after = &args.after, before = &args.before, first = &args.first, last = &args.last)] + pub messages_by_owner: DaMessageConnection, +} + #[derive(cynic::QueryFragment, Debug)] #[cynic(schema_path = "./assets/schema.sdl")] pub struct DaMessageConnection { @@ -40,6 +50,42 @@ pub struct DaMessageEdge { pub node: DaMessage, } +#[derive(cynic::FragmentArguments, Debug)] +pub struct OwnedMessagesConnectionArgs { + /// Filter messages based on an owner + pub owner: Address, + /// Skip until coin id (forward pagination) + pub after: Option, + /// Skip until coin id (backward pagination) + pub before: Option, + /// Retrieve the first n coins in order (forward pagination) + pub first: Option, + /// Retrieve the last n coins in order (backward pagination). + /// Can't be used at the same time as `first`. + pub last: Option, +} + +impl From<(Address, PaginationRequest)> for OwnedMessagesConnectionArgs { + fn from(r: (Address, PaginationRequest)) -> Self { + match r.1.direction { + PageDirection::Forward => OwnedMessagesConnectionArgs { + owner: r.0, + after: r.1.cursor, + before: None, + first: Some(r.1.results as i32), + last: None, + }, + PageDirection::Backward => OwnedMessagesConnectionArgs { + owner: r.0, + after: None, + before: r.1.cursor, + first: None, + last: Some(r.1.results as i32), + }, + } + } +} + impl From for PaginatedResult { fn from(conn: DaMessageConnection) -> Self { PaginatedResult { @@ -61,4 +107,19 @@ mod tests { let operation = DaMessageQuery::build(ConnectionArgs::default()); insta::assert_snapshot!(operation.query) } + + #[test] + fn owned_da_message_query_gql_output() { + use cynic::QueryBuilder; + + let operation = OwnedDaMessageQuery::build(OwnedMessagesConnectionArgs { + owner: Address::default(), + after: None, + before: None, + first: None, + last: None, + }); + + insta::assert_snapshot!(operation.query) + } } diff --git a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap new file mode 100644 index 00000000000..25240fb2830 --- /dev/null +++ b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap @@ -0,0 +1,28 @@ +--- +source: fuel-client/src/client/schema/message.rs +expression: operation.query +--- +query Query($_0: Address!, $_1: Int, $_2: String, $_3: Int, $_4: String) { + messagesByOwner(owner: $_0, first: $_1, after: $_2, last: $_3, before: $_4) { + edges { + cursor + node { + amount + sender + recipient + owner + nonce + data + daHeight + fuelBlockSpend + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + } +} + diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index d04fddbfbee..76fdb5a9e18 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -60,7 +60,7 @@ impl MessageQuery { async fn messages_by_owner( &self, ctx: &Context<'_>, - owner: Address, + #[graphql(desc = "address of the owner")] owner: Address, first: Option, after: Option, last: Option, @@ -97,6 +97,7 @@ impl MessageQuery { let mut message_ids = db.owned_message_ids(owner.into(), start.map(Into::into), Some(direction)); + let mut started = None; if start.is_some() { // skip initial result diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index db0f6579633..cc928b962c2 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -56,5 +56,35 @@ async fn messages() { // verify that there are 3 messages stored in total assert_eq!(result.results.len(), 3); - // get the messages by owner + // get the messages from Owner A + let result = client + .messages_by_owner( + &format!("{:?}", owner_a), + PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }, + ) + .await + .unwrap(); + + // verify that Owner A has 2 messages + assert_eq!(result.results.len(), 2); + + // get the messages from Owner B + let result = client + .messages_by_owner( + &format!("{:?}", owner_b), + PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }, + ) + .await + .unwrap(); + + // verify that Owner B has 1 message + assert_eq!(result.results.len(), 1); } From 971064be0b215bf7d9fcb0437360e0e6de3e9d36 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 8 Aug 2022 17:16:50 -0400 Subject: [PATCH 20/21] Split up tests --- fuel-tests/tests/messages.rs | 103 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 25 deletions(-) diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index cc928b962c2..90b5b1dd760 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -5,7 +5,7 @@ use fuel_crypto::fuel_types::{Address, MessageId}; use fuel_gql_client::client::{FuelClient, PageDirection, PaginationRequest}; #[tokio::test] -async fn messages() { +async fn messages_returns_messages_for_all_owners() { // setup server & client let mut db = Database::default(); let srv = FuelService::from_database(db.clone(), Config::local_node()) @@ -44,28 +44,65 @@ async fn messages() { let _ = Storage::::insert(&mut db, &third_id, &third_msg).unwrap(); // get the messages - let result = client - .messages(PaginationRequest { - cursor: None, - results: 5, - direction: PageDirection::Forward, - }) - .await - .unwrap(); + let request = PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }; + let result = client.messages(request).await.unwrap(); // verify that there are 3 messages stored in total assert_eq!(result.results.len(), 3); +} + +#[tokio::test] +async fn messages_by_owner_returns_messages_for_the_given_owner() { + // setup server & client + let mut db = Database::default(); + let srv = FuelService::from_database(db.clone(), Config::local_node()) + .await + .unwrap(); + let client = FuelClient::from(srv.bound_address); + + // create some owners + let owner_a = Address::new([1; 32]); + let owner_b = Address::new([2; 32]); + + // create some messages for owner A + let first_msg = DaMessage { + owner: owner_a, + ..Default::default() + }; + let second_msg = DaMessage { + owner: owner_a, + ..Default::default() + }; + + // create a message for owner B + let third_msg = DaMessage { + owner: owner_b, + ..Default::default() + }; + + // store the messages + let first_id = MessageId::new([1; 32]); + let _ = Storage::::insert(&mut db, &first_id, &first_msg).unwrap(); + + let second_id = MessageId::new([2; 32]); + let _ = Storage::::insert(&mut db, &second_id, &second_msg).unwrap(); + + let third_id = MessageId::new([3; 32]); + let _ = Storage::::insert(&mut db, &third_id, &third_msg).unwrap(); + + let request = PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }; // get the messages from Owner A let result = client - .messages_by_owner( - &format!("{:?}", owner_a), - PaginationRequest { - cursor: None, - results: 5, - direction: PageDirection::Forward, - }, - ) + .messages_by_owner(&owner_a.to_string(), request.clone()) .await .unwrap(); @@ -74,17 +111,33 @@ async fn messages() { // get the messages from Owner B let result = client - .messages_by_owner( - &format!("{:?}", owner_b), - PaginationRequest { - cursor: None, - results: 5, - direction: PageDirection::Forward, - }, - ) + .messages_by_owner(&owner_b.to_string(), request.clone()) .await .unwrap(); // verify that Owner B has 1 message assert_eq!(result.results.len(), 1); } + +#[tokio::test] +async fn messages_empty_results_for_owner_with_no_messages() { + let db = Database::default(); + let srv = FuelService::from_database(db.clone(), Config::local_node()) + .await + .unwrap(); + let client = FuelClient::from(srv.bound_address); + + let owner = Address::new([1; 32]); + let request = PaginationRequest { + cursor: None, + results: 5, + direction: PageDirection::Forward, + }; + + let result = client + .messages_by_owner(&owner.to_string(), request) + .await + .unwrap(); + + assert_eq!(result.results.len(), 0); +} From c760838ae50644f173fed71a3f87b4f847774c6f Mon Sep 17 00:00:00 2001 From: Brandon Kite Date: Tue, 9 Aug 2022 08:27:40 -0700 Subject: [PATCH 21/21] consolidate schema interface (#540) --- fuel-client/assets/schema.sdl | 3 +- fuel-client/src/client.rs | 17 +- fuel-client/src/client/schema/message.rs | 32 +--- ...ts__owned_da_message_query_gql_output.snap | 28 --- ...ests__owned_message_query_gql_output.snap} | 5 +- fuel-core/src/database/message.rs | 27 +-- fuel-core/src/schema/message.rs | 171 +++++------------- fuel-core/src/schema/scalars.rs | 22 --- fuel-tests/tests/messages.rs | 8 +- 9 files changed, 71 insertions(+), 242 deletions(-) delete mode 100644 fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap rename fuel-client/src/client/schema/snapshots/{fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap => fuel_gql_client__client__schema__message__tests__owned_message_query_gql_output.snap} (68%) diff --git a/fuel-client/assets/schema.sdl b/fuel-client/assets/schema.sdl index 87ce1803a4f..fce1aee2bd0 100644 --- a/fuel-client/assets/schema.sdl +++ b/fuel-client/assets/schema.sdl @@ -439,8 +439,7 @@ type Query { contractBalance(contract: ContractId!, asset: AssetId!): ContractBalance! contractBalances(filter: ContractBalanceFilterInput!, first: Int, after: String, last: Int, before: String): ContractBalanceConnection! nodeInfo: NodeInfo! - messagesByOwner(owner: Address!, first: Int, after: String, last: Int, before: String): DaMessageConnection! - messages(first: Int, after: String, last: Int, before: String): DaMessageConnection! + messages(owner: Address, first: Int, after: String, last: Int, before: String): DaMessageConnection! } type Receipt { diff --git a/fuel-client/src/client.rs b/fuel-client/src/client.rs index ec0262447b8..043c1a6cc8f 100644 --- a/fuel-client/src/client.rs +++ b/fuel-client/src/client.rs @@ -449,24 +449,13 @@ impl FuelClient { pub async fn messages( &self, + owner: Option<&str>, request: PaginationRequest, ) -> io::Result> { - let query = schema::message::DaMessageQuery::build(&request.into()); - - let messages = self.query(query).await?.messages.into(); - - Ok(messages) - } - - pub async fn messages_by_owner( - &self, - owner: &str, - request: PaginationRequest, - ) -> io::Result> { - let owner: schema::Address = owner.parse()?; + let owner: Option = owner.map(|owner| owner.parse()).transpose()?; let query = schema::message::OwnedDaMessageQuery::build(&(owner, request).into()); - let messages = self.query(query).await?.messages_by_owner.into(); + let messages = self.query(query).await?.messages.into(); Ok(messages) } diff --git a/fuel-client/src/client/schema/message.rs b/fuel-client/src/client/schema/message.rs index 78d13313d4b..447089e5959 100644 --- a/fuel-client/src/client/schema/message.rs +++ b/fuel-client/src/client/schema/message.rs @@ -1,5 +1,5 @@ use super::{PageDirection, PageInfo, PaginatedResult, PaginationRequest}; -use crate::client::schema::{schema, Address, ConnectionArgs, U64}; +use crate::client::schema::{schema, Address, U64}; #[derive(cynic::QueryFragment, Debug)] #[cynic(schema_path = "./assets/schema.sdl")] @@ -14,17 +14,6 @@ pub struct DaMessage { pub fuel_block_spend: Option, } -#[derive(cynic::QueryFragment, Debug)] -#[cynic( - schema_path = "./assets/schema.sdl", - graphql_type = "Query", - argument_struct = "ConnectionArgs" -)] -pub struct DaMessageQuery { - #[arguments(after = &args.after, before = &args.before, first = &args.first, last = &args.last)] - pub messages: DaMessageConnection, -} - #[derive(cynic::QueryFragment, Debug)] #[cynic( schema_path = "./assets/schema.sdl", @@ -33,7 +22,7 @@ pub struct DaMessageQuery { )] pub struct OwnedDaMessageQuery { #[arguments(owner = &args.owner, after = &args.after, before = &args.before, first = &args.first, last = &args.last)] - pub messages_by_owner: DaMessageConnection, + pub messages: DaMessageConnection, } #[derive(cynic::QueryFragment, Debug)] @@ -53,7 +42,7 @@ pub struct DaMessageEdge { #[derive(cynic::FragmentArguments, Debug)] pub struct OwnedMessagesConnectionArgs { /// Filter messages based on an owner - pub owner: Address, + pub owner: Option
, /// Skip until coin id (forward pagination) pub after: Option, /// Skip until coin id (backward pagination) @@ -65,8 +54,8 @@ pub struct OwnedMessagesConnectionArgs { pub last: Option, } -impl From<(Address, PaginationRequest)> for OwnedMessagesConnectionArgs { - fn from(r: (Address, PaginationRequest)) -> Self { +impl From<(Option
, PaginationRequest)> for OwnedMessagesConnectionArgs { + fn from(r: (Option
, PaginationRequest)) -> Self { match r.1.direction { PageDirection::Forward => OwnedMessagesConnectionArgs { owner: r.0, @@ -102,18 +91,11 @@ mod tests { use super::*; #[test] - fn da_message_query_gql_output() { - use cynic::QueryBuilder; - let operation = DaMessageQuery::build(ConnectionArgs::default()); - insta::assert_snapshot!(operation.query) - } - - #[test] - fn owned_da_message_query_gql_output() { + fn owned_message_query_gql_output() { use cynic::QueryBuilder; let operation = OwnedDaMessageQuery::build(OwnedMessagesConnectionArgs { - owner: Address::default(), + owner: Some(Address::default()), after: None, before: None, first: None, diff --git a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap deleted file mode 100644 index 25240fb2830..00000000000 --- a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_da_message_query_gql_output.snap +++ /dev/null @@ -1,28 +0,0 @@ ---- -source: fuel-client/src/client/schema/message.rs -expression: operation.query ---- -query Query($_0: Address!, $_1: Int, $_2: String, $_3: Int, $_4: String) { - messagesByOwner(owner: $_0, first: $_1, after: $_2, last: $_3, before: $_4) { - edges { - cursor - node { - amount - sender - recipient - owner - nonce - data - daHeight - fuelBlockSpend - } - } - pageInfo { - endCursor - hasNextPage - hasPreviousPage - startCursor - } - } -} - diff --git a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_message_query_gql_output.snap similarity index 68% rename from fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap rename to fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_message_query_gql_output.snap index ea4ea5109cb..68f889c82b0 100644 --- a/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__da_message_query_gql_output.snap +++ b/fuel-client/src/client/schema/snapshots/fuel_gql_client__client__schema__message__tests__owned_message_query_gql_output.snap @@ -1,9 +1,10 @@ --- source: fuel-client/src/client/schema/message.rs +assertion_line: 105 expression: operation.query --- -query Query($_0: Int, $_1: String, $_2: Int, $_3: String) { - messages(first: $_0, after: $_1, last: $_2, before: $_3) { +query Query($_0: Address, $_1: Int, $_2: String, $_3: Int, $_4: String) { + messages(owner: $_0, first: $_1, after: $_2, last: $_3, before: $_4) { edges { cursor node { diff --git a/fuel-core/src/database/message.rs b/fuel-core/src/database/message.rs index 3955edbe3b5..84c841e41c3 100644 --- a/fuel-core/src/database/message.rs +++ b/fuel-core/src/database/message.rs @@ -1,6 +1,5 @@ use crate::{ database::{columns, Database, KvStoreError}, - schema::scalars::OwnerAndMessageId, state::{Error, IterDirection}, }; use fuel_core_interfaces::{ @@ -11,6 +10,7 @@ use fuel_core_interfaces::{ model::DaMessage, }; use std::borrow::Cow; +use std::ops::Deref; impl Storage for Database { type Error = KvStoreError; @@ -78,27 +78,14 @@ impl Database { }) } - pub fn all_owners_and_message_ids( + pub fn all_messages( &self, - start: Option, + start: Option, direction: Option, - ) -> impl Iterator> + '_ { - let start = start.map(|v| owner_msg_id_key(&v.owner.into(), &v.message_id.into())); - self.iter_all::, bool>(columns::OWNED_MESSAGE_IDS, None, start, direction) - .map(|res| { - res.map(|(key, _)| { - // Safety: key is always 64 bytes - unsafe { - OwnerAndMessageId { - owner: Address::from_slice_unchecked(&key[0..32]).into(), - message_id: MessageId::new(*Bytes32::from_slice_unchecked( - &key[32..64], - )) - .into(), - } - } - }) - }) + ) -> impl Iterator> + '_ { + let start = start.map(|v| v.deref().to_vec()); + self.iter_all::, DaMessage>(columns::DA_MESSAGES, None, start, direction) + .map(|res| res.map(|(_, message)| message)) } } diff --git a/fuel-core/src/schema/message.rs b/fuel-core/src/schema/message.rs index 76fdb5a9e18..64d918a6cdd 100644 --- a/fuel-core/src/schema/message.rs +++ b/fuel-core/src/schema/message.rs @@ -1,3 +1,5 @@ +use super::scalars::{Address, MessageId, U64}; +use crate::{database::Database, state::IterDirection}; use anyhow::anyhow; use async_graphql::{ connection::{self, Connection, Edge, EmptyFields}, @@ -9,11 +11,6 @@ use fuel_core_interfaces::{ model, }; use itertools::Itertools; -use std::borrow::Cow; - -use crate::{database::Database, state::IterDirection}; - -use super::scalars::{Address, MessageId, OwnerAndMessageId, U64}; pub struct DaMessage(pub(crate) model::DaMessage); @@ -57,10 +54,10 @@ pub struct MessageQuery {} #[Object] impl MessageQuery { - async fn messages_by_owner( + async fn messages( &self, ctx: &Context<'_>, - #[graphql(desc = "address of the owner")] owner: Address, + #[graphql(desc = "address of the owner")] owner: Option
, first: Option, after: Option, last: Option, @@ -95,28 +92,42 @@ impl MessageQuery { before }; - let mut message_ids = - db.owned_message_ids(owner.into(), start.map(Into::into), Some(direction)); - - let mut started = None; - if start.is_some() { - // skip initial result - started = message_ids.next(); - } - - let message_ids = message_ids.take(records_to_fetch + 1); - let message_ids: Vec = message_ids.try_collect()?; - let has_next_page = message_ids.len() > records_to_fetch; - - let mut messages: Vec> = message_ids - .iter() - .take(records_to_fetch) - .map(|msg_id| { - Storage::::get(&db, msg_id) - .transpose() - .ok_or(KvStoreError::NotFound)? - }) - .try_collect()?; + let (mut messages, has_next_page, has_previous_page) = if let Some(owner) = owner { + let mut message_ids = + db.owned_message_ids(owner.into(), start.map(Into::into), Some(direction)); + let mut started = None; + if start.is_some() { + // skip initial result + started = message_ids.next(); + } + let message_ids = message_ids.take(records_to_fetch + 1); + let message_ids: Vec = message_ids.try_collect()?; + let has_next_page = message_ids.len() > records_to_fetch; + + let messages: Vec = message_ids + .iter() + .take(records_to_fetch) + .map(|msg_id| { + Storage::::get(&db, msg_id) + .transpose() + .ok_or(KvStoreError::NotFound)? + .map(|f| f.into_owned()) + }) + .try_collect()?; + (messages, has_next_page, started.is_some()) + } else { + let mut messages = db.all_messages(start.map(Into::into), Some(direction)); + let mut started = None; + if start.is_some() { + // skip initial result + started = messages.next(); + } + let messages: Vec = + messages.take(records_to_fetch + 1).try_collect()?; + let has_next_page = messages.len() > records_to_fetch; + let messages = messages.into_iter().take(records_to_fetch).collect(); + (messages, has_next_page, started.is_some()) + }; // reverse after filtering next page test record to maintain consistent ordering // in the response regardless of whether first or last was used. @@ -124,107 +135,17 @@ impl MessageQuery { messages.reverse(); } - let mut connection = Connection::new(started.is_some(), has_next_page); + let mut connection = Connection::new(has_previous_page, has_next_page); - connection - .edges - .extend( - messages - .into_iter() - .zip(message_ids) - .map(|(message, msg_id)| { - Edge::new(msg_id.into(), DaMessage(message.into_owned())) - }), - ); + connection.edges.extend( + messages + .into_iter() + .map(|message| Edge::new(message.id().into(), DaMessage(message))), + ); Ok::, anyhow::Error>(connection) }, ) .await } - - async fn messages( - &self, - ctx: &Context<'_>, - first: Option, - after: Option, - last: Option, - before: Option, - ) -> async_graphql::Result> - { - let db = ctx.data_unchecked::().clone(); - - connection::query( - after, - before, - first, - last, - |after: Option, - before: Option, - first, - last| async move { - let (records_to_fetch, direction) = if let Some(first) = first { - (first, IterDirection::Forward) - } else if let Some(last) = last { - (last, IterDirection::Reverse) - } else { - (0, IterDirection::Forward) - }; - - if (first.is_some() && before.is_some()) - || (after.is_some() && before.is_some()) - || (last.is_some() && after.is_some()) - { - return Err(anyhow!("Wrong argument combination")); - } - - let start = if direction == IterDirection::Forward { - after - } else { - before - }; - - let mut message_ids = db.all_owners_and_message_ids(start.clone(), Some(direction)); - let mut started = None; - if start.is_some() { - // skip initial result - started = message_ids.next(); - } - - let message_ids = message_ids.take(records_to_fetch + 1); - let message_ids: Vec = message_ids.try_collect()?; - let has_next_page = message_ids.len() > records_to_fetch; - - let mut messages: Vec> = message_ids - .iter() - .take(records_to_fetch) - .map(|value| { - Storage::::get( - &db, - &value.message_id.into(), - ) - .transpose() - .ok_or(KvStoreError::NotFound)? - }) - .try_collect()?; - - if direction == IterDirection::Forward { - messages.reverse(); - } - - let mut connection = Connection::new(started.is_some(), has_next_page); - - connection - .edges - .extend(messages.into_iter().zip(message_ids).map( - |(message, owner_msg_id)| { - Edge::new(owner_msg_id, DaMessage(message.into_owned())) - }, - )); - - Ok::, anyhow::Error>(connection) - }, - ) - .await - } } diff --git a/fuel-core/src/schema/scalars.rs b/fuel-core/src/schema/scalars.rs index 0736315bcf1..c70b3a06382 100644 --- a/fuel-core/src/schema/scalars.rs +++ b/fuel-core/src/schema/scalars.rs @@ -56,28 +56,6 @@ impl SortedTxCursor { } } } -#[derive(Clone, Debug)] -pub struct OwnerAndMessageId { - pub owner: Address, - pub message_id: MessageId, -} - -impl CursorType for OwnerAndMessageId { - type Error = String; - - fn decode_cursor(s: &str) -> Result { - let (owner, msg_id) = s.split_once('#').ok_or("Incorrect format provided")?; - - Ok(OwnerAndMessageId { - owner: Address::from_str(owner)?, - message_id: MessageId::from_str(msg_id)?, - }) - } - - fn encode_cursor(&self) -> String { - format!("{}#{}", self.owner, self.message_id) - } -} impl CursorType for SortedTxCursor { type Error = String; diff --git a/fuel-tests/tests/messages.rs b/fuel-tests/tests/messages.rs index 90b5b1dd760..2f3a176509e 100644 --- a/fuel-tests/tests/messages.rs +++ b/fuel-tests/tests/messages.rs @@ -49,7 +49,7 @@ async fn messages_returns_messages_for_all_owners() { results: 5, direction: PageDirection::Forward, }; - let result = client.messages(request).await.unwrap(); + let result = client.messages(None, request).await.unwrap(); // verify that there are 3 messages stored in total assert_eq!(result.results.len(), 3); @@ -102,7 +102,7 @@ async fn messages_by_owner_returns_messages_for_the_given_owner() { // get the messages from Owner A let result = client - .messages_by_owner(&owner_a.to_string(), request.clone()) + .messages(Some(&owner_a.to_string()), request.clone()) .await .unwrap(); @@ -111,7 +111,7 @@ async fn messages_by_owner_returns_messages_for_the_given_owner() { // get the messages from Owner B let result = client - .messages_by_owner(&owner_b.to_string(), request.clone()) + .messages(Some(&owner_b.to_string()), request.clone()) .await .unwrap(); @@ -135,7 +135,7 @@ async fn messages_empty_results_for_owner_with_no_messages() { }; let result = client - .messages_by_owner(&owner.to_string(), request) + .messages(Some(&owner.to_string()), request) .await .unwrap();