API Reference
This section documents the Candid interfaces for all Hello World Co-Op DAO canisters. Each canister exposes a set of methods that can be called from frontend applications or other canisters.
Overview
| Canister | Purpose | Standards |
|---|---|---|
| auth-service | Session management, password validation | Custom |
| user-service | User registration, profile management | Custom |
| membership | ICRC-7 Soul-Bound Token credentials | ICRC-7, ICRC-37 |
| dom-token | ICRC-1/2 token ledger with burn policies | ICRC-1, ICRC-2 |
| governance | Proposal system with vote-pass NFTs | ICRC-7 |
| treasury | Payment records, payout management | Custom |
| identity-gateway | Internet Identity integration | Custom |
Understanding Candid
Candid is the interface description language for the Internet Computer. It defines:
- Types: Records, variants, options, vectors
- Methods: Query (read-only) and update (state-changing)
- Service: The collection of methods a canister exposes
Type Conventions
candid
// Records are like structs
type Account = record {
owner : principal;
subaccount : opt blob;
};
// Variants are like enums
type Result = variant {
Ok : nat;
Err : text;
};
// Common types
principal // IC identity
nat // Natural number (unbounded)
nat64 // 64-bit natural number
text // UTF-8 string
blob // Binary data
opt T // Optional value
vec T // Vector/arrayCalling Canister Methods
From TypeScript (Frontend)
typescript
import { Actor, HttpAgent } from '@dfinity/agent';
import { idlFactory } from './declarations/auth-service';
const agent = new HttpAgent({ host: 'https://ic0.app' });
const actor = Actor.createActor(idlFactory, {
agent,
canisterId: 'your-canister-id',
});
// Call a query method (fast, no consensus)
const health = await actor.health();
// Call an update method (requires consensus)
const result = await actor.login_email_password(
'user@example.com',
'password123',
'device-fingerprint',
[], // opt ip_address
[], // opt timezone
[] // opt user_agent
);From Rust (Backend)
rust
use ic_cdk::call;
use candid::Principal;
// Inter-canister call
let auth_canister = Principal::from_text("auth-canister-id").unwrap();
let (result,): (Result<SessionInfo, String>,) = call(
auth_canister,
"validate_session",
(access_token, current_ip_hash)
).await?;From dfx CLI
bash
# Query method
dfx canister call auth-service health
# Update method
dfx canister call auth-service login_email_password \
'("user@example.com", "password", "device-fp", null, null, null)'Common Patterns
Result Types
Most methods return a variant { Ok: T; Err: text } pattern:
typescript
const result = await actor.create_proposal(args);
if ('Ok' in result) {
console.log('Proposal ID:', result.Ok);
} else {
console.error('Error:', result.Err);
}Optional Parameters
Use empty array [] for opt types in JavaScript:
typescript
// Candid: (text, opt text) -> (Result)
await actor.some_method("required", []); // No optional value
await actor.some_method("required", ["optional-value"]); // With optionalTimestamps
All timestamps are stored as nat64 nanoseconds since Unix epoch:
typescript
// Convert JS Date to nanoseconds
const timestamp = BigInt(Date.now()) * 1_000_000n;
// Convert nanoseconds to JS Date
const date = new Date(Number(timestamp / 1_000_000n));Error Handling
Standard Error Patterns
typescript
try {
const result = await actor.cast_vote(proposalId, { Yes: null });
if ('Err' in result) {
// Handle canister-level error
switch (result.Err) {
case 'Not a member':
// Handle membership error
break;
case 'Already voted':
// Handle duplicate vote
break;
default:
// Handle unknown error
}
}
} catch (e) {
// Handle network/agent-level error
console.error('Network error:', e);
}Next Steps
- Browse individual canister APIs using the sidebar
- See Error Catalog for error codes