import { type TransactionPartialSigner } from '@solana/kit'; import { Method, Store } from 'mppx'; /** * Creates a Solana `charge` method for usage on the server. * * Supports two settlement modes: * * - **Pull mode** (`type="transaction"`, default): The server receives a * signed transaction from the client, broadcasts it to Solana, confirms * it, and verifies the transfer on-chain. When `signer` is provided, * the server co-signs as fee payer before broadcasting. * * - **Push mode** (`type="signature"`): The client has already broadcast * and confirmed the transaction. The server verifies the transfer * on-chain using the signature. * * @example * ```ts * import { Mppx, solana } from '@solana/mpp/server' * * const mppx = Mppx.create({ * methods: [solana.charge({ * recipient: 'RecipientPubkey...', * spl: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', * decimals: 6, * network: 'devnet', * })], * }) * * export async function handler(request: Request) { * const result = await mppx.charge({ amount: '1000000', currency: 'USDC' })(request) * if (result.status === 402) return result.challenge * return result.withReceipt(Response.json({ data: '...' })) * } * ``` */ export declare function charge(parameters: charge.Parameters): Method.Server<{ readonly intent: "charge"; readonly name: "solana"; readonly schema: { readonly credential: { readonly payload: import("zod/mini").ZodMiniObject<{ signature: import("zod/mini").ZodMiniOptional>; transaction: import("zod/mini").ZodMiniOptional>; type: import("zod/mini").ZodMiniString; }, import("zod/v4/core").$strip>; }; readonly request: import("zod/mini").ZodMiniObject<{ amount: import("zod/mini").ZodMiniString; currency: import("zod/mini").ZodMiniString; description: import("zod/mini").ZodMiniOptional>; externalId: import("zod/mini").ZodMiniOptional>; methodDetails: import("zod/mini").ZodMiniObject<{ decimals: import("zod/mini").ZodMiniOptional>; feePayer: import("zod/mini").ZodMiniOptional>; feePayerKey: import("zod/mini").ZodMiniOptional>; network: import("zod/mini").ZodMiniOptional>; recentBlockhash: import("zod/mini").ZodMiniOptional>; splits: import("zod/mini").ZodMiniOptional; ataCreationRequired: import("zod/mini").ZodMiniOptional>; memo: import("zod/mini").ZodMiniOptional>; recipient: import("zod/mini").ZodMiniString; }, import("zod/v4/core").$strip>>>; tokenProgram: import("zod/mini").ZodMiniOptional>; }, import("zod/v4/core").$strip>; recipient: import("zod/mini").ZodMiniString; }, import("zod/v4/core").$strip>; }; }, { readonly currency: string; readonly methodDetails: {}; readonly recipient: ""; }, undefined>; /** * RPC-free pre-broadcast verification of a base64-encoded charge transaction * against the challenge it answers: split-count, address-lookup-table, * compute-budget, transfer, memo, and instruction-allowlist checks, up to the * simulate/send boundary. This is the deterministic half of the charge server * verify path; it runs no HMAC challenge step and reaches no live RPC. * * Exported so the cross-SDK conformance harness can assert the verifier's * accept/reject decision against a fixed transaction. A resolved promise means * the transaction conforms; a rejected promise carries the rejection reason. */ export declare function verifyChargeTransaction(clientTxBase64: string, challenge: ChallengeRequest): Promise; /** The request portion of a challenge, matching the Methods.ts schema. */ export type ChallengeRequest = { amount: string; currency: string; externalId?: string; methodDetails: { decimals?: number; feePayer?: boolean; feePayerKey?: string; network?: string; recentBlockhash?: string; splits?: Array<{ amount: string; ataCreationRequired?: boolean; memo?: string; recipient: string; }>; tokenProgram?: string; }; recipient: string; }; /** * Outcome of the one-shot definitive status check performed after the * confirmation-poll loop times out (audit #3). Pure and testable without a live * RPC. Mirrors the Rust `interpret_post_timeout_status` four-case interpretation: * * - landed cleanly → `{ kind: 'confirmed' }` (recover: treat as success) * - landed but failed on-chain → `{ kind: 'failed' }` (definitive: payment did not go through) * - definitively not on-chain → `{ kind: 'timeout' }` (keep the timeout error) * - the recovery RPC itself failed → `{ kind: 'timeout', detail }` (timeout, with RPC detail for triage) */ export type PostTimeoutStatus = { detail: string; kind: 'failed'; } | { detail?: string; kind: 'timeout'; } | { kind: 'confirmed'; }; export declare function interpretPostTimeoutStatus(status: { err: unknown; } | null, rpcError?: string): PostTimeoutStatus; export declare namespace charge { type Parameters = { /** * Currency identifier. "sol" (lowercase) for native SOL, or a * base58-encoded SPL token mint address. Defaults to "sol". */ currency?: string; /** Token decimals (required when currency is a mint address). */ decimals?: number; /** * Enable HTML payment link pages for browser requests. * When true, 402 responses for requests with `Accept: text/html` * will return an interactive payment page instead of JSON. * * Usage is seamless — just set `html: true` and `result.challenge` * automatically returns HTML for browsers: * * ```ts * const mppx = Mppx.create({ * methods: [solana.charge({ recipient, html: true, ... })], * }) * * // In your handler: * const result = await mppx.charge({ amount: '10000' })(request) * if (result.status === 402) return result.challenge // HTML for browsers, JSON for APIs * ``` */ html?: boolean; /** * Solana network. One of 'mainnet' | 'devnet' | 'localnet'. Defaults to * 'mainnet'. The legacy 'mainnet-beta' spelling is accepted as an alias. * Any other value is rejected at construction. */ network?: 'devnet' | 'localnet' | 'mainnet-beta' | 'mainnet' | (string & {}); /** Base58-encoded recipient public key that receives payments. */ recipient: string; /** Custom RPC URL. Defaults to public RPC for the selected network. */ rpcUrl?: string; /** * Server-side signer for fee sponsorship (feePayer mode). * When provided, the server's public key is included in the challenge * as `feePayerKey`, and the server co-signs the transaction as fee payer * before broadcasting. * * Accepts any TransactionPartialSigner — KeyPairSigner, Keychain SolanaSigner, etc. */ signer?: TransactionPartialSigner; /** Additional payment splits. Same asset as primary payment. Max 8 entries. */ splits?: Array<{ /** Amount in base units (same asset as primary). */ amount: string; /** If true, create the split recipient ATA idempotently before payment. */ ataCreationRequired?: boolean; /** Optional memo (max 566 bytes). */ memo?: string; /** Base58-encoded recipient of this split. */ recipient: string; }>; /** * Pluggable key-value store for consumed-signature tracking (replay prevention). * Defaults to in-memory. Use a persistent store in production. */ store?: Store.Store; /** Token program hint. If omitted, clients fetch the mint owner and fail closed on lookup errors. */ tokenProgram?: string; }; } //# sourceMappingURL=Charge.d.ts.map