@seer-pm/api-gateway
v0.1.0
Published
Shared types and helpers for the Seer API gateway (AA signing context, supported chains).
Maintainers
Readme
@seer-pm/api-gateway
Shared TypeScript types and small helpers used by the Seer API gateway and clients:
SigningContextandparseSigningContextfor ERC-4337 / Safe signing metadataENTRY_POINT_*/SAFE_ACCOUNT_VERSIONconstantsSUPPORTED_CHAINS,getChainById,getSigningContextgatewayRequest—gatewayRequest(baseUrl)returns a fluent client (.split(),.merge(),.quote(),.relay(), …); use.request({ path, method, body })for ad-hoc paths.fetch+ JSON + optionalrelayHint.signUserOperation— Safe account +signUserOperation(permissionless)
Peer dependencies: viem ^2, permissionless ^0.3.
Install
npm install @seer-pm/api-gateway viem permissionlessyarn add @seer-pm/api-gateway viem permissionlessUsage
gatewayRequest(baseUrl)
Call gatewayRequest with your API base URL (no trailing slash required). It returns a client with typed helpers for each route. Non-OK HTTP status codes throw; responses that include userOperation must also include a valid signingContext or the client throws.
import { gatewayRequest } from "@seer-pm/api-gateway";
const api = gatewayRequest("https://your-gateway.example.com/api");
// Convenience methods (paths match the Netlify/API handler)
const health = await api.health();
const split = await api.split(chainId, marketAddress, {
owner: "0x…",
amount: "1000000000000000000",
useMainCollateral: true
});
// When the gateway returns a UserOperation to sign, `relayHint` is set:
const hint = split.relayHint;
if (hint) {
const { intentId, userOperation, signingContext } = hint;
// … sign with signUserOperation, then submit:
await api.relay(chainId, {
intentId,
userOperation: { /* …signed op with `signature` field set… */ }
});
}
// Ad-hoc path when you already have path/method/body:
await api.request({
path: `/markets/${chainId}/${marketAddress}/merge`,
method: "POST",
body: { /* … */ }
});Other methods include merge, redeem, quote, executeTrade, createMarket, predictWallet, and userOperationReceipt.
signUserOperation
After a POST that returns userOperation + signingContext, use signUserOperation with a viem walletClient, the Safe owners (EOA account(s) or EIP-1193 provider(s), depending on your setup), and the same chainId as the request. The helper builds the Safe smart account from signingContext and returns the ERC-4337 signature.
import type { UserOperation } from "viem/account-abstraction";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { gnosis } from "viem/chains";
import { gatewayRequest, signUserOperation } from "@seer-pm/api-gateway";
const account = privateKeyToAccount(process.env.OWNER_PRIVATE_KEY as `0x${string}`);
const walletClient = createWalletClient({
account,
chain: gnosis,
transport: http()
});
const build = await gatewayRequest(API_BASE_URL).split(CHAIN_ID, MARKET_ADDRESS, {
owner: account.address,
amount: "10000000",
useMainCollateral: true
});
if (!build.relayHint) {
throw new Error("Expected relayHint from gateway");
}
const { intentId, userOperation, signingContext } = build.relayHint;
const { signature, userOperation: signedOp } = await signUserOperation({
walletClient,
signingContext,
userOperation: {
...(userOperation as Record<string, unknown>),
signature: "0x"
} as unknown as UserOperation,
chainId: CHAIN_ID,
owners: [account],
saltNonce: 0n // optional; must match the salt your Safe uses if non-default
});
await gatewayRequest(API_BASE_URL).relay(CHAIN_ID, {
intentId,
userOperation: {
...signedOp,
signature
}
});In browser apps with wagmi, owners is often [eip1193Provider] and you pass the wallet client from getWalletClient. Align chainId with signingContext.chainId and the chain the user selected.
Publishing (maintainers)
From the repo root after yarn install (which builds dist/ via postinstall):
cd packages/api-gateway
npm version patch # or minor / major
npm publish --access publicEnsure the @seer scope exists on npm and you are logged in (npm login).
