Skip to content

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

CanisterPurposeStandards
auth-serviceSession management, password validationCustom
user-serviceUser registration, profile managementCustom
membershipICRC-7 Soul-Bound Token credentialsICRC-7, ICRC-37
dom-tokenICRC-1/2 token ledger with burn policiesICRC-1, ICRC-2
governanceProposal system with vote-pass NFTsICRC-7
treasuryPayment records, payout managementCustom
identity-gatewayInternet Identity integrationCustom

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/array

Calling 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 optional

Timestamps

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

Hello World Co-Op DAO