Skip to content

Commit 18f4e34

Browse files
init4samwiseclaude
andauthored
chore: release v0.4.0 (#25)
* chore: bump version to 0.4.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add SKILL.md for SDK documentation - Add comprehensive skill file for @signet-sh/sdk - Document OrderEvent, FilledEvent, SweepEvent types (v0.4.0+) - Include core capabilities, exports, chain configs, common patterns Related to PR #21 * style: format SKILL.md --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 6fc00cf commit 18f4e34

File tree

3 files changed

+355
-1
lines changed

3 files changed

+355
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.4.0] - 2026-02-17
11+
1012
### Added
1113

1214
- `getTokenDecimals(symbol, config?)` helper for chain-aware decimal lookup

SKILL.md

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
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+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@signet-sh/sdk",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "TypeScript SDK for Signet Orders - create, sign, and verify orders compatible with signet-types",
55
"type": "module",
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)