Skip to main content

SDK Overview

@snapshot-labs/sx is the official TypeScript SDK for interacting with Snapshot X governance infrastructure. It provides a unified interface for creating and managing governance actions across multiple blockchain networks and offchain environments.

What is @snapshot-labs/sx?

The SDK is a comprehensive toolkit that enables developers to:
  • Create and manage governance spaces
  • Submit and vote on proposals
  • Execute approved proposals onchain
  • Implement custom voting strategies
  • Support multiple blockchain networks (Ethereum, Starknet, Polygon, Arbitrum, Optimism, Base, Mantle, and more)
  • Work with offchain Snapshot spaces
  • Handle cross-chain governance scenarios

Key Features

Multi-Network Support

The SDK supports three execution environments:
  • EVM Networks: Ethereum mainnet, Sepolia, Optimism, Polygon, Arbitrum, Base, Mantle, and ApeChain
  • Starknet: Native Starknet transactions and cross-chain messaging
  • Offchain: Traditional Snapshot spaces with gasless voting

Flexible Client Architecture

The SDK provides specialized clients for different signing and transaction patterns:
  • Signature-based clients (EthereumSig, StarknetSig) for gasless meta-transactions
  • Transaction clients (EthereumTx, StarknetTx) for direct onchain interactions
  • Protocol-specific clients for Compound Governor Bravo and OpenZeppelin Governor

Type-Safe TypeScript

Fully typed interfaces with comprehensive TypeScript definitions for all methods and data structures.

Package Structure

The SDK is organized into four main modules:

Clients

Clients handle the creation and submission of governance actions. Available clients include:
import { clients } from '@snapshot-labs/sx';

// EVM clients for Snapshot X spaces
const evmEthereumSig = new clients.EvmEthereumSig(config);
const evmEthereumTx = new clients.EvmEthereumTx(config);

// Starknet clients
const starknetSig = new clients.StarknetSig(config);
const starknetTx = new clients.StarknetTx(config);

// Offchain clients for traditional Snapshot
const offchainEthereumSig = new clients.OffchainEthereumSig();
const offchainStarknetSig = new clients.OffchainStarknetSig();

// Protocol-specific clients
const governorBravo = new clients.GovernorBravoEthereumSig(config);
const openZeppelin = new clients.OpenZeppelinEthereumSig(config);

Strategies

Strategies define how voting power is calculated. The SDK includes built-in strategies for:
  • Vanilla: Simple token balance voting
  • Comp: Compound-style checkpoint voting
  • OZVotes: OpenZeppelin Votes standard
  • Whitelist: Merkle tree-based whitelisting
  • Cross-chain: Storage proof-based voting from other chains
import { getEvmStrategy, getStarknetStrategy, getOffchainStrategy } from '@snapshot-labs/sx';

// Get strategy implementations
const evmStrategy = getEvmStrategy('vanilla');
const starknetStrategy = getStarknetStrategy('erc20Votes');
const offchainStrategy = getOffchainStrategy('remoteVp');

Executors

Executors determine how approved proposals are executed onchain:
  • SimpleQuorumAvatar: Execute through a Gnosis Safe
  • SimpleQuorumTimelock: Execute with a time delay
  • Axiom: ZK-proof based execution
  • Isokratia: Custom execution logic
  • EthRelayer: Cross-chain execution via relayer
import { getExecutionData } from '@snapshot-labs/sx';

const executionData = getExecutionData(
  'SimpleQuorumAvatar',
  executorAddress,
  { transactions: [...] }
);

Utils

Utility functions for common operations:
import { utils } from '@snapshot-labs/sx';

// Encoding utilities
const encoded = utils.encoding.executionHash(...);

// Merkle tree utilities
const tree = utils.merkle.createTree(leaves);

// Storage proof utilities
const proof = utils.storageProofs.getProof(...);

// Byte manipulation
const hex = utils.bytes.bytesToHex(buffer);

Use Cases

Creating a Governance Space

