Skip to content

Checking access...

Treasury API Reference ​

Canister: treasury Candid Interface: treasury.did — the live .did is the source of truth for all method names and signatures. Last reconciled: 2026-08-25 (bl-1404 — unified from the former treasury.md quick-ref and treasury-api.md comprehensive guide; signatures re-derived from the live Candid interface).


Overview ​

The treasury canister is the DAO's on-chain financial system of record. It provides role-gated payout management with multi-signature approval, membership-payment records, conditional and milestone-based escrow, annual profit-sharing and patronage distributions, DOM-token vesting, an internal sub-account ledger, a digital-asset registry, cross-entity transfer records, and point-in-time asset snapshots.

Per ADR-014 (records on-chain, business logic off-chain), the treasury records financial state and the Subchapter-T-required audit trail on-chain; oracle-bridge orchestrates the off-chain workflow and calls in over the service-principal auth boundary.

Method groups ​

  • Payout management — propose / approve / execute / retry payouts, with a governance-orchestrated entrypoint
  • Payment records — membership-fee payment history (Stripe-backed, written by oracle-bridge)
  • Escrow — conditional single-release escrow
  • Milestone escrow — multi-milestone escrow with approve / release / dispute / resolve
  • Profit sharing — annual member distributions with proration
  • Patronage credits — Subchapter-T patronage allocation, claim, and reversion
  • Vesting — DOM-token vesting schedules (federation partner token locks)
  • Sub-accounts & internal transfers — the account-type ledger with an audit trail
  • Digital-asset registry & reconciliation — asset entries, cross-entity transfers, snapshots, floor-value calculation
  • Configuration & backup — canister wiring, signing key, state export/import

Authentication ​

Methods authenticate on the caller principal via ic_cdk::caller(). The common access levels are:

  • Controllers — canister controllers (configuration, escrow/vesting/registry writes, distribution lifecycle)
  • oracle-bridge service principal — the off-chain orchestrator; gates payout proposal/approval/execution (AUTH-003.3) and payment recording
  • principals.is_authorized OR-gate — several lifecycle processors accept controller OR the configured oracle-bridge service principal OR principals.is_authorized(caller, "treasury:lifecycle:process") — an OR, never an AND (bl-1159)
  • Release authority — escrow releases are gated to the escrow's configured ReleaseAuthority (Controller / Governance / a specific principal)
  • Member — a member claims their own distribution / patronage

Auth-service note (2026-04-11): session-token variants (get_payment_history_with_session, get_payment_count_with_session) and set_auth_service were removed when the auth-service canister was decommissioned. Session validation now happens off-chain in oracle-bridge; the on-chain queries are keyed on principal. If you are migrating from an older client, use get_payment_history / get_payment_count below.


Core Types ​

candid
type PaymentType = variant { Initial; Renewal };

type PaymentStatus = variant { Succeeded; Failed; Pending };

type PaymentRecord = record {
  id: nat64;
  user_id: principal;
  amount: nat;
  currency: text;
  payment_type: PaymentType;
  status: PaymentStatus;
  stripe_payment_intent_id: text;
  receipt_number: opt text;
  payment_method_last4: text;
  timestamp: nat64;
};

type TokenType = variant { ICP; DOM };

type PayoutStatus = variant { Proposed; Approved; Executed; Failed };

type Payout = record {
  id: nat64;
  to: principal;
  amount: nat;
  reason: text;
  token_type: TokenType;
  status: PayoutStatus;
  approved_by: vec principal;
  proposed_at: nat64;
  executed_at: opt nat64;
  tx_id: opt text;
};

type TreasuryConfig = record {
  required_approvals: nat32;
  dom_token_canister: opt principal;
};

type TreasuryPolicy = record {
  max_single_payout: nat;
  daily_limit: nat;
  required_approvals: nat32;
  large_payout_threshold: nat;
  allowed_tokens: vec TokenType;
};

Additional record/variant types back the escrow, milestone, profit-sharing, patronage, vesting, sub-account, digital-asset, entity-transfer, and snapshot method groups — see the live .did for their full definitions.


Health ​

health (query) ​

candid
health : () -> (text) query;

Health check for uptime monitoring. Returns a status string.

bash
dfx canister call treasury health

Payout Management ​

Payouts move funds out of the treasury. A payout is proposed, gathers approvals up to the configured threshold, and is then executed. Proposal/approval/execution are gated to the oracle-bridge service principal (AUTH-003.3); retry_payout is controllers-only.

propose_payout ​

candid
propose_payout : (principal, nat, text, TokenType) -> (variant { Ok: nat64; Err: text });

