Skip to content

Commit

Permalink
Simplify query
Browse files Browse the repository at this point in the history
  • Loading branch information
DOBEN committed Dec 20, 2024
1 parent b6f8950 commit d018345
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 31 deletions.

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

13 changes: 8 additions & 5 deletions backend-rust/migrations/0001_initialize.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,9 @@ CREATE TABLE scheduled_releases (
-- This index is useful for that.
CREATE INDEX scheduled_releases_idx ON scheduled_releases (account_index, release_time);

-- All CIS2 tokens. A token is added to this table whenever a `CIS2 mint event` is logged for the first
-- time by a contract claiming to follow the `CIS2 standard` or a `CIS2 tokenMetadataUpdated event` is logged
-- for the first time by a contract claiming to follow the `CIS2 standard`.
-- All CIS2 tokens. A token is added to this table whenever a CIS2 `MintEvent`/`BurnEvent`
-- or `TokenMetadataEvent` is logged for the first time by a contract claiming
-- to follow the `CIS2 standard`.
CREATE TABLE tokens (
-- An index/id for the token (row number).
index
Expand Down Expand Up @@ -446,19 +446,22 @@ CREATE TABLE tokens (
token_id
TEXT
NOT NULL,
-- Accumulated total supply of the token calculated by considering all `mint/burn` events associated
-- Accumulated total supply of the token calculated by considering all `MintEvents` and `BurnEvents` associated
-- to the token. If no total supply is specified when inserting a new token in the table,
-- the default total supply 0 is used.
total_supply
NUMERIC
NOT NULL
DEFAULT 0,
-- Index of the transaction with the first `CIS2 mint event`, `CIS2 burn event` or `CIS2 tokenMetadata event` logged for the token.
-- Index of the transaction with the first CIS2 `MintEvent`, `BurnEvent` or `TokenMetadataEvent` logged for the token.
init_transaction_index
BIGINT
NOT NULL
);

-- We want to find a specific token (this index should be removed once the front-end querries a token by `token_address`).
CREATE INDEX token_idx ON tokens (contract_index, contract_sub_index, token_id);

CREATE OR REPLACE FUNCTION block_added_notify_trigger_function() RETURNS trigger AS $trigger$
DECLARE
rec blocks;
Expand Down
31 changes: 13 additions & 18 deletions backend-rust/src/graphql_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ macro_rules! todo_api {
};
}

use crate::indexer::get_token_address;
use account_metrics::AccountMetricsQuery;
use anyhow::Context as _;
use async_graphql::{
Expand All @@ -37,7 +36,6 @@ use concordium_rust_sdk::{
},
smart_contracts::ReceiveName,
},
cis2::{ParseTokenIdVecError, TokenId},
id::types as sdk_types,
types::AmountFraction,
};
Expand Down Expand Up @@ -357,10 +355,6 @@ enum ApiError {
InvalidContractVersion(#[from] InvalidContractVersionError),
#[error("Schema in database should be a valid versioned module schema")]
InvalidVersionedModuleSchema(#[from] VersionedSchemaError),
#[error("Invalid token ID: {0}")]
InvalidTokenID(Arc<ParseTokenIdVecError>),
#[error("Invalid token address: {0}")]
InvalidTokenAddress(Arc<anyhow::Error>),
}

impl From<sqlx::Error> for ApiError {
Expand Down Expand Up @@ -893,16 +887,9 @@ LIMIT 30", // WHERE slot_time > (LOCALTIMESTAMP - $1::interval)
) -> ApiResult<Token> {
let pool = get_pool(ctx)?;

let token_address = get_token_address(
contract_index.0,
contract_sub_index.0,
&TokenId::from_str(&token_id).map_err(|e| ApiError::InvalidTokenID(e.into()))?,
)
.map_err(|e| ApiError::InvalidTokenAddress(Arc::new(e)))?;

let token = sqlx::query_as!(
Token,
r#"SELECT
r#"SELECT
total_supply as "raw_total_supply: BigDecimal",
token_id,
contract_index as "contract_index: i64",
Expand All @@ -911,10 +898,10 @@ LIMIT 30", // WHERE slot_time > (LOCALTIMESTAMP - $1::interval)
metadata_url,
init_transaction_index
FROM tokens
WHERE tokens.contract_index = $1 AND tokens.contract_sub_index = $2 AND tokens.token_address = $3"#,
WHERE tokens.contract_index = $1 AND tokens.contract_sub_index = $2 AND tokens.token_id = $3"#,
contract_index.0 as i64,
contract_sub_index.0 as i64,
token_address
token_id
)
.fetch_optional(pool)
.await?
Expand Down Expand Up @@ -1391,7 +1378,7 @@ type Amount = i64; // TODO: should be UnsignedLong in graphQL
type Energy = i64; // TODO: should be UnsignedLong in graphQL
type DateTime = chrono::DateTime<chrono::Utc>; // TODO check format matches.
type ContractIndex = UnsignedLong; // TODO check format.
type BigInteger = Vec<u8>;
type BigInteger = BigDecimal;
type MetadataUrl = String;

#[derive(SimpleObject)]
Expand Down Expand Up @@ -2425,12 +2412,20 @@ struct AccountToken {
contract_index: ContractIndex,
contract_sub_index: ContractIndex,
token_id: String,
balance: BigInteger,
#[graphql(skip)]
raw_balance: BigInteger,
token: Token,
account_id: i64,
account: Account,
}

#[ComplexObject]
impl AccountToken {
async fn balance(&self, ctx: &Context<'_>) -> ApiResult<String> {
Ok(self.raw_balance.to_string())
}
}

#[derive(SimpleObject)]
#[graphql(complex)]
struct Token {
Expand Down
13 changes: 7 additions & 6 deletions backend-rust/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1960,21 +1960,22 @@ impl PreparedContractInitialized {
}
}

/// The token name is generated by using a `version byte 2` and concatenating it
/// with the leb128 byte encoding of the contract index and the leb128 byte
/// The token address is generated by using a `version byte 2` and concatenating
/// it with the leb128 byte encoding of the contract index and the leb128 byte
/// encoding of the contract subindex concatenated with the token id in bytes.
/// Finally the whole byte array is base 58 check encoded.
/// https://proposals.concordium.software/CIS/cis-2.html#token-address
/// The token address is a unique identifier used to distinguish tokens across
/// all smart contracts.
pub fn get_token_address(
contract_index: u64,
contract_subindex: u64,
token_id: &TokenId,
) -> Result<String, anyhow::Error> {
// Encode the contract index and subindex as unsigned LEB128.
let mut contract_index_bytes = Vec::new();
let mut contract_index_bytes = Vec::with_capacity(64);
encode_leb128(&mut contract_index_bytes, contract_index)?;

let mut contract_subindex_bytes = Vec::new();
let mut contract_subindex_bytes = Vec::with_capacity(64);
encode_leb128(&mut contract_subindex_bytes, contract_subindex)?;

let token_id_bytes = token_id.as_ref();
Expand All @@ -1983,7 +1984,7 @@ pub fn get_token_address(
1 + contract_index_bytes.len() + contract_subindex_bytes.len() + token_id_bytes.len();
let mut bytes = Vec::with_capacity(total_length);

// Fill in the byte buffer.
// Fill in the bytes.
bytes.push(2); // version byte 2
bytes.extend_from_slice(&contract_index_bytes);
bytes.extend_from_slice(&contract_subindex_bytes);
Expand Down

0 comments on commit d018345

Please sign in to comment.