/** * DPv2 escrow payment helpers. * * Covers the three-phase flow used by builders to pay for data access: * * 1. **Deposit** — call `depositNative` or `depositToken` on the * DataPortabilityEscrow contract, then notify the gateway. * 2. **Balance** — read or force-sync the gateway's off-chain credit view. * 3. **Pay** — sign a `GenericPayment` EIP-712 message and POST it to the * gateway's `/v1/escrow/pay` endpoint. * * The gateway is the authority on balances; the on-chain contract is the * authority on what has been settled. Nothing in this module touches the * chain directly — signing is done by the caller's wallet. * * @category Protocol * @module escrow */ export { buildWithdrawAuthorizationTypedData, withdrawAuthorizationDomain, WITHDRAW_AUTHORIZATION_TYPES, type WithdrawAuthorizationMessage, } from "./eip712.js"; import type { TypedDataDomain } from "viem"; /** * EIP-712 typed-data types for a generic op payment. * * The gateway verifies that the recovered signer == `payerAddress` and that * the (payer, paymentNonce) pair has not been seen before. Use a * monotonically-increasing nonce; the first payment for any payer should * start at 1. */ export declare const GENERIC_PAYMENT_TYPES: { readonly GenericPayment: readonly [{ readonly name: "payerAddress"; readonly type: "address"; }, { readonly name: "opType"; readonly type: "string"; }, { readonly name: "opId"; readonly type: "bytes32"; }, { readonly name: "asset"; readonly type: "address"; }, { readonly name: "amount"; readonly type: "uint256"; }, { readonly name: "paymentNonce"; readonly type: "uint256"; }]; }; /** * EIP-712 message payload for a generic op payment. * * - `opType` is `"grant"` for legacy grant lifecycle payments or * `"data_access"` for a standalone receipt-bound read. * - `opId` is the bytes32 id of the operation being paid for: the grant id for * `"grant"`, or `accessRecord.recordId` for `"data_access"`. * - `asset` is the ERC-20 token address, or the zero address for native VANA. * - `amount` is the total amount in base units (wei for VANA). Must match the * sum the gateway expects for the current lifecycle of the op. * - `paymentNonce` must be a positive integer unique per `payerAddress`. Use 1 * for the first payment; increment by at least 1 for each subsequent call. */ export interface GenericPaymentMessage { payerAddress: `0x${string}`; opType: string; opId: `0x${string}`; asset: `0x${string}`; amount: bigint; paymentNonce: bigint; } /** * Returns the EIP-712 domain for signing a `GenericPayment` message. * * The verifying contract is the `DataPortabilityEscrow` contract; all gateway * deployments share the same domain name and version. * * @param chainId - Chain ID of the Vana network (e.g. 1480 mainnet, 14800 testnet). * @param escrowContract - Deployed address of DataPortabilityEscrow. */ export declare function genericPaymentDomain(chainId: number, escrowContract: `0x${string}`): TypedDataDomain; /** * Minimal ABI for the two deposit entry points on `DataPortabilityEscrow`. * * - `depositNative(address account)` payable — credits native VANA. * - `depositToken(address account, address token, uint256 amount)` — credits * an ERC-20 token (caller must have pre-approved the escrow contract). * * Pass this to viem's `writeContract` or encode it manually. */ export declare const ESCROW_DEPOSIT_ABI: readonly [{ readonly type: "function"; readonly name: "depositNative"; readonly stateMutability: "payable"; readonly inputs: readonly [{ readonly name: "account"; readonly type: "address"; }]; readonly outputs: readonly []; }, { readonly type: "function"; readonly name: "depositToken"; readonly stateMutability: "nonpayable"; readonly inputs: readonly [{ readonly name: "account"; readonly type: "address"; }, { readonly name: "token"; readonly type: "address"; }, { readonly name: "amount"; readonly type: "uint256"; }]; readonly outputs: readonly []; }]; /** * The zero address used by the DataPortabilityEscrow contract to represent * native VANA in `asset` fields of events and balance responses. */ export declare const NATIVE_ASSET_ADDRESS: "0x0000000000000000000000000000000000000000"; /** * Per-asset balance entry returned by the gateway's escrow balance endpoints. * * - `balance` — gross finalized credit (deposits credited so far). * - `pendingAmount` — sum of submitted deposits not yet confirmed. * - `authorizedAmount` — sum of all in-flight payments authorized by * `/v1/escrow/pay` (soft-lock). May include payments not yet settled * on-chain. * - `withdrawingAmount` — sum of in-flight withdrawal reservations. * - `availableAmount` — `max(balance − authorizedAmount − withdrawingAmount, 0)`. * This is what the account can still authorize or withdraw. */ export interface EscrowBalanceEntry { asset: string; balance: string; pendingAmount: string; authorizedAmount: string; withdrawingAmount: string; availableAmount: string; /** Minimum withdrawal amount currently accepted for this asset, if configured. */ withdrawalMinimumAmount: string | null; updatedAt: string | null; } export interface SubmittedDepositEntry { txHash: string; submittedAt: string; claimedAsset: string; claimedAmount: string; } export interface FinalizedDepositEntry { txHash: string; finalizedAt: string | null; blockNumber: string | null; claimedAsset: string; claimedAmount: string; } export interface FailedDepositEntry { txHash: string; submittedAt: string; claimedAsset: string; claimedAmount: string; lastError: string | null; } /** Full balance read response from `GET /v1/escrow/balance`. */ export interface EscrowBalanceResult { account: string; balances: EscrowBalanceEntry[]; deposits: { submitted: SubmittedDepositEntry[]; finalized: FinalizedDepositEntry[]; failed: FailedDepositEntry[]; }; } /** * Response from `POST /v1/escrow/balance/sync`. * * Extends {@link EscrowBalanceResult} with a `sync` summary of what the * lazy-confirmation pass did. */ export interface EscrowBalanceSyncResult extends EscrowBalanceResult { sync: { scanned: number; finalized: number; stillPending: number; failed: number; } | { skipped: true; }; } /** Response from `POST /v1/escrow/deposit`. */ export interface DepositSubmissionResult { success: true; txHash: string; account: string; status: "submitted" | "finalized" | "failed"; blockNumber?: string | null; submittedAt: string; finalizedAt?: string | null; lastError?: string | null; } /** Breakdown returned by a successful `POST /v1/escrow/pay`. */ export interface PaymentBreakdown { registrationFee: string; dataAccessFee: string; /** True when this call settled the registration fee for the op. */ registrationPaid: boolean; } /** Response from `POST /v1/escrow/pay`. */ export interface EscrowPayResult { success: true; opType: string; opId: string; payerAddress: string; asset: string; amount: string; breakdown: PaymentBreakdown; paymentNonce: string; paidAt: string; } interface EscrowWithdrawalResponseBase { account: `0x${string}`; asset: `0x${string}`; amount: string; withdrawNonce: string; deadline: string; } /** A persisted authorization whose transaction has not been broadcast yet. */ export interface EscrowWithdrawalSubmittedWithoutTransaction extends EscrowWithdrawalResponseBase { success: true; status: "submitted"; txHash: null; message: string; } /** A withdrawal with a persisted transaction that is awaiting reconciliation. */ export interface EscrowWithdrawalSubmittedWithTransaction { success: true; status: "submitted"; txHash: `0x${string}`; message: string; account?: `0x${string}`; asset?: `0x${string}`; amount?: string; withdrawNonce?: string; deadline?: string; blockNumber?: string; } /** A withdrawal that the gateway has accepted but not yet confirmed. */ export type EscrowWithdrawalSubmittedResult = EscrowWithdrawalSubmittedWithoutTransaction | EscrowWithdrawalSubmittedWithTransaction; /** A withdrawal whose on-chain debit has reached the named lifecycle state. */ export interface EscrowWithdrawalSettledResult extends EscrowWithdrawalResponseBase { success: true; status: "confirmed" | "finalized"; txHash: `0x${string}`; blockNumber: string | null; } /** Successful lifecycle responses from `POST /v1/escrow/withdraw`. */ export type EscrowWithdrawalResult = EscrowWithdrawalSubmittedResult | EscrowWithdrawalSettledResult; /** Terminal or retryable withdrawal lifecycle state returned with a non-2xx status. */ export interface EscrowWithdrawalFailureResult extends EscrowWithdrawalResponseBase { success: false; status: "retryable" | "reorged" | "failed"; error: string; txHash: `0x${string}` | null; blockNumber?: string | null; } export type EscrowWithdrawalRejectionCode = "below_minimum" | "deadline_too_far" | "expired" | "insufficient_available" | "stale_nonce"; /** Definite pre-acceptance rejection. No durable withdrawal intent was created. */ export interface EscrowWithdrawalRejectedResult extends EscrowWithdrawalResponseBase { success: false; status: "rejected"; code: EscrowWithdrawalRejectionCode; error: string; balance?: string; authorizedAmount?: string; withdrawingAmount?: string; availableAmount?: string; requestedAmount?: string; minimumAmount?: string; } /** * A typed non-2xx gateway lifecycle response. * * `retryable` means resend the exact signed intent. `reorged` and `failed` * require a newly signed authorization with a new nonce. */ export declare class EscrowWithdrawalLifecycleError extends Error { readonly httpStatus: number; readonly result: EscrowWithdrawalFailureResult; readonly name = "EscrowWithdrawalLifecycleError"; constructor(httpStatus: number, result: EscrowWithdrawalFailureResult); } /** A typed non-2xx gateway rejection before a withdrawal intent is accepted. */ export declare class EscrowWithdrawalRejectionError extends Error { readonly httpStatus: number; readonly result: EscrowWithdrawalRejectedResult; readonly name = "EscrowWithdrawalRejectionError"; constructor(httpStatus: number, result: EscrowWithdrawalRejectedResult); } /** * Parameters for submitting a deposit tx hash to the gateway. * * The gateway will decode the `account` from the tx's calldata and * credit the identified account once the tx reaches the configured * confirmation depth. */ export interface SubmitDepositParams { /** 0x-prefixed 32-byte transaction hash. */ txHash: `0x${string}`; } /** * Parameters for the generic op payment endpoint (`POST /v1/escrow/pay`). * * The `signature` is an EIP-712 signature over a `GenericPayment` message * (see {@link GENERIC_PAYMENT_TYPES} and {@link genericPaymentDomain}). * Build and sign the typed data with your wallet before calling * {@link EscrowGatewayClient.payForOp}. */ export interface PayForOpParams { payerAddress: `0x${string}`; opType: string; opId: `0x${string}`; asset: `0x${string}`; /** Decimal string representation of the uint256 amount. */ amount: string; /** Decimal string representation of the uint256 nonce. */ paymentNonce: string; /** 0x-prefixed 65-byte EIP-712 signature hex string. */ signature: `0x${string}`; /** * Optional data-access receipt carried by x402 challenges. * * The gateway verifies its server signature; this type only describes the * wire shape. */ accessRecord?: EscrowAccessRecord; } /** * Parameters for `POST /v1/escrow/withdraw`. * * `withdrawNonce` and `deadline` are caller-supplied decimal uint256 strings. * The SDK intentionally does not generate a nonce: retrying safely requires a * durable caller-owned nonce source and the exact same signed payload. */ export interface WithdrawFromEscrowParams { account: `0x${string}`; asset: `0x${string}`; amount: string; withdrawNonce: string; deadline: string; signature: `0x${string}`; } /** * Response from `GET /v1/escrow/withdraw/nonce`. * * The gateway provides a read-only snapshot of the account's withdrawal nonce * state. This is **not** a reservation; multiple concurrent callers will see * the same `nextWithdrawNonce`. To reduce staleness risk, query immediately before * signing/submitting the withdrawal authorization. However, `stale_nonce` errors can * still occur under concurrent withdrawal attempts; if rejected, re-query and re-sign. * * Use `nextWithdrawNonce` in the signed withdrawal authorization; `lastWithdrawNonce` * is provided for reference and diagnostics. */ export interface WithdrawNonceResponse { success: true; account: `0x${string}`; chainId: string; lastWithdrawNonce: string | null; nextWithdrawNonce: string; } /** Wire shape of a receipt whose server signature the gateway verifies. */ export interface EscrowAccessRecord { dataPointId: `0x${string}`; version: string; accessor: `0x${string}`; recordId: `0x${string}`; signature: `0x${string}`; } /** * Minimal client for the gateway's escrow endpoints. * * Construct with {@link createEscrowGatewayClient}. */ export interface EscrowGatewayClient { /** * Notify the gateway of a submitted deposit transaction. * * The gateway decodes the credited account from the on-chain tx calldata * and starts tracking the deposit. Call this immediately after your * `depositNative` or `depositToken` tx is broadcast (it accepts pending * mempool txs). Returns `202` while the tx awaits confirmation. */ submitDeposit(params: SubmitDepositParams): Promise; /** * Read the current escrow balance for an account. * * Pure read — no chain calls. To force a reconciliation pass first, * use {@link syncEscrowBalance}. */ getEscrowBalance(account: `0x${string}`): Promise; /** * Force a reconciliation pass then return the updated balance. * * Triggers the gateway's lazy-confirmation worker for the account — any * submitted deposits that have reached the configured confirmation level * are credited before the balance is returned. Prefer this over * {@link getEscrowBalance} when you need a fresh view after a deposit. */ syncEscrowBalance(account: `0x${string}`): Promise; /** * Authorize a payment against the payer's escrow balance. * * The caller must: * 1. Assemble a {@link GenericPaymentMessage}. * 2. Sign it with `signTypedData` using {@link GENERIC_PAYMENT_TYPES} and * the domain from {@link genericPaymentDomain}. * 3. Pass the message fields + signature here. * * The gateway verifies the signature, checks the soft-lock balance, and * records the payment. Returns 402 if the payer has insufficient balance. */ payForOp(params: PayForOpParams): Promise; /** * Submit or reconcile a signed withdrawal authorization. * * The gateway decides which signers may authorize an account. For example, * it may accept the account itself or the confirmed owner of a registered * app account. * * Retry a `submitted` result with the exact same parameters. Do not replace * `withdrawNonce`, `deadline`, or signature unless starting a new intent. */ withdraw(params: WithdrawFromEscrowParams): Promise; /** * Read the authoritative next withdrawal nonce for an account. * * The gateway is the authority on what nonce to use; use the value from * `nextWithdrawNonce` when signing a withdrawal authorization. * * Do NOT generate or cache nonces client-side; concurrent callers cannot be * safely coordinated without durable shared state. Query this endpoint immediately * before signing/submitting to reduce staleness risk. However, `stale_nonce` errors * can still occur; if rejected, re-query and re-sign. */ getWithdrawNonce(account: `0x${string}`): Promise; } /** The only gateway capability required by direct data-access payment flows. */ export type EscrowPaymentClient = Pick; /** * Creates a client for the gateway escrow endpoints. * * @param baseUrl - Base URL of the DP RPC gateway * (e.g. `"https://dp.vana.org"`). Trailing slashes are trimmed. * * @example * ```typescript * import { * createEscrowGatewayClient, * genericPaymentDomain, * GENERIC_PAYMENT_TYPES, * } from "@opendatalabs/vana-sdk/node"; * * const escrow = createEscrowGatewayClient("https://dp.vana.org"); * * // 1. Submit your deposit tx hash after broadcasting depositNative on-chain * const deposit = await escrow.submitDeposit({ txHash: "0xabc…" }); * * // 2. Force-sync and read the updated balance * const { balances } = await escrow.syncEscrowBalance("0xpayerAddress"); * * // 3. Sign and authorize a grant payment * const sig = await walletClient.signTypedData({ * domain: genericPaymentDomain(1480, "0xEscrowContract"), * types: GENERIC_PAYMENT_TYPES, * primaryType: "GenericPayment", * message: { * payerAddress: "0xpayerAddress", * opType: "grant", * opId: "0xgrantId", * asset: "0x0000000000000000000000000000000000000000", * amount: 1000000000000000000n, * paymentNonce: 1n, * }, * }); * const result = await escrow.payForOp({ * payerAddress: "0xpayerAddress", * opType: "grant", * opId: "0xgrantId", * asset: "0x0000000000000000000000000000000000000000", * amount: "1000000000000000000", * paymentNonce: "1", * signature: sig, * }); * ``` */ export declare function createEscrowGatewayClient(baseUrl: string): EscrowGatewayClient;