> For the complete documentation index, see [llms.txt](https://docs.realms.today/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.realms.today/developer-resources/integrate-realms.md).

# Integrate Realms

## Integrate Realms Into Your Stack

This guide covers how to integrate SPL Governance (Realms) into your application, whether you're building a DeFi protocol, NFT project, or any on-chain application that needs decentralized decision-making.

### Integration Approaches

#### 1. Use Realms as Your Upgrade Authority

The simplest integration: let your DAO control program upgrades.

```bash
# Transfer program upgrade authority to your DAO wallet
solana program set-upgrade-authority <PROGRAM_ID> \
  --new-upgrade-authority <DAO_WALLET_ADDRESS>
```

The DAO Wallet is the native treasury PDA derived from your Governance account. Once transferred, all program upgrades must go through a governance vote.

#### 2. Use the DAO Wallet as Admin Authority

If your program has admin/authority accounts, point them to the DAO Wallet:

```rust
// In your program's initialize instruction
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
    let config = &mut ctx.accounts.config;
    config.authority = dao_wallet_address; // DAO controls this program
    Ok(())
}
```

Any instruction in your program that requires this authority can now only be executed through a governance proposal.

#### 3. SDK Integration

**Install**

```bash
npm install @realms-today/spl-governance @solana/web3.js
```

**Read Governance Data**

```typescript
import {
  getRealm,
  getGovernance,
  getProposal,
  getTokenOwnerRecord,
  getAllGovernances,
  getAllProposals,
  getVoteRecordsByVoter,
  GOVERNANCE_PROGRAM_ID,
} from '@realms-today/spl-governance';

// Fetch realm info
const realm = await getRealm(connection, realmAddress);
console.log('Realm:', realm.account.name);
console.log('Community Mint:', realm.account.communityMint.toBase58());

// Fetch all governances
const governances = await getAllGovernances(connection, programId, realmAddress);

// Fetch proposals for a governance
const proposals = await getAllProposals(connection, programId, governanceAddress);

// Check a user's voting power
const tokenOwnerRecord = await getTokenOwnerRecord(connection, torAddress);
console.log('Voting power:', tokenOwnerRecord.account.governingTokenDepositAmount.toString());
```

**Create Governance Actions**

The SDK uses a builder pattern where all instruction-building functions are prefixed with `with` and push instructions onto a `TransactionInstruction[]` array:

```typescript
import {
  withCreateProposal,
  withInsertTransaction,
  withSignOffProposal,
  withCastVote,
  withExecuteTransaction,
  VoteType,
  Vote,
} from '@realms-today/spl-governance';
import { TransactionInstruction } from '@solana/web3.js';

// Full proposal lifecycle
const instructions: TransactionInstruction[] = [];

const proposalAddress = await withCreateProposal(instructions, /* ... */);
const txAddress = await withInsertTransaction(instructions, /* ... */);
withSignOffProposal(instructions, /* ... */);
// ... voting period ...
const voteRecord = await withCastVote(instructions, /* ... */);
// ... after vote succeeds + hold_up_time ...
await withExecuteTransaction(instructions, /* ... */);
```

#### 4. Embed Governance in Your dApp

Display governance data within your own frontend:

```typescript
// Fetch and display active proposals
async function getActiveProposals(realmAddress: PublicKey) {
  const governances = await getAllGovernances(connection, programId, realmAddress);

  const allProposals = [];
  for (const gov of governances) {
    const proposals = await getAllProposals(connection, programId, gov.pubkey);
    allProposals.push(...proposals.flat());
  }

  return allProposals
    .filter(p => p.account.state === ProposalState.Voting)
    .sort((a, b) =>
      b.account.votingAt.toNumber() - a.account.votingAt.toNumber()
    );
}
```

#### 5. Plugin Integration

If your protocol has a custom token model (staking, locking, etc.), build a governance plugin so your token holders can vote with their staked/locked tokens. See Create a Custom Plugin for details.

### Architecture Patterns

#### Pattern A: Governance-Controlled Protocol

```
┌──────────────┐    vote    ┌──────────────┐   execute   ┌──────────────┐
│  Token Holder │ ────────► │  SPL         │ ──────────► │  Your        │
│  Community    │           │  Governance  │             │  Protocol    │
└──────────────┘           └──────────────┘             └──────────────┘
                                  │
                                  ▼
                           ┌──────────────┐
                           │  DAO Wallet   │
                           │  (Treasury)   │
                           └──────────────┘
```

#### Pattern B: Multi-Governance Setup

Create multiple governances within a single realm for different security tiers:

```typescript
import { GovernanceConfig, VoteThreshold, VoteThresholdType, VoteTipping } from '@realms-today/spl-governance';

// High-security governance (e.g., program upgrades)
const highSecConfig = new GovernanceConfig({
  communityVoteThreshold: new VoteThreshold({ type: VoteThresholdType.YesVotePercentage, value: 80 }),
  baseVotingTime: 7 * 24 * 3600,           // 7 days
  minInstructionHoldUpTime: 3 * 24 * 3600,  // 3 day delay
  /* ... other required fields */
});

// Low-security governance (e.g., parameter tweaks)
const lowSecConfig = new GovernanceConfig({
  communityVoteThreshold: new VoteThreshold({ type: VoteThresholdType.YesVotePercentage, value: 50 }),
  baseVotingTime: 2 * 24 * 3600,            // 2 days
  minInstructionHoldUpTime: 0,
  /* ... other required fields */
});
```

#### Pattern C: Council + Community Hybrid

Use a council for quick decisions and community for major changes:

```typescript
import { withCreateRealm, MintMaxVoteWeightSource } from '@realms-today/spl-governance';

const instructions: TransactionInstruction[] = [];

const realmAddress = await withCreateRealm(
  instructions,
  programId,
  programVersion,
  'My DAO',
  realmAuthority,
  communityMint,     // large community
  payer,
  councilMint,       // small council (e.g., core team)
  MintMaxVoteWeightSource.FULL_SUPPLY_FRACTION,
  new BN(1),
);

// Council governance: fast, low threshold
// Community governance: slow, high threshold
```

### Deployment Models

#### Shared Instance (Quick Start)

Use the public governance program instance:

```typescript
const GOVERNANCE_PROGRAM_ID = new PublicKey('GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw');
```

#### Own Instance (Maximum Control)

Deploy your own instance for full sovereignty:

```bash
# Build the program
cargo build-sbf --manifest-path governance/program/Cargo.toml

# Deploy
solana program deploy target/deploy/spl_governance.so

# Transfer upgrade authority to your DAO
solana program set-upgrade-authority <PROGRAM_ID> \
  --new-upgrade-authority <DAO_WALLET>
```

This way your DAO governs its own governance program - no external party can change the rules.

### SPL Token 2022 Support

SPL Governance v3.1.2 supports Token-2022 (Token Extensions) for both community and council mints. Pass the appropriate `GoverningTokenConfigAccountArgs` with the token type when creating the realm:

```typescript
import {
  withCreateRealm,
  MintMaxVoteWeightSource,
  GoverningTokenConfigAccountArgs,
  GoverningTokenType,
} from '@realms-today/spl-governance';

const instructions: TransactionInstruction[] = [];

const realmAddress = await withCreateRealm(
  instructions,
  programId,
  programVersion,
  'My Token-2022 DAO',
  realmAuthority,
  communityMint2022,
  payer,
  councilMint,
  MintMaxVoteWeightSource.FULL_SUPPLY_FRACTION,
  new BN(1),
  // Community token config (Token-2022)
  new GoverningTokenConfigAccountArgs({
    voterWeightAddin: undefined,
    maxVoterWeightAddin: undefined,
    tokenType: GoverningTokenType.Liquid,
  }),
  // Council token config (standard SPL Token)
  new GoverningTokenConfigAccountArgs({
    voterWeightAddin: undefined,
    maxVoterWeightAddin: undefined,
    tokenType: GoverningTokenType.Liquid,
  }),
);
```
