Skip to content

Commit 99abfff

Browse files
stefan-mystenDaughterOfMars
authored andcommitted
sui-graphql-rpc: add balance function (#13)
1 parent 5b616d6 commit 99abfff

File tree

3 files changed

+82
-7
lines changed

3 files changed

+82
-7
lines changed

crates/sui-graphql-client/src/lib.rs

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ pub mod query_types;
77

88
use base64ct::Encoding;
99
use query_types::{
10-
ChainIdentifierQuery, CheckpointArgs, CheckpointId, CheckpointQuery, CoinMetadata,
11-
CoinMetadataArgs, CoinMetadataQuery, EpochSummaryArgs, EpochSummaryQuery, EventFilter,
12-
EventsQuery, EventsQueryArgs, ObjectFilter, ObjectQuery, ObjectQueryArgs, ObjectsQuery,
13-
ObjectsQueryArgs, PageInfo, ProtocolConfigQuery, ProtocolConfigs, ProtocolVersionArgs,
14-
ServiceConfig, ServiceConfigQuery, TransactionBlockArgs, TransactionBlockQuery,
15-
TransactionBlocksQuery, TransactionBlocksQueryArgs, TransactionsFilter, Uint53,
10+
BalanceArgs, BalanceQuery, ChainIdentifierQuery, CheckpointArgs, CheckpointId, CheckpointQuery,
11+
CoinMetadata, CoinMetadataArgs, CoinMetadataQuery, EpochSummaryArgs, EpochSummaryQuery,
12+
EventFilter, EventsQuery, EventsQueryArgs, ObjectFilter, ObjectQuery, ObjectQueryArgs,
13+
ObjectsQuery, ObjectsQueryArgs, PageInfo, ProtocolConfigQuery, ProtocolConfigs,
14+
ProtocolVersionArgs, ServiceConfig, ServiceConfigQuery, TransactionBlockArgs,
15+
TransactionBlockQuery, TransactionBlocksQuery, TransactionBlocksQueryArgs, TransactionsFilter,
16+
Uint53,
1617
};
1718
use reqwest::Url;
1819
use sui_types::types::{
@@ -194,6 +195,38 @@ impl Client {
194195
.ok_or_else(|| Error::msg("No data in response"))
195196
}
196197

198+
// ===========================================================================
199+
// Balance API
200+
// ===========================================================================
201+
202+
/// Get the balance of all the coins owned by address for the provided coin type.
203+
/// Coin type will default to `0x2::coin::Coin<0x2::sui::SUI>` if not provided.
204+
pub async fn balance(
205+
&self,
206+
address: Address,
207+
coin_type: Option<&str>,
208+
) -> Result<Option<u128>, Error> {
209+
let operation = BalanceQuery::build(BalanceArgs {
210+
address: address.into(),
211+
coin_type: coin_type.map(|x| x.to_string()),
212+
});
213+
let response = self.run_query(&operation).await?;
214+
215+
if let Some(errors) = response.errors {
216+
return Err(Error::msg(format!("{:?}", errors)));
217+
}
218+
219+
let total_balance = response
220+
.data
221+
.map(|b| b.owner.and_then(|o| o.balance.map(|b| b.total_balance)))
222+
.ok_or_else(|| Error::msg("No data in response"))?
223+
.flatten()
224+
.map(|x| x.0.parse::<u128>())
225+
.transpose()
226+
.map_err(|e| Error::msg(format!("Cannot parse balance into u128: {e}")))?;
227+
Ok(total_balance)
228+
}
229+
197230
// ===========================================================================
198231
// Coin API
199232
// ===========================================================================
@@ -576,6 +609,15 @@ mod tests {
576609
assert!(client.set_rpc_server("9125/graphql").is_err());
577610
}
578611

612+
#[tokio::test]
613+
async fn test_balance_query() {
614+
for (n, _) in NETWORKS.iter() {
615+
let client = Client::new(n).unwrap();
616+
let balance = client.balance("0x1".parse().unwrap(), None).await;
617+
assert!(balance.is_ok(), "Balance query failed for network: {n}");
618+
}
619+
}
620+
579621
#[tokio::test]
580622
async fn test_chain_id() {
581623
for (n, id) in NETWORKS.iter() {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) Mysten Labs, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use super::SuiAddress;
5+
use crate::query_types::{schema, BigInt};
6+
7+
#[derive(cynic::QueryFragment, Debug)]
8+
#[cynic(schema = "rpc", graphql_type = "Query", variables = "BalanceArgs")]
9+
pub struct BalanceQuery {
10+
#[arguments(address: $address)]
11+
pub owner: Option<Owner>,
12+
}
13+
14+
#[derive(cynic::QueryFragment, Debug)]
15+
#[cynic(schema = "rpc", graphql_type = "Owner", variables = "BalanceArgs")]
16+
pub struct Owner {
17+
#[arguments(type: $coin_type)]
18+
pub balance: Option<Balance>,
19+
}
20+
21+
#[derive(cynic::QueryFragment, Debug)]
22+
#[cynic(schema = "rpc", graphql_type = "Balance")]
23+
pub struct Balance {
24+
pub total_balance: Option<BigInt>,
25+
}
26+
27+
#[derive(cynic::QueryVariables, Debug)]
28+
pub struct BalanceArgs {
29+
pub address: SuiAddress,
30+
pub coin_type: Option<String>,
31+
}

crates/sui-graphql-client/src/query_types/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
use std::str::FromStr;
44

5+
mod balance;
56
mod chain;
67
mod checkpoint;
78
mod coin;
@@ -13,6 +14,7 @@ mod service_config;
1314
mod transaction;
1415

1516
use anyhow::{anyhow, Error};
17+
pub use balance::{Balance, BalanceArgs, BalanceQuery, Owner};
1618
pub use chain::ChainIdentifierQuery;
1719
pub use checkpoint::{CheckpointArgs, CheckpointId, CheckpointQuery};
1820
pub use coin::{CoinMetadata, CoinMetadataArgs, CoinMetadataQuery};
@@ -48,7 +50,7 @@ pub struct BigInt(pub String);
4850
#[cynic(graphql_type = "DateTime")]
4951
pub struct DateTime(pub String);
5052

51-
#[derive(cynic::Scalar, Debug, Clone)]
53+
#[derive(cynic::Scalar, Debug)]
5254
pub struct SuiAddress(pub String);
5355

5456
#[derive(cynic::Scalar, Debug, Clone)]

0 commit comments

Comments
 (0)