import { clients, evmSepolia } from '@snapshot-labs/sx';
import { Wallet, providers } from 'ethers';

const provider = new providers.JsonRpcProvider('https://rpc.snapshot.org/11155111');
const wallet = new Wallet(privateKey, provider);

const client = new clients.EvmEthereumTx({
  networkConfig: evmSepolia
});

const { txId, address } = await client.deploySpace({
  signer: wallet,
  params: {
    controller: wallet.address,
    votingDelay: 0,
    minVotingDuration: 300,
    maxVotingDuration: 86400,
    proposalValidationStrategy: {
      addr: evmSepolia.strategies['0xC1245C5DCa7885C73E32294140F1e5d30688c202'].type,
      params: '0x'
    },
    proposalValidationStrategyMetadataUri: '',
    daoUri: 'https://example.com',
    metadataUri: 'ipfs://...',
    authenticators: [evmSepolia.authenticators['0x5f9B7D78c9a37a439D78f801E0E339C6E711e260']],
    votingStrategies: [{
      addr: '0xC1245C5DCa7885C73E32294140F1e5d30688c202',
      params: '0x'
    }],
    votingStrategiesMetadata: ['']
  }
});

Submitting a Proposal (EVM)

import { clients, evmMainnet } from '@snapshot-labs/sx';
import { Wallet, providers } from 'ethers';

const provider = new providers.JsonRpcProvider('https://rpc.snapshot.org/1');
const wallet = new Wallet(privateKey, provider);

const client = new clients.EvmEthereumSig({
  networkConfig: evmMainnet,
  manaUrl: 'https://mana.pizza'
});

const envelope = await client.propose({
  signer: wallet,
  data: {
    space: '0x...',
    authenticator: '0x...',
    strategies: [{
      index: 0,
      address: '0x...',
      params: '0x'
    }],
    executionStrategy: {
      addr: '0x...',
      params: '0x'
    },
    metadataUri: 'ipfs://...'
  }
});

const receipt = await client.send(envelope);

Voting on a Proposal (Starknet)

import { clients, starknetSepolia } from '@snapshot-labs/sx';
import { Account, RpcProvider } from 'starknet';

const provider = new RpcProvider({
  nodeUrl: 'https://starknet-sepolia.public.blastapi.io'
});
const account = new Account(provider, address, privateKey);

const client = new clients.StarknetSig({
  networkConfig: starknetSepolia,
  manaUrl: 'https://mana.pizza'
});

const envelope = await client.vote({
  signer: account,
  data: {
    space: '0x...',
    authenticator: '0x...',
    strategies: [{
      index: 0,
      address: '0x...',
      params: []
    }],
    proposal: 1,
    choice: 1,
    metadataUri: ''
  }
});

const receipt = await client.send(envelope);

Offchain Voting

import { clients } from '@snapshot-labs/sx';
import { Wallet } from 'ethers';

const wallet = new Wallet(privateKey);

const client = new clients.OffchainEthereumSig({
  networkConfig: { eip712ChainId: 1 }
});

const envelope = await client.vote({
  signer: wallet,
  data: {
    space: 'example.eth',
    proposal: '0x...', // IPFS hash
    type: 'single-choice',
    choice: 1,
    reason: 'I support this proposal',
    app: 'my-app',
    from: wallet.address
  }
});

const receipt = await client.send(envelope);

Network Configurations

The SDK provides pre-configured network settings for all supported chains:
import {
  // EVM networks
  evmMainnet,
  evmSepolia,
  evmOptimism,
  evmPolygon,
  evmArbitrum,
  evmBase,
  evmMantle,
  evmApe,
  evmCurtis,
  // Starknet networks
  starknetMainnet,
  starknetSepolia,
  // Offchain networks
  offchainMainnet,
  offchainGoerli
} from '@snapshot-labs/sx';
Each network configuration includes:
  • Chain ID and block time
  • Deployed contract addresses (authenticators, strategies, executors)
  • Network-specific parameters (gas settings, etc.)

Next Steps

Build docs developers (and LLMs) love