diff --git a/packages/core/src/errors/codes.ts b/packages/core/src/errors/codes.ts index 1545868..c7615f1 100644 --- a/packages/core/src/errors/codes.ts +++ b/packages/core/src/errors/codes.ts @@ -50,6 +50,10 @@ export const STELLAR_ERROR_CODES = { // ── Validation ───────────────────────────────────────────────────────── /** Caller-supplied input was invalid or the environment was unsupported. */ VALIDATION_ERROR: "VALIDATION_ERROR", + /** The supplied memo is invalid for its type (too long, wrong format, etc.). */ + INVALID_MEMO: "INVALID_MEMO", + /** The destination requires a memo (SEP-29) but none was supplied. */ + MEMO_REQUIRED: "MEMO_REQUIRED", // ── Network ──────────────────────────────────────────────────────────── /** A transport-level failure (offline, DNS, timeout, CORS, etc.). */ @@ -94,6 +98,8 @@ export const DEFAULT_ERROR_MESSAGES: Record = { "The requested start ledger is older than this RPC server retains. Use a more recent ledger, or an archival RPC provider.", RATE_LIMITED: "Too many requests were sent to Horizon. Please slow down and try again.", VALIDATION_ERROR: "The provided input is invalid.", + INVALID_MEMO: "The memo is invalid. Check the memo type and its length/format.", + MEMO_REQUIRED: "The destination account requires a memo. Add one before sending.", NETWORK_ERROR: "Unable to reach the Stellar network. Check your connection and try again.", UNKNOWN: "An unknown error occurred.", o SEP10_VALIDATION_FAILED: "The SEP-10 authentication challenge failed validation. It may be malformed or tampered with.", diff --git a/packages/core/src/types/index.ts b/packages/core/src/types/index.ts index 1b26a3b..ee9f932 100644 --- a/packages/core/src/types/index.ts +++ b/packages/core/src/types/index.ts @@ -356,6 +356,49 @@ export interface TransactionResult { envelope?: string } +/** + * Fee controls shared by every hook that builds a Horizon transaction. + * + * Stellar prices transactions by auction: each ledger has limited capacity, + * and when more transactions are submitted than fit, the network takes the + * highest bidders and rejects the rest with `tx_insufficient_fee`. + * + * **A fee is a maximum bid, not a charge.** The network only ever takes what + * it needs to include your transaction, so bidding generously costs nothing in + * the common case and is what keeps a transaction landing during congestion. + */ +export interface FeeOptions { + /** + * Explicit fee in stroops, per operation. Wins over everything else. + * + * @example + * send({ to, asset: "XLM", amount: "10", fee: "10000" }) + */ + fee?: string + /** + * Multiplier applied to the network's current base fee, fetched from + * Horizon at build time. Defaults to {@link DEFAULT_FEE_MULTIPLIER}. + * + * @example + * send({ to, asset: "XLM", amount: "10", feeMultiplier: 10 }) + */ + feeMultiplier?: number +} + +/** + * A memo to attach to a payment. A bare string is treated as `MEMO_TEXT`. + * + * - `text`: <= 28 UTF-8 bytes + * - `id`: unsigned 64-bit integer as a string; do not parse it to a JavaScript `number` + * - `hash` / `return`: exactly 64 hexadecimal characters (32 bytes) + */ +export type MemoInput = + | string + | { type: "text"; value: string } + | { type: "id"; value: string } + | { type: "hash"; value: string } + | { type: "return"; value: string } + /** * Options for sending a payment transaction. */ @@ -363,7 +406,7 @@ export interface SendPaymentOptions { to: string asset: Asset amount: string - memo?: string + memo?: MemoInput } /**