import type { Hex } from "viem"; import type { Encoding } from "../types/Delegation"; import type { FailureCode, MfaApprovalStateValue, MfaOperationType, SignatureMethod, SignJobFailureCode, SignJobStatusValue, TxJobStatusValue } from "./constants"; import { SIGN_REQUEST_KIND } from "./constants"; import type { RelayAuthorizationWire } from "./relayTypes"; export type { FailureCode, MfaApprovalStateValue, MfaOperationType, SignatureMethod, SignatureProtocol, SignJobFailureCode, SignJobStatusValue, SignRequestKind, TxJobStatusValue, } from "./constants"; /** * Tx wire shape the remote signing service accepts on * `POST /v1/projects/:projectId/transaction-requests`. Mirrors the * server's `TransactionTxDto`. EIP-1559 only — legacy `gasPrice` is not in * the DTO and is rejected by the server. Hex-string encoded fields match * viem's "hex string" convention for tx gas/value and signature `r`/`s`; * `nonce`, `chainId`, and `authorizationList` scalars are numeric on the wire. * * `encoding` is hoisted to the request body by {@link RemoteSigningClient.submitTransaction} * (ADR-0008). `authorizationList` stays nested on `tx` for BYOK type-4 * ERC-7821 upgrades; server-wallet erc7821 requests must omit it (Mimir * injects the 7702 auth). */ export type TransactionTx = { from: Hex; to: Hex; chainId: number; data?: string; value?: string; nonce?: number; gasLimit?: string; maxFeePerGas?: string; maxPriorityFeePerGas?: string; /** ADR-0008 encoding. Omit / `eip1559` for a normal tx; `erc7821` for a paid batch. */ encoding?: Encoding; /** BYOK-signed EIP-7702 auth for first-use upgrade on an erc7821 batch. */ authorizationList?: RelayAuthorizationWire[]; }; /** * MFA approval payload attached to any sign-job (tx, message, typed-data) * when policy evaluation requires user approval. Mirrors the backend's * `MfaApprovalStatusDto`. `decision` is set after the user approves/denies * on the bound device; `expiresAt` is the MFA window deadline; `effects` * is an open-shape list of side effects the policy engine attaches (we * keep it loose because the SDK never introspects it — the CLI surfaces * it verbatim). */ export type MfaApprovalStatus = { approvalId: string; expiresAt: string; violations: Array<{ policyId: string; severity: string; reason: string; details: Record; }>; decision?: "approve" | "deny"; decidedAt?: string; effects?: ApprovalEffect[]; }; /** * Open-shape policy effect (e.g. `{ type: "rate-limit", windowMs: 60000 }`). * The backend uses `additionalProperties: true`; we mirror that with an * index signature instead of typing each effect kind because the SDK does * not need to branch on them — the CLI surfaces them verbatim. */ export type ApprovalEffect = { [key: string]: unknown; type: string; }; type CommonJobFields = { requestId: string; approval?: MfaApprovalStatus; }; /** * Polled status for a transaction-signing job. `signedTransaction` and * `txHash` populate as the request transitions through `SIGNING` → * `BROADCASTING` → `BROADCASTED` → `CONFIRMED`. On terminal failure, * `failureCode` + `failureDescription` are set. */ export type TxJobStatus = CommonJobFields & { kind: typeof SIGN_REQUEST_KIND.TRANSACTION; status: TxJobStatusValue; tx: TransactionTx; txApprovalLink?: string; signedTransaction?: string; broadcastId?: string; txHash?: string; txBlock?: number; failureCode?: FailureCode; failureDescription?: string; }; /** * Open-shape Shield scan result the backend attaches to every signature * request once Shield has produced a terminal result. We intentionally type * the shape loosely — the CLI surfaces these fields verbatim and the SDK * does not branch on them. */ export type SignatureShieldStatus = { coverageId?: string; scanStatus?: string; reasonCode?: string; evaluatedAt?: string; }; /** * Single per-evaluator result the backend records on a signature request. * Currently shield-only; kept open-shape so future evaluators can land * without an SDK release. */ export type SignatureEvaluationStatus = { evaluator: string; type: string; scanStatus: string; externalId?: string; reasonCode?: string; evaluatedAt: string; }; /** * Polled status for a signature request. Replaces the previous * `MessageJobStatus` / `TypedDataJobStatus` split: the backend unified both * under `POST /v1/projects/:projectId/signature-requests`, distinguished by * `method` (`personal_sign` vs `eth_signTypedData_v4`). `signature` * populates only on the `SIGNED` terminal status. * * The SDK injects `kind: "signature"` at the boundary so the discriminated * union with {@link TxJobStatus} still works; the wire payload does not * include it. */ export type SignatureRequestStatus = CommonJobFields & { kind: typeof SIGN_REQUEST_KIND.SIGNATURE; status: SignJobStatusValue; walletAddress: string; method: SignatureMethod; chainId: number; origin: string; txApprovalLink?: string; shield?: SignatureShieldStatus; evaluations?: SignatureEvaluationStatus[]; signature?: string; failureCode?: SignJobFailureCode; failureDescription?: string; }; /** * Discriminated union covering every remote-signing job the SDK surfaces. * Both status endpoints (`/transaction-requests/:id` and * `/signature-requests/:id`) return into this type; the SDK narrows on * `kind` for terminal-set membership and success-payload extraction. */ export type JobStatus = TxJobStatus | SignatureRequestStatus; /** * Display-ready violation returned by the unified approval route. Richer * than the raw `approval.violations` on job status: the backend transforms * violations for UX (title, human-readable descriptions). Kept loosely * typed beyond the display fields — the SDK never branches on violation * internals; clients surface them verbatim. */ export type MfaApprovalViolation = { [key: string]: unknown; id: string; policyId: string; reason: string; title: string; severity: string; message: string; descriptions: string[]; details: Record; }; /** * Operation-specific subject attached to an MFA approval. The backend * returns a discriminated shape per `operationType` * (`transaction_request` / `signature_request` / `wallet_policy_update` / * `wallet_mode_change`); the SDK types only the fields consumers read * (`type`, correlation ids, request status, violations) and keeps the rest * open-shape — clients surface subject details verbatim. */ export type MfaApprovalSubject = { [key: string]: unknown; type: MfaOperationType; /** Present on transaction_request / signature_request subjects. */ requestId?: string; /** Underlying request status at read time (tx or signature lifecycle). */ requestStatus?: string; /** Present on wallet_mode_change / wallet_policy_update subjects. */ walletAddress?: string; violations?: MfaApprovalViolation[]; }; /** * MFA approval details from the unified approval route * (`GET /v1/projects/:projectId/approval/:id`). Mirrors the backend's * `MfaApprovalDetailsDto`. `status` is the approval's derived state — * distinct from the underlying job status: an `approved` approval means the * user passed MFA, not that the transaction has broadcast or confirmed. */ export type MfaApprovalDetails = { approvalId: string; operationType: MfaOperationType; /** Operation-specific subject id (requestId for tx/signature approvals). */ subjectId: string; status: MfaApprovalStateValue; /** ISO-8601 deadline after which the approval can no longer be accepted. */ expiresAt: string; createdAt: string; decision?: "approve" | "deny"; decidedAt?: string; subject: MfaApprovalSubject; };