Skip to content

Commit

Permalink
Applied comments from the PR.
Browse files Browse the repository at this point in the history
The last comment left to add indexation config field and decide do we need to index or not based on that
  • Loading branch information
xgreenx committed Jan 7, 2025
1 parent 1bc7ddd commit 319d32d
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 124 deletions.
10 changes: 6 additions & 4 deletions crates/client/assets/schema.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ scalar Address
scalar AssetId

type AssetInfoDetails {
contractId: HexString!
subId: HexString!
totalSupply: U64!
contractId: ContractId!
subId: SubId!
totalSupply: U128!
}

type Balance {
Expand Down Expand Up @@ -864,7 +864,7 @@ type Query {
ID of the Asset
"""
id: AssetId!
): AssetInfoDetails
): AssetInfoDetails!
"""
Read register value by index.
"""
Expand Down Expand Up @@ -1133,6 +1133,8 @@ type StateTransitionPurpose {
}


scalar SubId

type SubmittedStatus {
time: Tai64Timestamp!
}
Expand Down
13 changes: 4 additions & 9 deletions crates/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::client::{
TransactionId,
},
types::{
asset::AssetDetail,
gas_price::LatestGasPrice,
message::MessageStatus,
primitives::{
Expand Down Expand Up @@ -78,10 +79,7 @@ use pagination::{
PaginationRequest,
};
use schema::{
assets::{
AssetInfoArg,
AssetInfoDetails,
},
assets::AssetInfoArg,
balance::BalanceArgs,
blob::BlobByIdArgs,
block::BlockByIdArgs,
Expand Down Expand Up @@ -1196,14 +1194,11 @@ impl FuelClient {
Ok(status)
}

pub async fn asset_info(
&self,
asset_id: &AssetId,
) -> io::Result<Option<AssetInfoDetails>> {
pub async fn asset_info(&self, asset_id: &AssetId) -> io::Result<AssetDetail> {
let query = schema::assets::AssetInfoQuery::build(AssetInfoArg {
id: (*asset_id).into(),
});
let asset_info = self.query(query).await?.asset_details.map(Into::into);
let asset_info = self.query(query).await?.asset_details.into();
Ok(asset_info)
}
}
Expand Down
13 changes: 7 additions & 6 deletions crates/client/src/client/schema/assets.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::client::schema::{
schema,
AssetId,
HexString,
U64,
ContractId,
SubId,
U128,
};

#[derive(cynic::QueryVariables, Debug)]
Expand All @@ -18,13 +19,13 @@ pub struct AssetInfoArg {
)]
pub struct AssetInfoQuery {
#[arguments(id: $id)]
pub asset_details: Option<AssetInfoDetails>,
pub asset_details: AssetInfoDetails,
}

#[derive(cynic::QueryFragment, Clone, Debug)]
#[cynic(schema_path = "./assets/schema.sdl")]
pub struct AssetInfoDetails {
pub sub_id: HexString,
pub contract_id: HexString,
pub total_supply: U64,
pub sub_id: SubId,
pub contract_id: ContractId,
pub total_supply: U128,
}
1 change: 1 addition & 0 deletions crates/client/src/client/schema/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ fuel_type_scalar!(BlockId, Bytes32);
fuel_type_scalar!(AssetId, AssetId);
fuel_type_scalar!(BlobId, BlobId);
fuel_type_scalar!(ContractId, ContractId);
fuel_type_scalar!(SubId, Bytes32);
fuel_type_scalar!(Salt, Salt);
fuel_type_scalar!(TransactionId, Bytes32);
fuel_type_scalar!(RelayedTransactionId, Bytes32);
Expand Down
1 change: 1 addition & 0 deletions crates/client/src/client/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod contract;
pub mod gas_costs;
pub mod upgrades;

pub mod asset;
pub mod gas_price;
pub mod merkle_proof;
pub mod message;
Expand Down
24 changes: 24 additions & 0 deletions crates/client/src/client/types/asset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::client::schema;
use fuel_core_types::{
fuel_tx::Bytes32,
fuel_types::ContractId,
};

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AssetDetail {
pub contract_id: ContractId,
pub sub_id: Bytes32,
pub total_supply: u128,
}

// GraphQL Translation

impl From<schema::assets::AssetInfoDetails> for AssetDetail {
fn from(value: schema::assets::AssetInfoDetails) -> Self {
AssetDetail {
contract_id: value.contract_id.into(),
sub_id: value.sub_id.into(),
total_supply: value.total_supply.into(),
}
}
}
2 changes: 0 additions & 2 deletions crates/fuel-core/src/graphql_api/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ pub trait OffChainDatabase: Send + Sync {
fn message_is_spent(&self, nonce: &Nonce) -> StorageResult<bool>;

fn asset_info(&self, asset_id: &AssetId) -> StorageResult<Option<AssetDetails>>;

fn asset_exists(&self, asset_id: &AssetId) -> StorageResult<bool>;
}

/// The on chain database port expected by GraphQL API service.
Expand Down
20 changes: 12 additions & 8 deletions crates/fuel-core/src/graphql_api/storage/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ use fuel_core_storage::{
structured_storage::TableWithBlueprint,
Mappable,
};
use fuel_core_types::{
fuel_merkle::common::Bytes32,
fuel_tx::{
AssetId,
ContractId,
},
use fuel_core_types::fuel_tx::{
AssetId,
Bytes32,
ContractId,
};

/// Contract info
/// Asset info table to store information about the asset like total minted amounts,
/// source contract, original sub id, etc.
pub struct AssetsInfo;

pub type AssetDetails = (ContractId, Bytes32, u64); // (contract_id, sub_id, total_amount)
#[derive(Default, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AssetDetails {
pub contract_id: ContractId,
pub sub_id: Bytes32,
pub total_supply: u128,
}

impl Mappable for AssetsInfo {
type Key = AssetId;
Expand Down
77 changes: 36 additions & 41 deletions crates/fuel-core/src/graphql_api/worker_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
},
},
storage::{
assets::AssetDetails,
blocks::FuelBlockIdsToHeights,
coins::{
owner_coin_id_key,
Expand Down Expand Up @@ -93,6 +94,7 @@ use fuel_core_types::{
},
executor::{
Event,
TransactionExecutionResult,
TransactionExecutionStatus,
},
txpool::from_executor_to_status,
Expand Down Expand Up @@ -387,59 +389,52 @@ where
.into());
}

for receipt in result.receipts() {
// TODO: Do Asset indexation only if it is enabled.
// Enable the indexation only in the case of empty database

let TransactionExecutionResult::Success { receipts, .. } = result else {
continue
};

for receipt in receipts {
match receipt {
Receipt::Mint {
sub_id,
contract_id,
val,
..
} => {
let asset_id = contract_id.asset_id(sub_id);
let current_count = match db.storage::<AssetsInfo>().get(&asset_id) {
Ok(count) => count,
Err(_) => {
// If asset doesn't exist yet, create it with 0 count
db.storage::<AssetsInfo>()
.insert(&asset_id, &(*contract_id, **sub_id, 0))?;
Some(Cow::Owned((*contract_id, **sub_id, 0)))
}
}
.map(|info| {
info.2
.checked_add(*val)
.ok_or(anyhow::anyhow!("Asset count overflow"))
})
.transpose()?
.unwrap_or(*val);

db.storage::<AssetsInfo>()
.insert(&asset_id, &(*contract_id, **sub_id, current_count))?;
}
Receipt::Burn {
| Receipt::Burn {
sub_id,
contract_id,
val,
..
} => {
let asset_id = contract_id.asset_id(sub_id);
let current_count = db
let current_supply = db
.storage::<AssetsInfo>()
.get(&asset_id)
.unwrap_or_else(|_| {
tracing::warn!("Asset {} is not currently indexed", asset_id);
None
})
.map(|info| {
info.2
.checked_sub(*val)
.ok_or(anyhow::anyhow!("Asset count overflow"))
})
.transpose()?
.unwrap_or(*val);

db.storage::<AssetsInfo>()
.insert(&asset_id, &(*contract_id, **sub_id, current_count))?;
.get(&asset_id)?
.map(|info| info.total_supply)
.unwrap_or_default();

let new_supply = match receipt {
Receipt::Mint { val, .. } => current_supply
.checked_add(*val as u128)
.expect("Impossible to overflow, because `val` is `u64`"),
Receipt::Burn { val, .. } => {
current_supply.checked_sub(*val as u128).ok_or(
anyhow::anyhow!("Burned more than available amount"),
)?
}
_ => unreachable!(),
};

db.storage::<AssetsInfo>().insert(
&asset_id,
&AssetDetails {
contract_id: *contract_id,
sub_id: *sub_id,
total_supply: new_supply,
},
)?;
}
_ => {}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/fuel-core/src/query/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use fuel_core_storage::{
use fuel_core_types::fuel_tx::AssetId;

impl ReadView {
pub fn get_asset_details(&self, id: AssetId) -> StorageResult<AssetDetails> {
pub fn get_asset_details(&self, id: &AssetId) -> StorageResult<AssetDetails> {
let asset = self
.off_chain
.asset_info(&id)?
.asset_info(id)?
.ok_or(not_found!(AssetDetails))?;
Ok(asset)
}
Expand Down
6 changes: 3 additions & 3 deletions crates/fuel-core/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ where
} else if let Some(last) = last {
(last, IterDirection::Reverse)
} else {
return Err(anyhow!("Either `first` or `last` should be provided"));
return Err(anyhow!("Either `first` or `last` should be provided"))
};

let start;
Expand Down Expand Up @@ -172,7 +172,7 @@ where
// Skip until start + 1
if key == start {
has_previous_page = true;
return true;
return true
}
}
}
Expand All @@ -186,7 +186,7 @@ where
// take until we've reached the end
if key == end {
has_next_page = true;
return false;
return false
}
}
count = count.saturating_sub(1);
Expand Down
29 changes: 15 additions & 14 deletions crates/fuel-core/src/schema/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use crate::{
schema::{
scalars::{
AssetId,
HexString,
U64,
ContractId,
SubId,
U128,
},
ReadViewProvider,
},
Expand All @@ -26,43 +27,43 @@ impl AssetInfoQuery {
&self,
ctx: &Context<'_>,
#[graphql(desc = "ID of the Asset")] id: AssetId,
) -> async_graphql::Result<Option<AssetInfoDetails>> {
) -> async_graphql::Result<AssetInfoDetails> {
let query = ctx.read_view()?;
query
.get_asset_details(id.into())
.map(|details| Some(details.into()))
.get_asset_details(&id.into())
.map(|details| details.into())
.map_err(async_graphql::Error::from)
}
}

#[derive(Clone, Debug)]
pub struct AssetInfoDetails {
pub contract_id: HexString,
pub sub_id: HexString,
pub total_supply: U64,
pub contract_id: ContractId,
pub sub_id: SubId,
pub total_supply: U128,
}

impl From<AssetDetails> for AssetInfoDetails {
fn from(details: AssetDetails) -> Self {
AssetInfoDetails {
contract_id: details.0.as_ref().to_vec().into(),
sub_id: details.1.as_ref().to_vec().into(),
total_supply: details.2.into(),
contract_id: details.contract_id.into(),
sub_id: details.sub_id.into(),
total_supply: details.total_supply.into(),
}
}
}

#[Object]
impl AssetInfoDetails {
async fn contract_id(&self) -> &HexString {
async fn contract_id(&self) -> &ContractId {
&self.contract_id
}

async fn sub_id(&self) -> &HexString {
async fn sub_id(&self) -> &SubId {
&self.sub_id
}

async fn total_supply(&self) -> &U64 {
async fn total_supply(&self) -> &U128 {
&self.total_supply
}
}
Loading

0 comments on commit 319d32d

Please sign in to comment.