Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Encoding and types

What this teaches: which crates own which user-facing types, how numeric units are represented, and the shape of GraphQL response data.

Where types live

dango-sdk is thin: most user-facing types are re-exported by the SDK, dango_types, and indexer_graphql_types.

TypeCrateNotes
Addr, Hash256, Binary, ByteArray<N>CoreStrongly-typed wrappers over fixed-size byte arrays.
Message, Tx, UnsignedTx, Block, BlockOutcome, TxOutcomeCoreCore chain types.
Coins, Denom, Coin, Uint128, Uint256CoreBank balances and unsigned integers.
NonEmpty<T>, Defined<T>, Undefined<T>, MaybeDefined<T>CoreTypestate helpers.
Key, Signature, SignDoc, Nonce, UserIndexdango_types::auth / dango_types::account_factoryAccount-factory primitives.
PageInfo, <query>::Variables, <query>::ResponseData, generated *Nodes/*Edgesindexer_graphql_typesGraphQL codegen surface, re-exported at the dango_sdk crate root.
SubscribeBlock, …, SubscribeQueryStatus (×14)indexer_graphql_typesOne marker struct per subscription. Each has a snake-case module of Variables/ResponseData.
WsErrordango_sdkThe only public typed error in the crate.

Base units, not human units

Amounts on the wire are integers in base units (the contract's smallest denomination). Coins::one("bridge/usdc", 100_000_000_u128) is 100 USDC, not 100 micro-USDC.

the SDK exposes Uint128/Uint256 for amounts. Convert to display units at the edge — there is no SDK-side Decimal.

Addresses

Addr is a 20-byte fixed array, hex-encoded with the 0x prefix in display form.

use {grug::Addr, std::str::FromStr};
 
let addr = Addr::from_str("0x0000000000000000000000000000000000000000")?;
println!("{addr}");          // 0x0000...
let bytes: [u8; 20] = addr.into_inner();
// Ok::<(), anyhow::Error>(())

Hashes

Hash256 is a 32-byte hash, hex-encoded. Used for transaction hashes, key hashes, and content hashes.

use {grug::Hash256, std::str::FromStr};
let hash = Hash256::from_str("0x0000000000000000000000000000000000000000000000000000000000000000")?;
// Ok::<(), anyhow::Error>(())

GraphQL response types

Every query and subscription generates three pieces of code:

  1. A marker struct, e.g. SubscribeTrades. Use as the generic argument: session.subscribe::<SubscribeTrades>(...).
  2. A snake-case module — subscribe_trades — exposing Variables, ResponseData, and nested *Nodes records.
  3. An impl Variables for subscribe_trades::Variables { type Query = SubscribeTrades; } linking the two.
use dango_sdk::{SubscribeTrades, subscribe_trades};
 
let variables = subscribe_trades::Variables {
    base_denom:  "dango".into(),
    quote_denom: "bridge/usdc".into(),
};

All generated types derive Debug + Clone + PartialEq + Eq. Variables types derive Default so partial construction with ..Default::default() is idiomatic.

Connection nodes

Indexer queries return Relay-style connections: { nodes, page_info: PageInfo }. The paginate helpers extract nodes and follow cursors. Each query has its own node type (accounts::AccountsAccountsNodes, transfers::TransfersTransfersNodes, …) — see the SubscriptionVariables index for the subscription set.

Serializing dynamic payloads

Smart-contract calls and queries are JSON-encoded. the SDK provides JsonSerExt / JsonDeExt for typed encode/decode of any Serialize/Deserialize value:

use grug::JsonSerExt;
let json = my_struct.to_json_value()?;
// Ok::<(), anyhow::Error>(())

Message::execute and Message::transfer accept typed payloads directly; you rarely need raw JSON.

Next