Skip to main content
This guide will help you get up and running with the Snapshot X SDK (@snapshot-labs/sx) in minutes. You’ll learn how to install the package, create clients for different networks, and perform common governance operations.

Installation

Install the SDK using your preferred package manager:
npm install @snapshot-labs/sx
The SDK requires Node.js version 16 or higher and includes TypeScript definitions out of the box.

Core Dependencies

The SDK has peer dependencies for blockchain interactions:

Creating Clients

Snapshot X provides different clients for each network type. Choose the client that matches your governance setup.

EVM Client (Ethereum, Sepolia)

For Snapshot X spaces on Ethereum and EVM-compatible chains:
import { clients } from '@snapshot-labs/sx';
import { JsonRpcProvider } from '@ethersproject/providers';
import { Wallet } from '@ethersproject/wallet';
import { evmSepolia } from '@snapshot-labs/sx';

// Initialize provider and signer
const provider = new JsonRpcProvider('https://rpc.snapshot.org/11155111');
const signer = new Wallet('YOUR_PRIVATE_KEY', provider);

// Create signature-based client (for gasless voting via Mana)
const client = new clients.EvmEthereumSig({
  networkConfig: evmSepolia,
  manaUrl: 'https://mana.box',
  provider
});

Starknet Client

For Snapshot X spaces on Starknet:
import { clients } from '@snapshot-labs/sx';
import { Account, RpcProvider } from 'starknet';
import { starknetSepolia } from '@snapshot-labs/sx';

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

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

Offchain Client (Traditional Snapshot)

For offchain Snapshot spaces:
Offchain
import { clients } from '@snapshot-labs/sx';
import { Wallet } from '@ethersproject/wallet';
import { offchainMainnet } from '@snapshot-labs/sx';

const signer = new Wallet('YOUR_PRIVATE_KEY');

// Create offchain client for traditional Snapshot spaces
const client = new clients.OffchainEthereumSig({
  networkConfig: offchainMainnet
});

Creating a Proposal

Once you have a client, creating proposals is straightforward:
1

Prepare proposal data

Define your proposal parameters including space, metadata, and execution strategy.
const proposalData = {
  space: '0x1234...', // Your space contract address
  authenticator: '0x5678...', // Authenticator contract address
  strategies: [
    {
      index: 0,
      address: '0xabcd...', // Voting strategy address
      params: '0x' // Strategy-specific parameters
    }
  ],
  executionStrategy: {
    addr: '0xef01...', // Execution strategy address
    params: '0x' // Execution parameters
  },
  metadataUri: 'ipfs://QmNrm6xKuib1THtWkiN5CKtBEerQCDpUtmgDqiaU2xDmca'
};
2

Create envelope (signature clients only)

For signature-based clients, create a signed envelope:
// For EvmEthereumSig or StarknetSig clients
const envelope = await client.propose({
  signer, // or account for Starknet
  data: proposalData
});
3

Submit proposal

Send the proposal to the network:
// Signature clients send to Mana relayer
const receipt = await client.send(envelope);
console.log('Proposal created:', receipt);
The metadataUri should point to JSON containing your proposal title, body, choices, and other metadata. Many projects use IPFS for decentralized storage.

Voting on Proposals

Voting follows a similar pattern to proposal creation:
import { clients } from '@snapshot-labs/sx';

// Create vote envelope
const envelope = await client.vote({
  signer,
  data: {
    space: '0x1234...',
    authenticator: '0x5678...',
    strategies: [
      {
        index: 0,
        address: '0xabcd...',
        params: '0x'
      }
    ],
    proposal: 1, // Proposal ID
    choice: 1, // 1 = For, 2 = Against, 3 = Abstain (depends on proposal type)
    metadataUri: '' // Optional vote reason
  }
});

// Submit vote
const receipt = await client.send(envelope);
console.log('Vote cast:', receipt);

Complete Example

Here’s a complete example showing the full workflow:
Full Example
import { clients, evmSepolia } from '@snapshot-labs/sx';
import { JsonRpcProvider } from '@ethersproject/providers';
import { Wallet } from '@ethersproject/wallet';

async function governanceWorkflow() {
  // Setup
  const provider = new JsonRpcProvider('https://rpc.snapshot.org/11155111');
  const signer = new Wallet(process.env.PRIVATE_KEY, provider);
  
  const client = new clients.EvmEthereumSig({
    networkConfig: evmSepolia,
    manaUrl: 'https://mana.box',
    provider
  });

  // Create a proposal
  console.log('Creating proposal...');
  const proposalEnvelope = await client.propose({
    signer,
    data: {
      space: '0x1234567890123456789012345678901234567890',
      authenticator: '0x5f9B7D78c9a37a439D78f801E0E339C6E711e260',
      strategies: [{
        index: 0,
        address: '0xC1245C5DCa7885C73E32294140F1e5d30688c202',
        params: '0x'
      }],
      executionStrategy: {
        addr: '0xecE4f6b01a2d7FF5A9765cA44162D453fC455e42',
        params: '0x'
      },
      metadataUri: 'ipfs://QmNrm6xKuib1THtWkiN5CKtBEerQCDpUtmgDqiaU2xDmca'
    }
  });
  
  const proposalReceipt = await client.send(proposalEnvelope);
  console.log('Proposal created with ID:', proposalReceipt.proposalId);

  // Wait for proposal to become active (based on voting delay)
  // In production, you'd query the API to check proposal status
  
  // Cast a vote
  console.log('Casting vote...');
  const voteEnvelope = await client.vote({
    signer,
    data: {
      space: '0x1234567890123456789012345678901234567890',
      authenticator: '0x5f9B7D78c9a37a439D78f801E0E339C6E711e260',
      strategies: [{
        index: 0,
        address: '0xC1245C5DCa7885C73E32294140F1e5d30688c202',
        params: '0x'
      }],
      proposal: proposalReceipt.proposalId,
      choice: 1, // Vote "For"
      metadataUri: ''
    }
  });
  
  const voteReceipt = await client.send(voteEnvelope);
  console.log('Vote cast:', voteReceipt);
}

governanceWorkflow().catch(console.error);

Network Configurations

The SDK includes pre-configured network settings:
import { 
  evmMainnet,
  evmSepolia,
  evmArbitrumOne,
  evmArbitrumSepolia,
  evmBaseMainnet,
  evmBaseSepolia,
  evmOptimismMainnet,
  evmOptimismSepolia
} from '@snapshot-labs/sx';
Each network configuration includes:
  • Contract addresses (authenticators, strategies, execution strategies)
  • Chain IDs and network parameters
  • Block time and fee settings

Next Steps

Architecture Deep Dive

Learn how the components work together

SDK Overview

Explore the complete SDK documentation

Strategies Guide

Learn about voting power strategies

Execution Strategies

Implement onchain proposal execution
Never commit private keys to version control. Use environment variables or secure key management solutions in production.

Build docs developers (and LLMs) love