import { type AccountMeta, type Address, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyUint8Array, type Signature, type TransactionPartialSigner, type TransactionSigner } from '@solana/kit'; import { ASSOCIATED_TOKEN_PROGRAM } from '../../constants.js'; import type { OpenPayload, SignedVoucher } from '../../shared/session-types.js'; /** * Concrete instruction shape returned by every builder in this module: * the program address, a concrete account list, and a `Uint8Array` data * buffer. Avoids the `data?: Uint8Array | undefined` widening of the * base `Instruction` interface. */ export type ServerInstruction = Instruction & InstructionWithAccounts & InstructionWithData; /** Sysvar address holding the current transaction's instructions list. */ export declare const INSTRUCTIONS_SYSVAR_ADDRESS: Address<"Sysvar1nstructions1111111111111111111111111">; /** Ed25519 signature-verification precompile program id. */ export declare const ED25519_PROGRAM_ADDRESS: Address<"Ed25519SigVerify111111111111111111111111111">; /** * Canonical payment-channels program ID, re-exported from the generated client * so there's a single source of truth that updates on IDL regeneration. * Callers can override per-call. */ export declare const PAYMENT_CHANNELS_PROGRAM_ID: Address<"CHNLxYvVA28MJP9PrFuDXccuoGXAx7jBacfLEkahyGsX">; /** Canonical multi-delegator program ID. */ export declare const MULTI_DELEGATOR_PROGRAM_ID: Address<"EPEUTog1kptYkthDJF6MuB1aM4aDAwHYwoF32Rzv5rqg">; /** * Build an Ed25519 verify precompile instruction over the 50-byte voucher * message. Layout matches `build_ed25519_verify_instruction` in * `rust/crates/mpp/src/program/payment_channels.rs`. * * `signature` is the 64-byte ed25519 signature, `signer` is the 32-byte * verifying key, and `message` is the canonical voucher payload. */ export declare function buildEd25519VerifyInstruction(args: { readonly message: Uint8Array; readonly signature: Uint8Array; readonly signer: Uint8Array; }): ServerInstruction; /** * Encode the canonical 50-byte voucher payload (magic-prefixed). Identical * to `encodeVoucherMessage` in `shared/voucher.ts` but kept here so the * on-chain helpers don't pull in client-side types. */ export declare function encodeVoucherMessageBytes(args: { readonly channelId: string; readonly cumulativeAmount: bigint; readonly expiresAt: bigint; }): Uint8Array; /** Arguments to {@link buildSettleAndSealInstructions}. */ export interface SettleAndSealBuildArgs { /** Payment-channel address being settled (base58). */ readonly channelId: string; /** Merchant signer authorized to settle the channel. */ readonly merchantSigner: TransactionSigner; /** Payment-channels program id override. */ readonly programId?: Address | undefined; /** * Optional final voucher. When present, an Ed25519 precompile IX is * prepended and `hasVoucher` is set to 1 on the settle_and_seal args. * Both `signature` (base58, 64 bytes) and `authorizedSigner` (base58, 32 bytes) * are required when `voucher` is provided. */ readonly voucher?: { readonly authorizedSigner: string; readonly signed: SignedVoucher; } | undefined; } /** Instructions produced for a settle_and_seal call. */ export interface SettleAndSealBuildResult { /** Instructions in submit order (Ed25519 precompile first when a voucher is settled). */ readonly instructions: readonly ServerInstruction[]; /** True when the transaction must carry the Ed25519 precompile instruction. */ readonly requiresEd25519Precompile: boolean; } /** * Build the instruction(s) for an on-chain settle_and_seal. If a * voucher is provided, an Ed25519 precompile IX is prepended at index 0 * — the settle_and_seal IX references the instructions sysvar at * index `-1` (i.e. the precompile immediately before it). */ export declare function buildSettleAndSealInstructions(args: SettleAndSealBuildArgs): SettleAndSealBuildResult; /** Arguments to {@link buildDistributeInstruction}. */ export interface DistributeBuildArgs { readonly channelState: { readonly channelId: string; readonly payee: string; readonly payer: string; }; readonly mint: string; readonly payerAddr?: string | undefined; readonly programId?: Address | undefined; /** * Operator recorded as `rentPayer` at open; it reclaims the channel PDA + * escrow ATA rent at distribute (writable, not a signer). Required — it * must match the rentPayer the channel stored, so there is no payer * fallback. */ readonly rentPayer: string; readonly splits: readonly { readonly bps: number; readonly recipient: string; }[]; readonly tokenProgram: string; } /** * Build a distribute instruction with the dynamic recipient ATA tail. * * The tail (one writable account per split) is appended after the fixed * 10-account header, matching the Rust `build_distribute_instruction` in * `rust/crates/mpp/src/program/payment_channels.rs`. */ export declare function buildDistributeInstruction(args: DistributeBuildArgs): Promise; /** Arguments to the top_up instruction builder. */ export interface TopUpBuildArgs { readonly amount: bigint; readonly channelId: string; readonly mint: string; readonly payer: TransactionSigner; readonly programId?: Address | undefined; readonly tokenProgram: string; } /** * Build a top_up instruction. Derives the payer + channel ATAs for the * given mint/token program — same layout the on-chain program expects. */ export declare function buildTopUpInstruction(args: TopUpBuildArgs): Promise; /** Arguments to the reclaim instruction builder. */ export interface ReclaimBuildArgs { readonly channelId: string; readonly programId?: Address | undefined; /** Operator recorded as `rentPayer` at open; receives the channel PDA lamports. */ readonly rentPayer: string; } /** * Build a reclaim instruction. Permissionless rent recovery for a channel * left in the `distributed` status: the program closes the channel PDA and * returns its lamports to `rentPayer` once `clock.slot > open_slot + 1500`. */ export declare function buildReclaimInstruction(args: ReclaimBuildArgs): ServerInstruction; /** * Expected fields against which the server validates a client-submitted * open transaction. The PDAs (channel, channel-token-account, * payer-token-account, event-authority) are recomputed if not provided. */ export interface VerifyOpenTxExpected { readonly authorizedSigner: string; readonly currency: string; readonly maxCap: bigint; /** Optional override for the SPL mint (otherwise resolved from currency/network). */ readonly mint?: string | undefined; readonly network?: string | undefined; /** * Challenge-issued open slot. When set, the open instruction's `openSlot` * arg must equal it — the client is required to echo the slot the server * handed out in the 402 challenge. */ readonly openSlot?: bigint | undefined; /** * Operator / fee-payer pubkey (base58) = the expected `rentPayer`. The open * instruction's `rentPayer` account (slot 1) must equal it (it is pinned to * the operator that co-signs open as fee payer while gasless). Required: the * rentPayer slot is a security boundary and is always checked. */ readonly operator: string; /** Optional override for the payment-channels program id. */ readonly programId?: string | undefined; /** Primary recipient (challenge `recipient`). */ readonly recipient: string; /** Optional explicit token program (otherwise derived from currency/network). */ readonly tokenProgram?: string | undefined; } /** One entry of a `getSignatureStatuses` response. */ export interface SignatureStatus { readonly confirmationStatus?: string | null | undefined; readonly err: unknown; } /** Minimal RPC shape needed to check transaction signature statuses. */ export interface SignatureStatusRpc { getSignatureStatuses(signatures: readonly Signature[]): { send(): Promise<{ value: ReadonlyArray; }>; }; } /** Arguments to {@link verifyOpenTx}. */ export interface VerifyOpenTxArgs { /** Expected values from the challenge. */ readonly expected: VerifyOpenTxExpected; /** Open payload received from the client. */ readonly openPayload: OpenPayload; /** Minimal RPC shape; only `getSignatureStatuses` is used. Optional. */ readonly rpc?: SignatureStatusRpc | undefined; } /** Channel facts extracted from a verified open transaction. */ export interface VerifyOpenTxResult { /** Payment-channel address derived from the open instruction (base58). */ readonly channelId: string; /** Deposit locked by the open, in base units. */ readonly deposit: bigint; /** Close grace period in seconds. */ readonly gracePeriod: number; /** Slot the open was built against (a channel PDA seed; gates reclaim). */ readonly openSlot: bigint; /** * Channel payer (open account 0, base58): the deposit funder and the * distribute refund destination (the program enforces it equals * `channel.payer`). */ readonly payer: string; /** Channel-derivation salt. */ readonly salt: bigint; } /** * Decode and validate the client-submitted open transaction. * * Accepts both legacy and v0 transaction encodings (the Rust client emits * legacy; the TS client emits v0). * * Asserts the embedded Open IX targets the configured payment-channels * program, that `payee == expected.recipient`, that the mint matches the * challenge currency/network, that `deposit <= maxCap`, and that the * channel PDA matches the recomputed value. * * When the payload carries a non-placeholder `signature`, it must equal * the transaction's own first signature — a client must not be able to * pair unrelated (but confirmed) signatures with different transaction * bytes. If `rpc` is provided, that signature is also sanity-checked via * `getSignatureStatuses`. When the transaction is still partially-signed * (signature placeholder), neither check is made. */ export declare function verifyOpenTx(args: VerifyOpenTxArgs): Promise; /** Tuning knobs for {@link waitForSignatureConfirmation}. */ export interface ConfirmSignatureOptions { /** Delay between status polls in ms. Defaults to 1_000. */ readonly pollIntervalMs?: number | undefined; /** Optional abort signal to cancel the wait early. */ readonly signal?: AbortSignal | undefined; /** Total time budget in ms. Defaults to 30_000. */ readonly timeoutMs?: number | undefined; } /** * Poll `getSignatureStatuses` until `signature` reaches at least * 'confirmed' commitment. Throws if the transaction failed on-chain, the * abort signal fires, or the timeout elapses before confirmation. */ export declare function waitForSignatureConfirmation(args: { readonly context?: string | undefined; readonly options?: ConfirmSignatureOptions | undefined; readonly rpc: SignatureStatusRpc; readonly signature: Signature; }): Promise; /** * Server-submits-open flow: validates the client-submitted tx, broadcasts * it via the supplied RPC, then waits for the signature to reach at least * 'confirmed' before returning — callers must not persist channel state * for a transaction that never landed. */ export interface SubmitOpenTxArgs extends VerifyOpenTxArgs { /** Confirmation polling overrides (timeout, poll interval, abort). */ readonly confirm?: ConfirmSignatureOptions | undefined; /** * Server-side fee-payer signer. When the client built the open * transaction with the operator as fee payer (and a placeholder where * the operator's signature belongs), this signer completes the * signature before broadcast. */ readonly payerSigner?: TransactionPartialSigner | undefined; readonly rpc: SignatureStatusRpc & { sendTransaction: (wire: string, config?: unknown) => { send: () => Promise; }; }; } /** Result of a server-submitted open: the verified channel facts plus the broadcast signature. */ export interface SubmitOpenTxResult extends VerifyOpenTxResult { /** Signature of the broadcast open transaction. */ readonly signature: Signature; } /** * Verifies a client-built open transaction, broadcasts it, and waits for * confirmation. Used when the session is configured with * `openTxSubmitter: 'server'`. */ export declare function submitOpenTx(args: SubmitOpenTxArgs): Promise; /** Arguments to {@link submitSettleAndDistribute}. */ export interface SubmitSettleAndDistributeArgs { /** * Caller-provided transaction builder — keeping this module RPC-free * for now keeps tests deterministic. The caller composes the * instructions into a transaction, signs it, encodes as base64, and * returns the wire bytes. Phase F surfpool integration will replace * this with a real pipe/sign call. */ readonly buildAndSignWireTransaction: (instructions: readonly ServerInstruction[]) => Promise; readonly channelId: string; readonly currency?: string | undefined; readonly mint: string; readonly network?: string | undefined; readonly payee: string; readonly payer: string; readonly programId?: Address | undefined; /** * Operator recorded as `rentPayer` at open; it reclaims the channel/escrow * rent at distribute. Required (no payer fallback). */ readonly rentPayer: string; readonly rpc: { sendTransaction: (wire: string, config?: unknown) => { send: () => Promise; }; }; readonly signer: TransactionSigner; readonly splits: readonly { readonly bps: number; readonly recipient: string; }[]; readonly tokenProgram?: string | undefined; readonly voucher?: { readonly authorizedSigner: string; readonly signed: SignedVoucher; } | undefined; } /** Result of a settle-and-distribute submission. */ export interface SubmitSettleAndDistributeResult { /** Instructions that were composed into the transaction. */ readonly instructions: readonly ServerInstruction[]; /** Signature of the broadcast transaction. */ readonly signature: Signature; } /** * Build settle_and_seal (+ optional Ed25519 precompile) + distribute * instructions and submit them as a single transaction. Designed for * push-mode close — the caller supplies a signing closure so the actual * compile/sign step stays out of this module's surface. */ export declare function submitSettleAndDistribute(args: SubmitSettleAndDistributeArgs): Promise; /** PDA seed for the multi-delegate account (mirrors the Rust program). */ export declare const MULTI_DELEGATE_SEED = "MultiDelegate"; /** PDA seed for per-operator delegation accounts (mirrors the Rust program). */ export declare const DELEGATION_SEED = "delegation"; export declare function findMultiDelegatePda(args: { readonly mint: string; readonly programId?: Address | undefined; readonly user: string; }): Promise
; export declare function findFixedDelegationPda(args: { readonly delegatee: string; readonly delegator: string; readonly multiDelegate: string; readonly nonce: bigint; readonly programId?: Address | undefined; }): Promise
; /** RPC shape needed by {@link submitInitMultiDelegateTxIfMissing}. */ export interface MultiDelegateSubmitRpc extends SignatureStatusRpc { getAccountInfo(address: Address, config?: unknown): { send(): Promise<{ value: unknown; }>; }; sendTransaction(wire: string, config?: unknown): { send(): Promise; }; } /** * Idempotently submit a client-pre-signed `InitMultiDelegate` (+ initial * `CreateFixedDelegation`) transaction: the MultiDelegate PDA for * (owner, mint) is checked first via RPC and the transaction is only * broadcast when the PDA does not exist yet. Returns the submission * signature, or `undefined` when the PDA already exists. */ export declare function submitInitMultiDelegateTxIfMissing(args: { readonly confirm?: ConfirmSignatureOptions | undefined; readonly initMultiDelegateTx: string; readonly mint: string; readonly owner: string; readonly programId?: Address | undefined; readonly rpc: MultiDelegateSubmitRpc; }): Promise; export interface MultiDelegatorInitArgs { readonly mint: string; readonly programId?: Address | undefined; readonly tokenProgram: string; readonly user: TransactionSigner; readonly userAta: string; } /** * Hand-encoded `InitMultiDelegate` instruction (disc = 0x00). * * Accounts: `[user (signer/write), multiDelegate (write, derived), * tokenMint (read), userAta (write), systemProgram (read), tokenProgram * (read)]`. Matches Rust `build_init_multi_delegate_ix` in * `program/multi_delegator.rs`. */ export declare function buildMultiDelegatorInitInstruction(args: MultiDelegatorInitArgs): Promise; export interface MultiDelegatorUpdateArgs { readonly amount: bigint; readonly delegatee: string; readonly delegator: TransactionSigner; /** Unix seconds, 0 = no expiry. */ readonly expiryTs: bigint; readonly mint: string; readonly nonce: bigint; readonly programId?: Address | undefined; } /** * Hand-encoded `CreateFixedDelegation` instruction (disc = 0x01). * * Data: `[0x01] ++ nonce_le ++ amount_le ++ expiry_le` (25 bytes). * Accounts: `[delegator (signer/write), multiDelegate (read), delegationPda * (write), delegatee (read), systemProgram (read)]`. Matches Rust * `build_create_fixed_delegation_ix` in `program/multi_delegator.rs`. */ export declare function buildMultiDelegatorUpdateInstruction(args: MultiDelegatorUpdateArgs): Promise; declare const SYSTEM_PROGRAM_ADDRESS: Address<"11111111111111111111111111111111">; export { ASSOCIATED_TOKEN_PROGRAM, SYSTEM_PROGRAM_ADDRESS }; //# sourceMappingURL=on-chain.d.ts.map