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:
Signature-based (Gasless)
Transaction-based
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:
Starknet Signature
Starknet Transaction
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:
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:
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'
};
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
});
Submit proposal
Send the proposal to the network: Signature-based
Transaction-based
// 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:
EVM Signature Client
EVM Transaction Client
Starknet
Offchain
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:
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:
EVM Networks
Starknet Networks
Offchain Networks
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.