|
| 1 | +--- |
| 2 | +name: signet-ts-sdk |
| 3 | +description: TypeScript SDK for Signet blockchain operations — order creation/signing, bundle building, event parsing, passage bridging, and chain configuration |
| 4 | +--- |
| 5 | + |
| 6 | +# @signet-sh/sdk |
| 7 | + |
| 8 | +TypeScript SDK for creating, signing, and submitting Signet orders. Compatible with the Rust `signet-types` crate for cross-implementation interoperability. |
| 9 | + |
| 10 | +## Core Capabilities |
| 11 | + |
| 12 | +### Order Creation & Signing |
| 13 | + |
| 14 | +Build and sign EIP-712 orders using the `UnsignedOrder` builder. Orders use Permit2 for gasless token approvals. |
| 15 | + |
| 16 | +```typescript |
| 17 | +import { UnsignedOrder, orderHash, MAINNET } from "@signet-sh/sdk"; |
| 18 | + |
| 19 | +const signedOrder = await UnsignedOrder.new() |
| 20 | + .withInput(tokenAddress, amount) |
| 21 | + .withOutput(outputToken, outputAmount, recipient, chainId) |
| 22 | + .withDeadline(deadline) |
| 23 | + .withChain({ |
| 24 | + chainId: MAINNET.rollupChainId, |
| 25 | + orderContract: MAINNET.rollupOrders, |
| 26 | + }) |
| 27 | + .sign(walletClient); |
| 28 | + |
| 29 | +const hash = orderHash(signedOrder); |
| 30 | +``` |
| 31 | + |
| 32 | +### Bundle Building |
| 33 | + |
| 34 | +Construct atomic transaction bundles for block builders. Bundles support rollup transactions, host chain transactions, and timing constraints. |
| 35 | + |
| 36 | +```typescript |
| 37 | +import { SignetEthBundleBuilder, createTxCacheClient } from "@signet-sh/sdk"; |
| 38 | + |
| 39 | +const bundle = SignetEthBundleBuilder.new() |
| 40 | + .withTx(signedTx) |
| 41 | + .withBlockNumber(12345678n) |
| 42 | + .build(); |
| 43 | + |
| 44 | +const txCache = createTxCacheClient("https://tx.signet.sh"); |
| 45 | +await txCache.submitBundle(bundle); |
| 46 | +``` |
| 47 | + |
| 48 | +Simulate bundles before submission: |
| 49 | + |
| 50 | +```typescript |
| 51 | +import { SignetCallBundleBuilder, serializeCallBundle } from "@signet-sh/sdk"; |
| 52 | + |
| 53 | +const callBundle = SignetCallBundleBuilder.new() |
| 54 | + .withTx(signedTx) |
| 55 | + .withBlockNumber(12345679n) |
| 56 | + .withStateBlockNumber("latest") |
| 57 | + .build(); |
| 58 | + |
| 59 | +const serialized = serializeCallBundle(callBundle); |
| 60 | +``` |
| 61 | + |
| 62 | +### Event Parsing |
| 63 | + |
| 64 | +Parse RollupOrders contract events with full type safety using viem's `parseEventLogs` and the SDK's typed event interfaces (v0.4.0+). |
| 65 | + |
| 66 | +```typescript |
| 67 | +import { parseEventLogs } from "viem"; |
| 68 | +import { |
| 69 | + rollupOrdersAbi, |
| 70 | + type OrderEvent, |
| 71 | + type FilledEvent, |
| 72 | + type SweepEvent, |
| 73 | +} from "@signet-sh/sdk"; |
| 74 | + |
| 75 | +const events = parseEventLogs({ abi: rollupOrdersAbi, logs }); |
| 76 | + |
| 77 | +for (const event of events) { |
| 78 | + switch (event.eventName) { |
| 79 | + case "Order": { |
| 80 | + const { deadline, inputs, outputs } = event.args as OrderEvent; |
| 81 | + break; |
| 82 | + } |
| 83 | + case "Filled": { |
| 84 | + const { outputs } = event.args as FilledEvent; |
| 85 | + break; |
| 86 | + } |
| 87 | + case "Sweep": { |
| 88 | + const { recipient, token, amount } = event.args as SweepEvent; |
| 89 | + break; |
| 90 | + } |
| 91 | + } |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +### Passage Bridging |
| 96 | + |
| 97 | +Bridge native ETH and ERC20 tokens between host chain and Signet rollup using the Passage contract. |
| 98 | + |
| 99 | +```typescript |
| 100 | +import { passageAbi, MAINNET } from "@signet-sh/sdk"; |
| 101 | + |
| 102 | +// Bridge native ETH |
| 103 | +await walletClient.writeContract({ |
| 104 | + address: MAINNET.hostPassage, |
| 105 | + abi: passageAbi, |
| 106 | + functionName: "enter", |
| 107 | + args: [recipientAddress], |
| 108 | + value: 1000000000000000000n, |
| 109 | +}); |
| 110 | + |
| 111 | +// Bridge ERC20 tokens |
| 112 | +await walletClient.writeContract({ |
| 113 | + address: MAINNET.hostPassage, |
| 114 | + abi: passageAbi, |
| 115 | + functionName: "enterToken", |
| 116 | + args: [MAINNET.rollupChainId, recipientAddress, tokenAddress, amount], |
| 117 | +}); |
| 118 | +``` |
| 119 | + |
| 120 | +## Exports |
| 121 | + |
| 122 | +### Types |
| 123 | + |
| 124 | +- `SignedOrder` — A signed order ready for submission |
| 125 | +- `SignedFill` — A signed fill for filling orders |
| 126 | +- `SignetEthBundle` — Bundle for `signet_sendBundle` |
| 127 | +- `SignetCallBundle` — Bundle for `signet_callBundle` (simulation) |
| 128 | +- `SignetCallBundleResponse` — Response from `signet_callBundle` |
| 129 | +- `Permit2Batch` — Permit2 batch transfer data |
| 130 | +- `PermitBatchTransferFrom` — Permit2 batch transfer from structure |
| 131 | +- `Output` — Order output specification (token, amount, recipient, chainId) |
| 132 | +- `Input` — Order input specification (token, amount) |
| 133 | +- `TokenPermissions` — Token permission for Permit2 |
| 134 | +- `ChainConfig` — Chain configuration for order signing |
| 135 | +- `UnsignedOrderParams` — Parameters for building unsigned orders |
| 136 | +- `SerializedSignedOrder` — JSON-serializable signed order |
| 137 | +- `SerializedSignetEthBundle` — JSON-serializable eth bundle |
| 138 | +- `SerializedSignetCallBundle` — JSON-serializable call bundle |
| 139 | +- `SerializedSignetCallBundleResponse` — JSON-serializable call bundle response |
| 140 | +- `CallBundleTransactionResult` — Result of a simulated bundle transaction |
| 141 | +- `SerializedCallBundleTransactionResult` — JSON-serializable transaction result |
| 142 | +- `AggregateFills` — Aggregate fill data |
| 143 | +- `AggregateOrders` — Aggregate order data |
| 144 | +- `BlockNumberOrTag` — Block number or tag (`"latest"`, `"pending"`, etc.) |
| 145 | +- `SignetSystemConstants` — Chain configuration interface |
| 146 | +- `Eip712SigningParams` — EIP-712 signing parameters |
| 147 | +- `FeasibilityResult` — Result of order feasibility check |
| 148 | +- `FeasibilityIssue` — Individual feasibility issue |
| 149 | +- `FeasibilityIssueType` — Type of feasibility issue |
| 150 | +- `Flow` — Entry mechanism: `"passage"` or `"orders"` |
| 151 | +- `TokenSymbol` — Supported token symbols |
| 152 | +- `TokenMeta` — Token metadata (symbol, decimals, addresses) |
| 153 | +- `TxCacheClient` — Tx-cache client interface |
| 154 | +- `Address`, `Hex`, `B256`, `Bytes` — Ethereum primitive types (re-exported from viem) |
| 155 | + |
| 156 | +### Event Types (v0.4.0+) |
| 157 | + |
| 158 | +Typed interfaces for parsing RollupOrders contract events with `parseEventLogs`: |
| 159 | + |
| 160 | +- `OrderEvent` — Parsed args from an `Order` event: `{ deadline, inputs, outputs }` |
| 161 | +- `FilledEvent` — Parsed args from a `Filled` event: `{ outputs }` |
| 162 | +- `SweepEvent` — Parsed args from a `Sweep` event: `{ recipient, token, amount }` |
| 163 | + |
| 164 | +### Functions |
| 165 | + |
| 166 | +**Order hashing & signing:** |
| 167 | + |
| 168 | +- `orderHash(order)` — Compute the order hash |
| 169 | +- `orderHashPreImage(order)` — Get the pre-image used for hashing |
| 170 | +- `computeOrderHash(order)` — Compute order hash (alternate) |
| 171 | +- `normalizeSignature(sig)` — Normalize ECDSA signature S-value |
| 172 | +- `eip712Components(order)` — Get EIP-712 domain and types |
| 173 | +- `eip712SigningHash(order)` — Compute EIP-712 signing hash |
| 174 | +- `permit2Domain(chainId)` — Get Permit2 EIP-712 domain |
| 175 | +- `permit2DomainSeparator(chainId)` — Compute Permit2 domain separator |
| 176 | +- `permitBatchWitnessStructHash(data)` — Compute batch witness struct hash |
| 177 | +- `randomNonce()` — Generate a random Permit2 nonce |
| 178 | +- `nonceFromSeed(seed)` — Derive a nonce from a seed |
| 179 | + |
| 180 | +**Validation:** |
| 181 | + |
| 182 | +- `validateOrder(order)` — Validate an order's structure |
| 183 | +- `validateFill(fill)` — Validate a fill's structure |
| 184 | +- `checkOrderFeasibility(order, params)` — Check if an order is feasible on-chain |
| 185 | +- `hasPermit2Approval(client, params)` — Check Permit2 approval status |
| 186 | +- `isNonceUsed(client, params)` — Check if a Permit2 nonce is used |
| 187 | + |
| 188 | +**Encoding:** |
| 189 | + |
| 190 | +- `encodeInitiatePermit2(order)` — Encode order for Permit2 initiation |
| 191 | +- `encodeFillPermit2(fill)` — Encode fill for Permit2 execution |
| 192 | + |
| 193 | +**Serialization:** |
| 194 | + |
| 195 | +- `serializeOrder(order)` — Serialize a signed order for JSON |
| 196 | +- `deserializeOrder(data)` — Deserialize a signed order from JSON |
| 197 | +- `serializeEthBundle(bundle)` — Serialize eth bundle for JSON-RPC |
| 198 | +- `deserializeEthBundle(data)` — Deserialize eth bundle from JSON |
| 199 | +- `serializeCallBundle(bundle)` — Serialize call bundle for JSON-RPC |
| 200 | +- `deserializeCallBundle(data)` — Deserialize call bundle from JSON |
| 201 | +- `deserializeCallBundleResponse(data)` — Deserialize call bundle response |
| 202 | +- `deserializeTransactionResult(data)` — Deserialize transaction result |
| 203 | + |
| 204 | +**Permit2:** |
| 205 | + |
| 206 | +- `ensurePermit2Approval(walletClient, publicClient, params)` — Smart Permit2 approval with USDT handling |
| 207 | + |
| 208 | +**Tokens:** |
| 209 | + |
| 210 | +- `getTokenAddress(symbol, chainId, config)` — Get token contract address |
| 211 | +- `getTokenDecimals(symbol, config?)` — Get token decimals with chain-specific overrides |
| 212 | +- `resolveTokenSymbol(address, chainId, config)` — Resolve address to token symbol |
| 213 | +- `getAvailableTokens(chainId, config)` — Get available tokens for a chain |
| 214 | +- `mapTokenCrossChain(symbol, fromChainId, toChainId, config)` — Map token across chains |
| 215 | +- `needsWethWrap(symbol, direction, flow)` — Check if ETH needs wrapping for operation |
| 216 | + |
| 217 | +**Client:** |
| 218 | + |
| 219 | +- `createTxCacheClient(baseUrl)` — Create a tx-cache client for submitting orders and bundles |
| 220 | + |
| 221 | +**Constants helpers:** |
| 222 | + |
| 223 | +- `getOrdersContract(constants, chainId)` — Get the orders contract for a chain |
| 224 | + |
| 225 | +### Classes |
| 226 | + |
| 227 | +- `UnsignedOrder` — Builder for creating and signing orders. Methods: `new()`, `withInput()`, `withOutput()`, `withDeadline()`, `withChain()`, `sign()` |
| 228 | +- `UnsignedFill` — Builder for creating and signing fills |
| 229 | +- `SignetEthBundleBuilder` — Builder for eth bundles. Methods: `new()`, `withTx()`, `withTxs()`, `withHostTx()`, `withBlockNumber()`, `withMinTimestamp()`, `withMaxTimestamp()`, `build()` |
| 230 | +- `SignetCallBundleBuilder` — Builder for call bundles (simulation). Methods: `new()`, `withTx()`, `withBlockNumber()`, `withStateBlockNumber()`, `build()` |
| 231 | + |
| 232 | +### Constants |
| 233 | + |
| 234 | +- `PERMIT2_ADDRESS` — Canonical Permit2 contract address |
| 235 | +- `PERMIT2_NAME` — Permit2 EIP-712 domain name |
| 236 | +- `MAINNET` — Mainnet chain configuration (host chain 1, rollup chain 519) |
| 237 | +- `PARMIGIANA` — Parmigiana testnet configuration (host chain 3151908, rollup chain 88888) |
| 238 | +- `OUTPUT_WITNESS_TYPE_STRING` — EIP-712 output witness type string |
| 239 | +- `PERMIT_BATCH_WITNESS_TRANSFER_FROM_TYPES` — Permit2 batch witness transfer types |
| 240 | +- `TOKENS` — Token registry with addresses and metadata |
| 241 | +- `signetRollup` — Viem chain definition for Signet rollup |
| 242 | +- `parmigianaRollup` — Viem chain definition for Parmigiana rollup |
| 243 | +- `parmigianaHost` — Viem chain definition for Parmigiana host |
| 244 | + |
| 245 | +### ABIs |
| 246 | + |
| 247 | +- `rollupOrdersAbi` — Rollup orders contract ABI (Order, Filled, Sweep events) |
| 248 | +- `hostOrdersAbi` — Host orders contract ABI |
| 249 | +- `passageAbi` — Passage bridge contract ABI (Enter, EnterToken events) |
| 250 | +- `rollupPassageAbi` — Rollup passage contract ABI |
| 251 | +- `permit2Abi` — Permit2 contract ABI |
| 252 | +- `wethAbi` — WETH contract ABI (deposit, withdraw) |
| 253 | +- `zenithAbi` — Zenith contract ABI |
| 254 | +- `transactorAbi` — Transactor contract ABI |
| 255 | +- `bundleHelperAbi` — Bundle helper contract ABI |
| 256 | + |
| 257 | +## Subpath Imports |
| 258 | + |
| 259 | +The SDK supports subpath imports for smaller bundle sizes: |
| 260 | + |
| 261 | +```typescript |
| 262 | +import { MAINNET, PARMIGIANA } from "@signet-sh/sdk/constants"; |
| 263 | +import { UnsignedOrder } from "@signet-sh/sdk/signing"; |
| 264 | +import type { SignedOrder } from "@signet-sh/sdk/types"; |
| 265 | +import { rollupOrdersAbi, passageAbi, wethAbi } from "@signet-sh/sdk/abi"; |
| 266 | +import { getTokenAddress, getTokenDecimals } from "@signet-sh/sdk/tokens"; |
| 267 | +import { createTxCacheClient } from "@signet-sh/sdk/client"; |
| 268 | +import { ensurePermit2Approval } from "@signet-sh/sdk/permit2"; |
| 269 | +``` |
| 270 | + |
| 271 | +## Chain Configurations |
| 272 | + |
| 273 | +### MAINNET |
| 274 | + |
| 275 | +| Field | Value | |
| 276 | +| --------------- | -------------------------------------------- | |
| 277 | +| `hostChainId` | `1n` (Ethereum) | |
| 278 | +| `rollupChainId` | `519n` | |
| 279 | +| `hostPassage` | `0x02a64d6e2c30d2B07ddBD177b24D9D0f6439CcbD` | |
| 280 | +| `rollupOrders` | `0x000000000000007369676e65742d6f7264657273` | |
| 281 | +| `hostOrders` | `0x96f44ddc3Bc8892371305531F1a6d8ca2331fE6C` | |
| 282 | +| `txCacheUrl` | `https://transactions.signet.sh` | |
| 283 | + |
| 284 | +### PARMIGIANA (Testnet) |
| 285 | + |
| 286 | +| Field | Value | |
| 287 | +| --------------- | -------------------------------------------- | |
| 288 | +| `hostChainId` | `3151908n` | |
| 289 | +| `rollupChainId` | `88888n` | |
| 290 | +| `hostPassage` | `0x28524D2a753925Ef000C3f0F811cDf452C6256aF` | |
| 291 | +| `rollupOrders` | `0x000000000000007369676E65742D6f7264657273` | |
| 292 | +| `hostOrders` | `0x96f44ddc3Bc8892371305531F1a6d8ca2331fE6C` | |
| 293 | +| `txCacheUrl` | `https://transactions.parmigiana.signet.sh` | |
| 294 | +| `tokenDecimals` | `{ WUSD: 18 }` (testnet override) | |
| 295 | + |
| 296 | +## Common Patterns |
| 297 | + |
| 298 | +### Order Signing Flow |
| 299 | + |
| 300 | +1. Approve token to Permit2 (one-time per token) |
| 301 | +2. Build order with `UnsignedOrder` builder |
| 302 | +3. Sign with wallet (off-chain EIP-712 via Permit2) |
| 303 | +4. Submit to tx-cache with `createTxCacheClient` |
| 304 | + |
| 305 | +### Permit2 Approval (USDT-safe) |
| 306 | + |
| 307 | +```typescript |
| 308 | +import { ensurePermit2Approval } from "@signet-sh/sdk"; |
| 309 | + |
| 310 | +const { approved, txHash } = await ensurePermit2Approval( |
| 311 | + walletClient, |
| 312 | + publicClient, |
| 313 | + { |
| 314 | + token: tokenAddress, |
| 315 | + owner: account.address, |
| 316 | + amount: 1000000n, |
| 317 | + } |
| 318 | +); |
| 319 | +``` |
| 320 | + |
| 321 | +### Token Address Lookup |
| 322 | + |
| 323 | +```typescript |
| 324 | +import { getTokenAddress, getTokenDecimals, MAINNET } from "@signet-sh/sdk"; |
| 325 | + |
| 326 | +const weth = getTokenAddress("WETH", MAINNET.hostChainId, MAINNET); |
| 327 | +const decimals = getTokenDecimals("WETH", MAINNET); |
| 328 | +``` |
| 329 | + |
| 330 | +### WETH Wrap Check |
| 331 | + |
| 332 | +```typescript |
| 333 | +import { needsWethWrap } from "@signet-sh/sdk"; |
| 334 | + |
| 335 | +// Check if ETH needs wrapping for an Orders flow (Permit2 requires WETH) |
| 336 | +const wrap = needsWethWrap("ETH", "input", "orders"); // true |
| 337 | +const noWrap = needsWethWrap("ETH", "input", "passage"); // false — Passage accepts native ETH |
| 338 | +``` |
| 339 | + |
| 340 | +### Order Feasibility Check |
| 341 | + |
| 342 | +```typescript |
| 343 | +import { checkOrderFeasibility } from "@signet-sh/sdk"; |
| 344 | + |
| 345 | +const result = await checkOrderFeasibility(order, { |
| 346 | + publicClient, |
| 347 | + config: MAINNET, |
| 348 | +}); |
| 349 | +if (result.issues.length > 0) { |
| 350 | + console.log("Issues:", result.issues); |
| 351 | +} |
| 352 | +``` |
0 commit comments