The UI is the official interface for Snapshot X.
https://github.com/snapshot-labs/sx-monorepo/tree/master/apps/ui
To enhance the user experience of interacting with the protocol, we offer a number of additional off-chain services. All of these products are fully open source in the Snapshot Labs Github organization. These are all completely optional and therefore do not introduce any censorship concerns.
SX UI: An easy to use interface for interacting with the protocol.
SX API: A fast and efficient indexer for all the protocol data.
SX.js: A Typescript SDK that can be used to build 3rd Party Integrations with the protocol.
: A meta-transaction relayer that can provide a way for proposal creation and vote costs to be sponsored.
SX.js is the official Typescript SDK to interact with Snapshot X. The SDK includes a client for Mana, the meta transaction relayer.
https://github.com/snapshot-labs/sx-monorepo/tree/master/packages/sx.js
Install the latest version of the beta release:
Everything happens thanks to the clients objects. Depending on the specific Space or Proposal setup, you may need to use a Transaction or Signature Client. This quick guide demonstrates how to easily set all of them up, both for Ethereum and StarkNet:
To learn more about StarkNet's Provider object, have a look .
Address' voting power depends on the strategy used. Below you can see an example of getting voting power for whitelist Voting strategy on Starknet.
npm install @snapshot-labs/sx@betayarn add @snapshot-labs/sx@betabun add @snapshot-labs/sx@betaimport { clients, evmSepolia } from '@snapshot-labs/sx';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumTx(clientConfig);
const ethSigClient = new clients.EthereumSig(clientConfig);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetTx(clientConfig);
const starkSigClient = new clients.StarkNetSig(clientConfig);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumTx(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
proposal: 7,
choice: 1,
metadataUri: ''
};
const receipt = await client.vote({
signer: web3.getSigner(),
envelope: {
data
}
});
console.log('Receipt', receipt);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const ethSigClient = new clients.EthereumSig(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
proposal: 7,
choice: 1,
metadataUri: ''
};
const receipt = await ethSigClient.vote({
signer: web3.getSigner(),
data
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetTx(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
proposal: 7,
choice: 1,
metadataUri: ''
};
const receipt = await client.vote(web3.provider.account, {
data
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetSig(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
proposal: 7,
choice: 1,
metadataUri: ''
};
const envelope = await client.vote({
signer: web3.provider.account,
data
});
const receipt = await client.send(envelope);
console.log('Receipt', receipt);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumTx(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await client.propose({
signer: web3.getSigner(),
envelope: {
data
}
});
console.log('Receipt', receipt);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumSig(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await ethSigClient.propose({
signer: web3.getSigner(),
data
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetTx(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await client.propose(web3.provider.account, {
data
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetSig(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
strategies: [
{
address: '0xc1245c5dca7885c73e32294140f1e5d30688c202',
index: 0
}
],
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const envelope = await client.propose({
signer: web3.provider.account,
data
});
const receipt = await client.send(envelope);
console.log('Receipt', receipt);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumTx(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
proposal: 1, // proposalId
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await client.updateProposal({
signer: web3.getSigner(),
envelope: {
data
}
});
console.log('Receipt', receipt);import { clients, evmSepolia } from '@snapshot-labs/sx';
import type { Web3Provider } from '@ethersproject/providers';
const clientConfig = { networkConfig: evmSepolia }
const client = new clients.EthereumSig(clientConfig);
const web3 = new Web3Provider(window.ethereum);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
proposal: 1, // proposalId
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await ethSigClient.updateProposal({
signer: web3.getSigner(),
envelope: {
data
}
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetTx(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
proposal: 1, // proposalId
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const receipt = await client.updateProposal(web3.provider.account, {
data
});
console.log('Receipt', receipt);import { clients } from '@snapshot-labs/sx';
import { Provider, constants } from 'starknet';
const web3 = window.starknet.provider;
const ethUrl = 'https://rpc.snapshot.org/1';
const manaUrl = 'https://mana.pizza';
const starkProvider = new Provider({ sequencer: { network: constants.NetworkName.SN_GOERLI } });
const clientConfig = {
starkProvider,
manaUrl,
ethUrl
};
const client = new clients.StarkNetSig(clientConfig);
const data = {
space: '0x012b261effbf548f2b9a495d50b81a8a7c1dd941',
proposal: 1, // proposalId
authenticator: '0xba06e6ccb877c332181a6867c05c8b746a21aed1',
executionStrategy: {
addr: '0x0000000000000000000000000000000000000000',
params: '0x'
},
metadataUri: ''
};
const envelope = await client.updateProposal({
signer: web3.provider.account,
data
});
const receipt = await client.send(envelope);
console.log('Receipt', receipt);import {
starknetGoerli1,
getStarknetStrategy,
} from '@snapshot-labs/sx';
const clientConfig = {
starkProvider,
ethUrl,
networkConfig: starknetGoerli1
};
const address = '0xe3ca14dcb7862116bbbe4331a9927c6693b141aa8936bb76e2bdfa4b551a52';
const voterAddress = '0x556B14CbdA79A36dC33FcD461a04A5BCb5dC2A70';
const strategyMetadata = {
"tree": [
{
"type": 1,
"address": "0x556B14CbdA79A36dC33FcD461a04A5BCb5dC2A70",
"votingPower": "10"
}
]
}
const timestamp = 1703090187
const strategyParams = [
"0xe3ca14dcb7862116bbbe4331a9927c6693b141aa8936bb76e2bdfa4b551a52"
]
const strategy = getStarknetStrategy(address, clientConfig.networkConfig);
const vp = await strategy.getVotingPower(
address,
voterAddress,
strategyMetadata,
timestamp,
strategyParams,
clientConfig
);Mana is a meta-transaction relayer that allows users to interact with Snapshot X without paying gas fee. This service works in conjunction with signature based Snapshot X . Users sign a meta transaction in the SX UI and then the relayer submits each encoded transaction along with its signature to the signature authenticator. If the signature is valid, then the transaction will be forwarded to the relevant space contract.
The system included a mechanism that allows DAOs to fund the transactions sent by the relayer, enabling the free end user experience. However importantly, users can directly interact with Snapshot X and therefore do not rely on trusting the relayer to not censor votes. Additionally, Anyone can run a relayer if they want to take over the sponsoring of transactions.
Note that currently Mana only supports proposal creation, proposal updates, and vote casting transactions. It does not currently support proposal execution or space controller actions.
Mainnets: https://api.snapshot.box Testnets: https://testnet-api.snapshot.box