---
title: "Getting started"
url: "/docs/build-on-signet/getting-started/index.md"
description: "Install dependencies and configure clients for Signet development."
---
New to Signet? Start with [Learn about Signet](/docs/learn-about-signet/) for background on how the system works.

Select your language to see the relevant setup instructions. Get testnet tokens from the [Parmigiana quickstart](/docs/build-on-signet/parmigiana/index.md).

## TypeScript

These docs use [Viem](https://viem.sh) as the Ethereum interface. Any library that can send transactions and read contract state will work (ethers.js, web3.js, etc.), but the SDK is built on Viem and the examples use it throughout. You should be comfortable with Ethereum basics: wallets, transactions, ABIs, and ERC-20 tokens.
All examples target the [Parmigiana testnet](/docs/build-on-signet/parmigiana/index.md) . To follow along, grab testnet ETH and USD from the [faucet](/docs/build-on-signet/parmigiana/index.md) .
> **Adapting for mainnet:** Replace `PARMIGIANA` with `MAINNET`, `parmigianaRollup` with `signetRollup`, and `parmigianaHost` with Viem's built-in `mainnet` chain from `viem/chains`. Everything else stays the same. ## Install the SDK ```bash npm install @signet-sh/sdk viem ``` ## Create clients Viem uses separate clients for reads and writes. Signet spans two chains, so you need a pair for each:
Client Chain Purpose signetPublicClient Signet Read balances, events, contract state signetWalletClient Signet Create orders, approve tokens hostPublicClient Ethereum Read fill events, check balances hostWalletClient Ethereum Enter Signet via Passage, fill orders The SDK provides pre-configured Viem chain definitions for both:
```typescript import { createPublicClient, createWalletClient, http } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; import { parmigianaRollup, parmigianaHost } from '@signet-sh/sdk/constants'; // Signet (rollup) clients const signetPublicClient = createPublicClient({ chain: parmigianaRollup, transport: http(), }); const signetWalletClient = createWalletClient({ account: privateKeyToAccount('0x...'), chain: parmigianaRollup, transport: http(), }); // Ethereum (host) clients const hostPublicClient = createPublicClient({ chain: parmigianaHost, transport: http(), }); const hostWalletClient = createWalletClient({ account: privateKeyToAccount('0x...'), chain: parmigianaHost, transport: http(), }); ``` When you see hostWalletClient.writeContract(...) in later pages, that's a transaction on Ethereum. signetWalletClient.writeContract(...) is on Signet.
**Without the SDK** Define the chains manually with Viem's `defineChain`: ```typescript import { createPublicClient, createWalletClient, defineChain, http } from 'viem'; import { privateKeyToAccount } from 'viem/accounts'; const signetParmigiana = defineChain({ id: 88888, name: 'Parmigiana Testnet', nativeCurrency: { name: 'USD', symbol: 'USD', decimals: 18 }, rpcUrls: { default: { http: ['https://rpc.parmigiana.signet.sh'] }, }, blockExplorers: { default: { name: 'Signet Explorer', url: 'https://explorer.parmigiana.signet.sh', }, }, }); const signetHost = defineChain({ id: 3151908, name: 'Parmigiana Host', nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 }, rpcUrls: { default: { http: ['https://host-rpc.parmigiana.signet.sh'] }, }, blockExplorers: { default: { name: 'Host Explorer', url: 'https://explorer-host.parmigiana.signet.sh', }, }, }); const signetPublicClient = createPublicClient({ chain: signetParmigiana, transport: http() }); const signetWalletClient = createWalletClient({ account: privateKeyToAccount('0x...'), chain: signetParmigiana, transport: http(), }); const hostPublicClient = createPublicClient({ chain: signetHost, transport: http() }); const hostWalletClient = createWalletClient({ account: privateKeyToAccount('0x...'), chain: signetHost, transport: http(), }); ``` ## Reading balances Use the SDK's token helpers to resolve addresses:
```typescript import { PARMIGIANA } from '@signet-sh/sdk/constants'; import { getTokenAddress } from '@signet-sh/sdk/tokens'; import { erc20Abi } from 'viem'; const weth = getTokenAddress('WETH', PARMIGIANA.rollupChainId, PARMIGIANA); const balance = await signetPublicClient.readContract({ address: weth, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress], }); ``` **Without the SDK** ```typescript import { erc20Abi } from 'viem'; const wethAddress = '0x...'; // WETH contract on Signet const balance = await signetPublicClient.readContract({ address: wethAddress, abi: erc20Abi, functionName: 'balanceOf', args: [userAddress], }); ``` > **USD and WUSD:** Signet's native token is USD. The SDK calls the wrapped ERC-20 version WUSD. Use `getTokenAddress('WUSD', ...)` when you need the ERC-20 contract address rather than the native token. ## Working with tokens ### List available tokens Query which tokens exist on each chain:
```typescript import { PARMIGIANA } from '@signet-sh/sdk/constants'; import { getAvailableTokens } from '@signet-sh/sdk/tokens'; const rollupTokens = getAvailableTokens(PARMIGIANA.rollupChainId, PARMIGIANA); // ['ETH', 'WETH', 'WBTC', 'USDC', 'USDT', 'WUSD', 'USD'] const hostTokens = getAvailableTokens(PARMIGIANA.hostChainId, PARMIGIANA); // ['ETH', 'WETH', 'WBTC', 'USDC', 'USDT'] ``` ### Resolve tokens across chains mapTokenCrossChain returns the equivalent symbol, or undefined if no cross-chain counterpart exists:
```typescript import { mapTokenCrossChain } from '@signet-sh/sdk/tokens'; mapTokenCrossChain('WETH'); // 'WETH' mapTokenCrossChain('USDC'); // 'USDC' mapTokenCrossChain('WUSD'); // undefined (no host equivalent) ``` resolveTokenSymbol turns a contract address back into a symbol:
```typescript import { resolveTokenSymbol } from '@signet-sh/sdk/tokens'; import { PARMIGIANA } from '@signet-sh/sdk/constants'; const symbol = resolveTokenSymbol(tokenAddress, PARMIGIANA.rollupChainId, PARMIGIANA); // 'WETH', 'USDC', etc. ``` ### Check if ETH needs wrapping needsWethWrap returns true when a flow requires WETH rather than native ETH:
```typescript import { needsWethWrap } from '@signet-sh/sdk/tokens'; needsWethWrap('ETH', 'hostToRollup', 'passage'); // false (Passage accepts native ETH) needsWethWrap('ETH', 'hostToRollup', 'orders'); // true (orders need WETH) needsWethWrap('USDC', 'hostToRollup', 'orders'); // false (already ERC-20) ``` wrapEth and unwrapEth handle the conversion:
```typescript import { PARMIGIANA } from '@signet-sh/sdk/constants'; import { getTokenAddress } from '@signet-sh/sdk/tokens'; import { wethAbi } from '@signet-sh/sdk/abi'; import { parseEther } from 'viem'; // Wrap ETH to WETH const weth = getTokenAddress('WETH', PARMIGIANA.rollupChainId, PARMIGIANA); await signetWalletClient.writeContract({ address: weth, abi: wethAbi, functionName: 'deposit', value: parseEther('1'), }); ``` 

## Rust

The Signet Rust SDK is a collection of crates built on [alloy](https://docs.rs/alloy) . Install the core crates:
```bash cargo add signet-constants signet-types ``` Additional crates for specific features:
Crate Purpose signet-constants Chain configs, contract addresses, token addresses signet-types Order and fill types, EIP-712 signing signet-tx-cache Submit transactions, orders, and bundles to the tx-cache signet-orders OrderSender for long-running services signet-zenith Zenith contract bindings signet-bundle Bundle construction (SignetEthBundle) ## Create providers Signet spans two chains, so you need a provider for each:
```rust use alloy::providers::{Provider, ProviderBuilder}; // Signet (rollup) provider let signet_provider = ProviderBuilder::new() .on_http("https://rpc.parmigiana.signet.sh".parse()?); // Ethereum (host) provider let host_provider = ProviderBuilder::new() .on_http("https://host-rpc.parmigiana.signet.sh".parse()?); ``` For signing transactions, add a wallet:
```rust use alloy::{ network::EthereumWallet, providers::ProviderBuilder, signers::local::PrivateKeySigner, }; let signer: PrivateKeySigner = "0x...".parse()?; let wallet = EthereumWallet::from(signer); let signet_provider = ProviderBuilder::new() .wallet(wallet) .on_http("https://rpc.parmigiana.signet.sh".parse()?); ``` ## Contract addresses and chain config The signet-constants crate provides all addresses and chain IDs for each network:
```rust use signet_constants::parmigiana; // Chain IDs let rollup_chain_id = parmigiana::ROLLUP_CHAIN_ID; // 88888 let host_chain_id = parmigiana::HOST_CHAIN_ID; // 3151908 // Token addresses let ru_weth = parmigiana::RU_WETH; let host_weth = parmigiana::HOST_WETH; // System constants (for order signing) let constants = parmigiana::system_constants(); ``` 

## Solidity

Signet contracts are part of the [Zenith](https://github.com/init4tech/zenith) repository. Install with Foundry:
```bash forge install https://github.com/init4tech/zenith forge install https://github.com/init4tech/signet-sol ``` ## Contract addresses and ABIs All contract addresses, ABIs, and RPC endpoints are on the [Parmigiana quickstart](/docs/build-on-signet/parmigiana/index.md) page.
In Solidity, use the SignetL2 base contract from [signet-sol](https://github.com/init4tech/signet-sol) for automatic chain-aware address resolution:
```solidity import {SignetL2} from "./Signet.sol"; contract YourContract is SignetL2 { function doSomething() external { // Automatically has access to: // - rollupOrders: RollupOrders contract address // - permit2: Permit2 contract address } } ``` Source: [Signet.sol](https://github.com/init4tech/signet-sol/blob/main/src/l2/Signet.sol) 

## Terminal

These examples use [Foundry's cast](https://book.getfoundry.sh/reference/cast/) and curl. No SDK required.
## RPC endpoints Set up environment variables for both chains:
```bash export SIGNET_RPC=https://rpc.parmigiana.signet.sh export HOST_RPC=https://host-rpc.parmigiana.signet.sh export TX_CACHE=https://transactions.parmigiana.signet.sh export PRIVATE_KEY= export YOUR_ADDRESS= ``` Chain RPC URL Signet (Parmigiana) https://rpc.parmigiana.signet.sh Ethereum (Host) https://host-rpc.parmigiana.signet.sh ## Check RPC health ```bash curl -s -X POST $SIGNET_RPC \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' ``` ## Check balances ```bash # Native balance on Signet cast balance 0xYourAddress --rpc-url $SIGNET_RPC # Native balance on Ethereum host cast balance 0xYourAddress --rpc-url $HOST_RPC ``` ## Read contracts ```bash # Read a contract on Signet cast call 0xContractAddress "balanceOf(address)(uint256)" 0xYourAddress \ --rpc-url $SIGNET_RPC # Read a contract on Ethereum host cast call 0xContractAddress "functionName()" --rpc-url $HOST_RPC ``` ## Contract addresses and ABIs All contract addresses and ABI downloads are on the [Parmigiana quickstart](/docs/build-on-signet/parmigiana/index.md) page.