Create a new payout proposal. Parameters: recipient principal, amount (smallest token units, e8s), reason text, and TokenType (ICP or DOM). Returns the new payout ID.

typescript
const res = await treasuryActor.propose_payout(
  Principal.fromText("aaaaa-aa"),
  BigInt(100_000_000),        // 1 DOM (8 decimals)
  "Developer compensation - Q1",
  { DOM: null }
);
if ('Ok' in res) console.log("Payout ID:", res.Ok);

propose_payout_with_options ​

candid
propose_payout_with_options : (principal, nat, text, TokenType, opt nat64, opt bool, opt nat64) -> (variant { Ok: nat64; Err: text });

Propose a payout with extended spending-authority options (BL-087): amount_usd_cents (USD value for threshold enforcement), emergency flag, and a governance proposal_id for above-threshold payouts. All three are optional.

propose_payout_for_governance_proposal ​

candid
propose_payout_for_governance_proposal : (nat64, principal, nat, text, TokenType) -> (variant { Ok: nat64; Err: text });

Dedicated governance-orchestrated payout entrypoint. Gated by the OR-gate (oracle-bridge principal OR principals.is_authorized(caller, "treasury:payout:execute")). Independently verifies (to, amount, token_type) against the on-chain governance proposal (category == Treasury, status == Executing, execution_data JSON match) and deduplicates retries by proposal_id.

approve_payout ​

candid
approve_payout : (nat64) -> (variant { Ok: text; Err: text });

Add an approval to a payout proposal (oracle-bridge principal only). When the approval count reaches the configured threshold the payout becomes eligible for execution.

execute_payout ​

candid
execute_payout : (nat64) -> (variant { Ok: text; Err: text });

Execute an approved payout, transferring funds to the recipient. execute_payout ceiling-gates every caller that is NOT the configured oracle_bridge principal against auto_execute_ceiling (USD cents; default 0 = human-execute-only).

retry_payout ​

candid
retry_payout : (nat64) -> (variant { Ok: text; Err: text });

Retry a failed payout (controllers only).

Queries ​

candid
get_payout : (nat64) -> (opt Payout) query;
list_payouts : (opt PayoutStatus) -> (vec Payout) query;
get_payout_history : (nat32, nat32) -> (vec Payout) query;   // (page, page_size)

Multi-sig payout workflow ​

typescript
// 1. Propose (oracle-bridge principal)
const { Ok: payoutId } = await treasuryActor.propose_payout(
  Principal.fromText("aaaaa-aa"), BigInt(50_000_000), "Marketing budget", { DOM: null }
);

// 2. Approve until threshold reached
await treasuryActor.approve_payout(payoutId);

// 3. Execute
await treasuryActor.execute_payout(payoutId);

Payment Records ​

Membership-fee payments recorded on-chain after Stripe confirmation. Written by oracle-bridge (controllers only); read by suites and admin surfaces.

record_payment ​

candid
record_payment : (principal, nat, PaymentType, text, text, opt text) -> (nat64);

Record a payment. Parameters: user_id, amount, PaymentType, stripe_payment_intent_id, payment_method_last4, receipt_number (opt). Returns the new payment ID. Note: returns a bare nat64, not a Result.

get_payment_history (query) ​

candid
get_payment_history : (principal, nat32, nat32, opt PaymentType, opt nat64, opt nat64) -> (vec PaymentRecord) query;

Paginated payment history. Parameters: user_id, page, page_size, payment_type (opt filter), from_date / to_date (opt nanosecond bounds).

typescript
const payments = await treasuryActor.get_payment_history(
  Principal.fromText(userId), 0, 10, [], [], []
);

get_payment_count (query) ​

candid
get_payment_count : (principal, opt PaymentType, opt nat64, opt nat64) -> (nat64) query;

Count payments for a user with the same optional filters.

cleanup_old_payments ​

candid
cleanup_old_payments : () -> (nat64);

GDPR/retention processor — removes payments past the retention window. Returns the deleted count as a bare nat64 (a refusal traps). Auth: the treasury:lifecycle:process OR-gate (bl-1159).


Configuration (controllers only) ​

Canister wiring and policy. Highlights:

