TypeScript SDK
@ravelin-wall/sdk is a typed client for the canonical authorization protocol. It holds no security logic of its own: every decision is made server-side.
Configuration
config.ts◆ pseudocode · not yet runnable
import { ravelin } from "@ravelin-wall/sdk";
const wall = ravelin({
apiKey: process.env.RAVELIN_API_KEY!, // server-side only; never in a browser bundle
chainId: 4663,
timeoutMs: 10_000,
logger: console, // secrets are redacted before logging
});Decisions are a discriminated union
An ALLOW is an authorization, not a completed transaction. Submission, inclusion and execution are tracked separately through the operation status.
types.ts◆ pseudocode · not yet runnable
type Decision =
| { decision: "ALLOW"; operationId: string; authorizationId: string;
policyVersion: number }
| { decision: "REQUIRES_HUMAN_SIGNATURE"; operationId: string;
approvalId: string; expiresAt: Date; reasonCode: "RW_HUMAN_001" }
| { decision: "DENY"; reasonCode: ReasonCode; retryable: boolean;
message: string; transactionHash: null };Typed errors
Every reason code is exported as a string literal union. Retries reuse the original idempotency key.
errors.ts◆ pseudocode · not yet runnable
try {
await wall.operations.create(request);
} catch (err) {
if (err instanceof RavelinError) {
switch (err.code) {
case "RW_STATE_001": // retryable: authoritative state unavailable
case "RW_CHAIN_001": // retryable: bundler or RPC unavailable
return retryWithSameIdempotencyKey(request);
default:
throw err; // terminal
}
}
}About wrapping wallets
A helper that wraps a viem wallet client cannot protect a key that can still broadcast on its own. The SDK will only offer wallet wrapping for constrained smart-account signers, and will refuse to wrap a plain EOA as if it were protected.
Build order
- Canonical REST and authorization protocol.
- TypeScript SDK with viem.
- Protected smart-account integration.
- Python SDK.
- ethers adapter.
- Agent-framework examples, all calling the same protected interface.