diff --git a/crates/sui-graphql-client/src/lib.rs b/crates/sui-graphql-client/src/lib.rs index b1c3eb9..3c08a90 100644 --- a/crates/sui-graphql-client/src/lib.rs +++ b/crates/sui-graphql-client/src/lib.rs @@ -10,20 +10,20 @@ use base64ct::Encoding; use query_types::{ BalanceArgs, BalanceQuery, ChainIdentifierQuery, CheckpointArgs, CheckpointId, CheckpointQuery, CoinMetadata, CoinMetadataArgs, CoinMetadataQuery, EpochSummaryArgs, EpochSummaryQuery, - EventFilter, EventsQuery, EventsQueryArgs, ObjectFilter, ObjectQuery, ObjectQueryArgs, - ObjectsQuery, ObjectsQueryArgs, PageInfo, ProtocolConfigQuery, ProtocolConfigs, - ProtocolVersionArgs, ServiceConfig, ServiceConfigQuery, TransactionBlockArgs, - TransactionBlockQuery, TransactionBlocksQuery, TransactionBlocksQueryArgs, TransactionsFilter, - Uint53, + EventFilter, EventsQuery, EventsQueryArgs, ExecuteTransactionArgs, ExecuteTransactionQuery, + ObjectFilter, ObjectQuery, ObjectQueryArgs, ObjectsQuery, ObjectsQueryArgs, PageInfo, + ProtocolConfigQuery, ProtocolConfigs, ProtocolVersionArgs, ServiceConfig, ServiceConfigQuery, + TransactionBlockArgs, TransactionBlockQuery, TransactionBlocksQuery, + TransactionBlocksQueryArgs, TransactionsFilter, Uint53, }; use reqwest::Url; use sui_types::types::{ framework::Coin, Address, CheckpointSequenceNumber, CheckpointSummary, Event, Object, - SignedTransaction, + SignedTransaction, Transaction, TransactionEffects, UserSignature, }; use anyhow::{anyhow, ensure, Error, Result}; -use cynic::{serde, GraphQlResponse, Operation, QueryBuilder}; +use cynic::{serde, GraphQlResponse, MutationBuilder, Operation, QueryBuilder}; use futures::Stream; use std::pin::Pin; @@ -677,6 +677,38 @@ impl Client { Ok(None) } } + + /// Execute a transaction. + pub async fn execute_tx( + &self, + signatures: Vec, + tx: &Transaction, + ) -> Result, Error> { + let operation = ExecuteTransactionQuery::build(ExecuteTransactionArgs { + signatures: signatures.iter().map(|s| s.to_base64()).collect(), + tx_bytes: base64ct::Base64::encode_string(bcs::to_bytes(tx).unwrap().as_ref()), + }); + + let response = self.run_query(&operation).await?; + + if let Some(errors) = response.errors { + return Err(Error::msg(format!("{:?}", errors))); + } + + if let Some(data) = response.data { + let result = data.execute_transaction_block; + let bcs = + base64ct::Base64::decode_vec(result.effects.bcs.0.as_str()).map_err(|_| { + Error::msg("Cannot decode bcs bytes from Base64 for transaction effects") + })?; + let effects: TransactionEffects = bcs::from_bytes(&bcs) + .map_err(|_| Error::msg("Cannot decode bcs bytes into TransactionEffects"))?; + + Ok(Some(effects)) + } else { + Ok(None) + } + } } #[cfg(test)] diff --git a/crates/sui-graphql-client/src/query_types/execute_tx.rs b/crates/sui-graphql-client/src/query_types/execute_tx.rs new file mode 100644 index 0000000..aa0f80b --- /dev/null +++ b/crates/sui-graphql-client/src/query_types/execute_tx.rs @@ -0,0 +1,34 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::query_types::{schema, Base64}; + +#[derive(cynic::QueryFragment, Debug)] +#[cynic( + schema = "rpc", + graphql_type = "Mutation", + variables = "ExecuteTransactionArgs" +)] +pub struct ExecuteTransactionQuery { + #[arguments(signatures: $signatures, txBytes: $tx_bytes)] + pub execute_transaction_block: ExecutionResult, +} + +#[derive(cynic::QueryVariables, Debug)] +pub struct ExecuteTransactionArgs { + pub signatures: Vec, + pub tx_bytes: String, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(schema = "rpc", graphql_type = "ExecutionResult")] +pub struct ExecutionResult { + pub errors: Option>, + pub effects: TransactionBlockEffects, +} + +#[derive(cynic::QueryFragment, Debug)] +#[cynic(schema = "rpc", graphql_type = "TransactionBlockEffects")] +pub struct TransactionBlockEffects { + pub bcs: Base64, +} diff --git a/crates/sui-graphql-client/src/query_types/mod.rs b/crates/sui-graphql-client/src/query_types/mod.rs index 34accfd..0dbcb8a 100644 --- a/crates/sui-graphql-client/src/query_types/mod.rs +++ b/crates/sui-graphql-client/src/query_types/mod.rs @@ -8,6 +8,7 @@ mod checkpoint; mod coin; mod epoch; mod events; +mod execute_tx; mod object; mod protocol_config; mod service_config; @@ -20,6 +21,7 @@ pub use checkpoint::{CheckpointArgs, CheckpointId, CheckpointQuery}; pub use coin::{CoinMetadata, CoinMetadataArgs, CoinMetadataQuery}; pub use epoch::{Epoch, EpochSummaryArgs, EpochSummaryQuery}; pub use events::{Event, EventConnection, EventFilter, EventsQuery, EventsQueryArgs}; +pub use execute_tx::{ExecuteTransactionArgs, ExecuteTransactionQuery, ExecutionResult}; pub use object::{ ObjectFilter, ObjectKey, ObjectQuery, ObjectQueryArgs, ObjectsQuery, ObjectsQueryArgs, };