Skip to main content

Overview

The ProposalTypes module defines the core data structures for representing governance proposals in the OpenChat Bot SDK. These types are used throughout the proposal service to represent proposal data, status, and filtering arguments.

Types

ProposalId

Unique identifier for a governance proposal.
public type ProposalId = Nat64;
Represents a 64-bit natural number used as a unique identifier for proposals. Proposal IDs are sequential and increase over time.

Proposal

Internal representation of a governance proposal with mutable fields.
public type Proposal = {
  id : ProposalId;
  topicId : Int32;
  title : Text;
  description : ?Text;
  proposer : Nat64;
  timestamp : Nat64;
  var status : ProposalStatus;
  var deadlineTimestampSeconds : ?Nat64;
  proposalTimestampSeconds : Nat64;
};
id
ProposalId
required
Unique identifier for the proposal
topicId
Int32
required
The topic/function ID that categorizes the proposal (e.g., Governance, Network Economics, etc.)
title
Text
required
Human-readable title of the proposal
description
?Text
Optional detailed description or summary of the proposal
proposer
Nat64
required
Neuron ID of the entity that created the proposal
timestamp
Nat64
required
Timestamp when the proposal was processed (in nanoseconds since epoch)
status
ProposalStatus
required
Current status of the proposal (mutable field)
deadlineTimestampSeconds
?Nat64
Optional deadline for voting on the proposal (in seconds since epoch)
proposalTimestampSeconds
Nat64
required
Timestamp when the proposal was originally created (in seconds since epoch)

ProposalAPI

API-safe representation of a proposal with immutable fields.
public type ProposalAPI = {
  id : ProposalId;
  topicId : Int32;
  title : Text;
  description : ?Text;
  proposer : Nat64;
  timestamp : Nat64;
  status : ProposalStatus;
  deadlineTimestampSeconds : ?Nat64;
  proposalTimestampSeconds : Nat64;
};
Identical structure to Proposal, but all fields are immutable. This type is suitable for returning from public API methods or sending across canister boundaries. Conversion: Use proposalToAPI() from ProposalMappings to convert a Proposal to ProposalAPI.

ProposalStatus

Represents the current state of a governance proposal.
public type ProposalStatus = {
  #Pending;
  #Executed : {#Approved; #Rejected}
};
#Pending
variant
The proposal is currently open for voting and has not been executed yet
#Executed
variant
The proposal has been executed with one of two outcomes:
  • #Approved: The proposal was accepted and executed successfully
  • #Rejected: The proposal was rejected and not executed
Status Code Mapping: The NNS governance canister uses integer status codes:
  • 1#Pending
  • 4#Executed(#Approved)
  • 2#Executed(#Rejected)

ListProposalArgs

Arguments for filtering and configuring proposal list queries.
public type ListProposalArgs = {
  includeRewardStatus : [Int32];
  omitLargeFields : ?Bool;
  excludeTopic : [Int32];
  includeAllManageNeuronProposals : ?Bool;
  includeStatus : [Int32];
};
includeRewardStatus
[Int32]
required
Array of reward status codes to include in results. Empty array means no filtering by reward status.
omitLargeFields
?Bool
If true, large fields (like detailed proposal payloads) are omitted from results to reduce response size
excludeTopic
[Int32]
required
Array of topic IDs to exclude from results. Useful for filtering out specific proposal types.
includeAllManageNeuronProposals
?Bool
If true, includes all ManageNeuron proposals. If false or null, may filter out some ManageNeuron proposals.
includeStatus
[Int32]
required
Array of status codes to include in results. Empty array means no filtering by status.
Example:
let args : ListProposalArgs = {
  includeRewardStatus = [];
  omitLargeFields = ?true;
  excludeTopic = [3, 7]; // Exclude topics 3 and 7
  includeAllManageNeuronProposals = null;
  includeStatus = [1]; // Only include pending proposals
};

Mapping Functions

The ProposalMappings module provides utility functions for converting between different proposal representations.

proposalToAPI

Converts a Proposal to ProposalAPI format.
public func proposalToAPI(p : Proposal) : ProposalAPI
p
Proposal
required
The proposal to convert
ProposalAPI
ProposalAPI
Returns an immutable API-safe version of the proposal
Example:
let proposal : Proposal = /* ... */;
let apiProposal = proposalToAPI(proposal);

mapProposal

Maps a governance canister’s ProposalInfo to the SDK’s Proposal type.
public func mapProposal(
  nnsProposal : ProposalInfo
) : Result.Result<Proposal, Text>
nnsProposal
ProposalInfo
required
Raw proposal data from the governance canister
Result
Result<Proposal, Text>
Returns:
  • #ok(Proposal) if mapping succeeds
  • #err(Text) if required fields are missing or status is unknown
Validation: Returns an error if:
  • Proposal has no ID
  • Proposal has no proposer
  • Status cannot be mapped
Example:
let nnsProposal : ProposalInfo = /* from governance canister */;
switch (mapProposal(nnsProposal)) {
  case (#ok(proposal)) {
    // Successfully mapped
  };
  case (#err(error)) {
    Debug.print("Mapping error: " # error);
  };
};

mapGetProposals

Maps an array of ProposalInfo objects to an array of Proposal objects, silently skipping invalid proposals.
public func mapGetProposals(
  nnsProposals : [ProposalInfo]
) : [Proposal]
nnsProposals
[ProposalInfo]
required
Array of raw proposal data from the governance canister
Proposals
[Proposal]
Returns an array of successfully mapped proposals. Invalid proposals are silently excluded.
Example:
let nnsProposals : [ProposalInfo] = /* from governance canister */;
let proposals = mapGetProposals(nnsProposals);
Debug.print("Mapped " # Int.toText(proposals.size()) # " proposals");

Status Mapping

Internal function that maps NNS status codes to ProposalStatus:
func mapStatus(nnsStatus : Int32) : Result.Result<ProposalStatus, Text>
NNS Status CodeProposalStatus
1#Pending
4#Executed(#Approved)
2#Executed(#Rejected)
OtherError: “Unknown proposal status”

Usage Example

Complete example of fetching and working with proposals:
import ProposalService "ProposalService";
import ProposalTypes "ProposalTypes";
import ProposalMappings "ProposalMappings";

let proposalService = ProposalService.ProposalService(governanceService, logService);

// Get valid topics
let #ok(topics) = await* proposalService.getValidTopicIds("rrkah-fqaaa-aaaaa-aaaaq-cai")
else { return #err("Failed to get topics") };

// Create filter arguments
let args : ProposalTypes.ListProposalArgs = {
  includeRewardStatus = [];
  omitLargeFields = ?true;
  excludeTopic = []; // Include all topics
  includeAllManageNeuronProposals = ?true;
  includeStatus = [1]; // Only pending proposals
};

// Fetch proposals after ID 10000
let #ok(response) = await* proposalService.listProposalsAfterId(
  "rrkah-fqaaa-aaaaa-aaaaq-cai",
  ?10000,
  args
) else { return #err("Failed to fetch proposals") };

// Map to SDK format
let proposals = ProposalMappings.mapGetProposals(response.proposal_info);

// Convert to API format for response
let apiProposals = Array.map(proposals, ProposalMappings.proposalToAPI);

Build docs developers (and LLMs) love