candid
set_oracle_bridge_principal : (principal) -> (variant { Ok; Err: text });
get_oracle_bridge_principal : () -> (opt principal) query;
set_principals_canister : (principal) -> (variant { Ok; Err: text });
clear_principals_canister : () -> (variant { Ok; Err: text });        // kill switch for the is_authorized OR-gate
get_principals_canister : () -> (opt principal) query;
set_governance_canister : (principal) -> (variant { Ok; Err: text }); // for the anti-drain get_proposal query
get_governance_canister : () -> (opt principal) query;
set_governance_service_principal : (principal) -> (variant { Ok; Err: text });
get_governance_service_principal : () -> (opt principal) query;
set_auto_execute_ceiling : (nat64) -> (variant { Ok; Err: text });   // USD cents; default 0 = human-execute-only
get_auto_execute_ceiling : () -> (opt nat64) query;
set_dom_token_canister : (principal) -> (variant { Ok; Err: text });
set_required_approvals : (nat32) -> (variant { Ok; Err: text });
get_treasury_config : () -> (TreasuryConfig) query;
set_policy : (TreasuryPolicy) -> (variant { Ok; Err: text });
get_policy : () -> (TreasuryPolicy) query;

Oracle-bridge notification + request signing (BL-002.2 / bl-1177): set_oracle_bridge : (text), clear_oracle_bridge : (), initialize_signing_key : (), get_signing_public_key : () query. The Ed25519 signing secret is generated in-canister and never leaves it; get_signing_public_key exposes only the derived public key for oracle-bridge's dynamic discovery. transform_http_response supports IC HTTP outcalls (system use).


Additional live method groups ​

The following method groups are live in the canonical .did. Their full per-method signatures and parameter semantics are authoritative there; the summaries below name each method so you can find it. (A method-by-method expansion of these groups is a documentation follow-up — file against docs if you need one.)

Escrow ​

Conditional single-release escrow with a configurable ReleaseAuthority.

  • create_escrow, release_escrow (optional partial-release amount), cancel_escrow, get_escrow (query), list_escrows (query), process_expired_escrows (lifecycle processor)

Milestone escrow ​

Multi-milestone escrow with per-milestone approval, release, and dispute resolution.

  • create_milestone_escrow, approve_milestone, release_milestone, dispute_milestone, resolve_dispute, get_milestone_status (query)

Profit sharing (annual member distributions) ​

Proration-aware annual distributions (26 CFR §1.6001-1 audit trail; ProrationBasis distinguishes a supplied join date from an assumed full year — bl-1094).

  • set_distribution_cap, initiate_profit_sharing, approve_distribution, cancel_distribution, execute_distribution, claim_profit_share, claim_profit_share_for (service-vouched twin, ADR-014 C1), process_unclaimed_distributions, get_distribution_status (query), get_member_distribution (query), get_my_distribution (query), list_distributions (query)

Patronage credits (Subchapter T) ​

  • initialize_member_equity_accounts, allocate_patronage, claim_patronage, claim_patronage_for (service-vouched twin), process_patronage_reversions, get_member_patronage (query), set_patronage_claim_window

Vesting (BL-088 — DOM-token federation-partner locks) ​

  • create_vesting_schedule, get_vesting_schedule (query), list_vesting_schedules (query), get_vested_balance (query), pause_vesting, resume_vesting, forfeit_vesting

Sub-accounts & internal transfers (BL-075.1 / BL-075.2) ​

The account-type ledger (Operating, Capital, MemberEquity, Escrow, Restricted, DigitalAsset, Reconciliation) with an audit trail.

  • create_sub_account, get_sub_account (query), list_sub_accounts (query), deposit_to_sub_account, transfer_between_accounts, get_transfer_history (query)

Digital-asset registry, cross-entity transfers & reconciliation (BL-079.1 / BL-077 / BL-079.2) ​

  • Registry: register_digital_asset, update_digital_asset, remove_digital_asset, list_digital_assets (query)
  • Cross-entity transfers: record_entity_transfer, get_entity_transfers (query), get_entity_balance_summary (query)
  • Reconciliation: create_asset_snapshot, get_snapshot (query), diff_snapshots (query), calculate_floor_value (query)
  • Asset contributions: record_asset_contribution, get_member_contributions (query)

Balance & backup ​

  • get_treasury_balance : () -> (variant { Ok: TreasuryBalance; Err: text })
  • export_state : () -> (blob) query (public — financial data is auditable), import_state : (blob) (controller-only)

Error Handling ​

Most update methods return variant { Ok; Err : text } (or Ok : nat64 / Ok : text). Handle both arms:

typescript
const res = await treasuryActor.execute_payout(payoutId);
if ('Err' in res) {
  console.error("Payout failed:", res.Err);
}

Common error strings:

ErrorCauseResolution
Unauthorized / auth errorCaller is not a controller / not the oracle-bridge principal / not authorizedUse the authorized identity
Payment not found / Payout not foundInvalid IDVerify the ID exists
Payout not approvedExecuting before the approval threshold is metCollect the required approvals first
Insufficient-balance errorTreasury balance below the payout amountFund the treasury

Hello World DAO