From d7fe8b21cb68dc30969312a1c7a5124eec3ca810 Mon Sep 17 00:00:00 2001 From: kingrichie Date: Fri, 28 Aug 2026 20:56:31 +0100 Subject: [PATCH] docs: add comprehensive JSDoc to SplitClient methods --- src/client.ts | 2726 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 2718 insertions(+), 8 deletions(-) diff --git a/src/client.ts b/src/client.ts index 31f7d8c..495b09c 100644 --- a/src/client.ts +++ b/src/client.ts @@ -700,7 +700,19 @@ export class StellarSplitClient extends TypedEventEmitter { // eslint-disable-next-line @typescript-eslint/no-explicit-any private get server(): any { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._resilientRpc) return this._resilientRpc; + /** + * return + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ return ( this._injectedRpcClient ?? this._rpcClient ?? @@ -719,6 +731,12 @@ export class StellarSplitClient extends TypedEventEmitter { * Fire lifecycle hooks for invoice creation. */ private _fireOnCreated(invoice: Invoice): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._hooks?.onCreated) { try { this._hooks.onCreated(invoice); @@ -732,6 +750,12 @@ export class StellarSplitClient extends TypedEventEmitter { * Fire lifecycle hooks for invoice payment. */ private _fireOnPaid(invoice: Invoice, payment: Payment): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._hooks?.onPaid) { try { this._hooks.onPaid(invoice, payment); @@ -745,6 +769,12 @@ export class StellarSplitClient extends TypedEventEmitter { * Fire lifecycle hooks for invoice release. */ private _fireOnReleased(invoice: Invoice): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._hooks?.onReleased) { try { this._hooks.onReleased(invoice); @@ -758,6 +788,12 @@ export class StellarSplitClient extends TypedEventEmitter { * Fire lifecycle hooks for invoice refund. */ private _fireOnRefunded(invoice: Invoice): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._hooks?.onRefunded) { try { this._hooks.onRefunded(invoice); @@ -771,6 +807,12 @@ export class StellarSplitClient extends TypedEventEmitter { * Fire lifecycle hooks for invoice cancellation. */ private _fireOnCancelled(invoice: Invoice): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._hooks?.onCancelled) { try { this._hooks.onCancelled(invoice); @@ -781,7 +823,19 @@ export class StellarSplitClient extends TypedEventEmitter { } constructor(config: StellarSplitClientConfig) { + /** + * super + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ super(); + /** + * validateOrThrow + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ validateOrThrow(config); this.config = config; this._metadataValidator = new InvoiceMetadataValidator( @@ -799,9 +853,21 @@ export class StellarSplitClient extends TypedEventEmitter { config.container?.getWalletAdapter() ?? config.adapter ?? null; // Per-method timeout manager (Issue #1) + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.timeout !== undefined) { this._timeoutManager = new TimeoutManager(config.timeout); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.rpcEndpoints && config.rpcEndpoints.length > 0) { this._rpcLoadBalancer = new RpcLoadBalancer(config.rpcEndpoints, config.rpcLoadBalancer); this._rpcLoadBalancer.on("endpoint:demoted", (event) => this.emit("endpoint:demoted", event)); @@ -815,6 +881,12 @@ export class StellarSplitClient extends TypedEventEmitter { } // Circuit breaker + retry resilience layer (Issue #419) + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.circuitBreaker) { const rpcTarget = this._injectedRpcClient ?? this._rpcClient ?? this._mainServer; this._resilientRpc = new ResilientRpcClient( @@ -827,12 +899,24 @@ export class StellarSplitClient extends TypedEventEmitter { this._resilientRpc.on("circuit:half-open", () => this.emit("circuit:half-open", undefined)); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.advancedCircuitBreaker) { this._advancedCircuitBreaker = new AdvancedCircuitBreaker(config.advancedCircuitBreaker, { warn: (event) => this.emit("circuit_state_change", event), }); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.optimisticCache) { this._optimisticCache = new OptimisticCache(); } @@ -846,6 +930,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Best-effort startup probe; getSorobanFeatures() will retry on demand. }); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if ( !this._rpcClient && Array.isArray(config.rpcUrl) && @@ -859,6 +949,12 @@ export class StellarSplitClient extends TypedEventEmitter { // when an external RPC client hasn't been injected via the DI container. const wantsPool = !this._rpcClient && !this._standby && (config.rpcPoolSize ?? 0) >= 2; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (wantsPool) { this._effectiveRpcPoolSize = Math.min( Math.max(config.rpcPoolSize!, 1), @@ -876,21 +972,75 @@ export class StellarSplitClient extends TypedEventEmitter { this._cache = config.container?.getCacheStore() ?? (config.cache?.enabled ? new SimpleCache(config.cache) : null); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.telemetry) { telemetry.init(config.telemetry); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.signingKeypair) { + /** + * addRequestInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ addRequestInterceptor( + /** + * createRequestSigningInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ createRequestSigningInterceptor(config.signingKeypair), ); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.compression?.enabled) { + /** + * addRequestInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ addRequestInterceptor( + /** + * createCompressionRequestInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ createCompressionRequestInterceptor(config.compression), ); + /** + * addResponseInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ addResponseInterceptor( + /** + * createCompressionResponseInterceptor + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ createCompressionResponseInterceptor(config.compression), ); } @@ -898,25 +1048,55 @@ export class StellarSplitClient extends TypedEventEmitter { // Initialize hooks this._hooks = config.hooks ?? {}; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.retry) { this._retryOptions = config.retry; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.horizonUrl) { this._horizonReader = new HorizonFallbackReader(config.horizonUrl); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.idempotency) { this._idempotency = new IdempotencyManager(config.idempotency); } // WebSocket transport (Issue #377) + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.transport === 'websocket') { this._transportType = 'websocket'; this._activeTransportType = 'websocket'; this._wsTransport = new WebSocketTransport(primaryUrl, config.wsUrl); this._wsTransport.onFallback((event: { from: 'websocket'; to: 'http' }) => { this._activeTransportType = 'http'; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const cb of this._fallbackListeners) { try { cb(event); } catch { } } @@ -927,26 +1107,68 @@ export class StellarSplitClient extends TypedEventEmitter { this._signer = config.signer ?? null; // Admin keypair for admin-only operations + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.adminKeypair) { this._adminKeypair = config.adminKeypair; } + /** + * initHealthDashboard + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ initHealthDashboard(this.server, this._dedup); // Register and initialize config-level plugins + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.plugins) { + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const plugin of config.plugins) { this.registerPlugin(plugin); } } + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const p of this._pluginInstances) { p.onInit?.(this); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.validatePassphrase !== false) { void this._validateStartupConfig(); } // OpenTelemetry instrumentation (opt-in, zero overhead when omitted/disabled). + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (config.otel?.enabled) { const otelExporter = config.otel.exporterUrl ? new OtelExporter({ @@ -982,6 +1204,12 @@ export class StellarSplitClient extends TypedEventEmitter { this.config.networkPassphrase, primaryUrl, ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.mismatch) { throw new PassphraseMismatchError(result.configured, result.reported); } @@ -989,38 +1217,89 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Live network switcher. Migrates state and re-subscribes. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async switchTo(network: "mainnet" | "testnet" | "futurenet"): Promise { const { NetworkSwitcher } = await import("./network/NetworkSwitcher.js"); return NetworkSwitcher.switchTo(network, this); } + /** + * isShutdownInProgress + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ isShutdownInProgress(): boolean { return this._shutdownInProgress; } + /** + * beginGracefulShutdown + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ beginGracefulShutdown(): void { this._shutdownInProgress = true; } + /** + * registerHorizonStreamManager + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ registerHorizonStreamManager(manager: { stop(): void }): () => void { this._managedHorizonStreams.add(manager); + /** + * return + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ return () => { this._managedHorizonStreams.delete(manager); }; } + /** + * getInFlightRequests + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ getInFlightRequests(): InFlightRequestInfo[] { return [...this._inFlightRequests.values()].sort( (left, right) => left.startedAt - right.startedAt, ); } + /** + * waitForInFlightRequests + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async waitForInFlightRequests(): Promise { await Promise.allSettled([...this._inFlightRequestPromises.values()]); } + /** + * finalizeShutdown + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async finalizeShutdown(): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._runtimeShutdownPromise) { return this._runtimeShutdownPromise; } @@ -1028,7 +1307,19 @@ export class StellarSplitClient extends TypedEventEmitter { this.beginGracefulShutdown(); this._runtimeShutdownPromise = (async () => { await this._destroyPlugins(); + /** + * destroySubscriptionManager + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ destroySubscriptionManager(this.config.contractId); + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const manager of this._managedHorizonStreams) { manager.stop(); } @@ -1041,16 +1332,58 @@ export class StellarSplitClient extends TypedEventEmitter { this._pool?.dispose(); this._pool = null; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache && typeof (this._cache as any).persist === "function") { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._cache as any).persist(); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache && typeof (this._cache as any).close === "function") { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._cache as any).close(); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if ( this._rpcClient && + /** + * typeof + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ typeof (this._rpcClient as any).close === "function" ) { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._rpcClient as any).close(); } @@ -1061,9 +1394,21 @@ export class StellarSplitClient extends TypedEventEmitter { } private async _destroyPlugins(): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._pluginsDestroyed) return; this._pluginsDestroyed = true; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const plugin of [...this._pluginInstances].reverse()) { try { await plugin.onDestroy?.(this); @@ -1080,6 +1425,12 @@ export class StellarSplitClient extends TypedEventEmitter { } private _assertWritable(): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._shutdownInProgress) { throw new ShutdownInProgressError(); } @@ -1131,12 +1482,36 @@ export class StellarSplitClient extends TypedEventEmitter { private _instrumentOtel(): void { const proto = Object.getPrototypeOf(this) as object; const self = this as unknown as Record; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const name of Object.getOwnPropertyNames(proto)) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (name === "constructor" || name.startsWith("_")) continue; const descriptor = Object.getOwnPropertyDescriptor(proto, name); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!descriptor || typeof descriptor.value !== "function") continue; const original = descriptor.value as (...args: unknown[]) => unknown; const isAsync = original.constructor.name === "AsyncFunction"; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (isAsync) { self[name] = (...args: unknown[]) => this._withOtelSpanAsync(name, args, () => original.apply(this, args) as Promise); @@ -1150,11 +1525,35 @@ export class StellarSplitClient extends TypedEventEmitter { /** Best-effort `invoice.id` extraction from a method's first argument. */ private _otelInvoiceId(args: unknown[]): string | undefined { const first = args[0]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof first === "string") return first; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (first && typeof first === "object") { const obj = first as Record; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const key of ["invoiceId", "invoice_id", "id"]) { const value = obj[key]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof value === "string") return value; } } @@ -1163,8 +1562,20 @@ export class StellarSplitClient extends TypedEventEmitter { /** Best-effort `tx.hash` extraction from a method's resolved return value. */ private _otelTxHash(result: unknown): string | undefined { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result && typeof result === "object") { const value = (result as Record).txHash; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof value === "string") return value; } return undefined; @@ -1175,8 +1586,20 @@ export class StellarSplitClient extends TypedEventEmitter { const span = this._otel.startSpan(name); span.setAttribute("stellar.network", this.config.networkPassphrase); const rpcUrl = Array.isArray(this.config.rpcUrl) ? this.config.rpcUrl[0] : this.config.rpcUrl; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (rpcUrl) span.setAttribute("rpc.url", rpcUrl); const invoiceId = this._otelInvoiceId(args); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (invoiceId) span.setAttribute("invoice.id", invoiceId); return span; } @@ -1186,6 +1609,12 @@ export class StellarSplitClient extends TypedEventEmitter { args: unknown[], fn: () => Promise, ): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._otelInitPromise) await this._otelInitPromise; const span = this._otelStartSpan(name, args); const startedAt = Date.now(); @@ -1194,6 +1623,12 @@ export class StellarSplitClient extends TypedEventEmitter { const durationMs = Date.now() - startedAt; span.setAttribute("rpc.duration_ms", durationMs); const txHash = this._otelTxHash(result); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (txHash) span.setAttribute("tx.hash", txHash); this._otel.recordRpcCall(durationMs, { method: name }); span.end(); @@ -1217,6 +1652,12 @@ export class StellarSplitClient extends TypedEventEmitter { const durationMs = Date.now() - startedAt; span.setAttribute("rpc.duration_ms", durationMs); const txHash = this._otelTxHash(result); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (txHash) span.setAttribute("tx.hash", txHash); this._otel.recordRpcCall(durationMs, { method: name }); span.end(); @@ -1242,6 +1683,12 @@ export class StellarSplitClient extends TypedEventEmitter { this.config.networkPassphrase, primaryUrl ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.mismatch) { throw new PassphraseMismatchError(result.configured, result.reported); } @@ -1250,6 +1697,8 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Live network switcher. Migrates state and re-subscribes. * @param network - 'mainnet' | 'testnet' | 'futurenet' + * @returns The result of the method. + * @throws {Error} If the method fails. */ public async switchTo(network: 'mainnet' | 'testnet' | 'futurenet'): Promise { const { NetworkSwitcher } = await import("./network/NetworkSwitcher.js"); @@ -1265,19 +1714,40 @@ export class StellarSplitClient extends TypedEventEmitter { * startup and re-probed automatically after the detector's staleness * window (default 1 hour). Emits `protocolUpgradeDetected` on the * underlying detector when a re-probe observes a version change. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getSorobanFeatures(): Promise { return this._sorobanFeatureDetector.detect(); } + /** + * healthCheck + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async healthCheck(): Promise { const start = Date.now(); try { return await Promise.race([ this._doHealthCheck(start), new Promise((_, reject) => + /** + * setTimeout + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ setTimeout( () => + /** + * reject + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ reject( new HealthCheckTimeoutError( "Health check timed out after 5000ms", @@ -1288,6 +1758,12 @@ export class StellarSplitClient extends TypedEventEmitter { ), ]); } catch (e: any) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (e instanceof HealthCheckTimeoutError) { throw e; } @@ -1315,6 +1791,12 @@ export class StellarSplitClient extends TypedEventEmitter { await this.server.getContractWasmByContractId(this.config.contractId); contractDeployed = true; } catch (err: any) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!err.message?.includes("Could not obtain contract hash")) { // If we get here, it might be deployed but we couldn't fetch the wasm, // or it threw some other error. We'll conservatively say true if it's @@ -1339,9 +1821,23 @@ export class StellarSplitClient extends TypedEventEmitter { * Enable or disable request batching for read methods (getInvoice, getPaymentHistory, getInvoiceExt). * Disabled by default — opt-in to batch concurrent RPC calls within a 10 ms window. * @param enabled - Pass `true` to enable batching, `false` to disable. + * @returns The result of the method. + * @throws {Error} If the method fails. */ setBatchingEnabled(enabled: boolean): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (enabled) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._batcher) { this._batcher = new BatchedRpcClient({ fetchInvoice: (id: string) => this._fetchInvoice(id), @@ -1359,9 +1855,23 @@ export class StellarSplitClient extends TypedEventEmitter { * Manually invalidate cache entries. * @param method Optional method name to invalidate. * @param args Optional arguments array to invalidate a specific call. + * @returns The result of the method. + * @throws {Error} If the method fails. */ public invalidateCache(method?: string, args?: any[]): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof (this._cache as any).invalidate === "function") { (this._cache as any).invalidate(method, args); } @@ -1371,9 +1881,23 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Get cache statistics. * @returns Cache stats including hits, misses, size, and keys. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ public getCacheStats(): import("./cache.js").CacheStats | null { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache && typeof (this._cache as any).getStats === "function") { + /** + * return + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ return (this._cache as any).getStats(); } return null; @@ -1393,6 +1917,12 @@ export class StellarSplitClient extends TypedEventEmitter { this.config.networkPassphrase, primaryUrl, ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.mismatch) { throw new PassphraseMismatchError(result.configured, result.reported); } @@ -1401,6 +1931,8 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Live network switcher. Migrates state and re-subscribes. * @param network - 'mainnet' | 'testnet' | 'futurenet' + * @returns The result of the method. + * @throws {Error} If the method fails. */ public async switchTo( network: "mainnet" | "testnet" | "futurenet", @@ -1415,6 +1947,12 @@ export class StellarSplitClient extends TypedEventEmitter { success: boolean, durationMs: number, ): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._auditLogger) return; this._auditLogger.log({ timestamp: Date.now(), @@ -1484,6 +2022,12 @@ export class StellarSplitClient extends TypedEventEmitter { const timeoutMs = opts?.timeout ?? this._timeoutManager?.resolveTimeout(method); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (timeoutMs !== undefined) { return withTimeout(() => run(), timeoutMs, method); } @@ -1497,8 +2041,17 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Register a plugin that extends this client instance. * Throws if a plugin with the same name has already been registered. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ registerPlugin(plugin: StellarSplitPlugin): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._plugins.has(plugin.name)) { throw new PluginAlreadyRegisteredError(plugin.name); } @@ -1507,17 +2060,29 @@ export class StellarSplitClient extends TypedEventEmitter { plugin.install?.(this); } - /** Register a middleware plugin (interceptor-style). */ + /** Register a middleware plugin (interceptor-style). + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ use(plugin: SdkPlugin): void { this._pluginRegistry.use(plugin); } - /** Deregister a middleware plugin by name. */ + /** Deregister a middleware plugin by name. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ removePlugin(name: string): void { this._pluginRegistry.removePlugin(name); } - /** Return the names of all active middleware plugins. */ + /** Return the names of all active middleware plugins. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ getPlugins(): string[] { return this._pluginRegistry.getPlugins(); } @@ -1550,6 +2115,8 @@ export class StellarSplitClient extends TypedEventEmitter { * } * }); * ``` + * @returns The result of the method. + * @throws {Error} If the method fails. */ setTelemetryHooks(hooks: TelemetryHooks): void { this._telemetryHookManager.setHooks(hooks); @@ -1557,6 +2124,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Remove all registered telemetry hooks. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ clearTelemetryHooks(): void { this._telemetryHookManager.clearHooks(); @@ -1570,6 +2140,9 @@ export class StellarSplitClient extends TypedEventEmitter { * Returns the resolved timeout (in ms) for each known SDK method. * Reflects both the `default` timeout and any per-method overrides. * Returns an empty object when no `timeout` option was set at construction. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getTimeoutConfig(): Record { return this._timeoutManager?.getTimeoutConfig() ?? {}; @@ -1585,6 +2158,9 @@ export class StellarSplitClient extends TypedEventEmitter { * * @example * sdk.setDefaultTraceIdGenerator(() => opentelemetry.trace.getActiveSpan()?.spanContext().traceId ?? crypto.randomUUID()); + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ setDefaultTraceIdGenerator(generator: () => string): void { this._traceIdManager.setGenerator(generator); @@ -1598,12 +2174,19 @@ export class StellarSplitClient extends TypedEventEmitter { * Dispute an invoice by ID. * @param invoiceId - The ID of the invoice to dispute. * @returns The dispute ID and transaction hash. + * @throws {Error} If the method fails. */ async disputeInvoice(invoiceId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "dispute_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); // Assuming the creator is the one calling dispute @@ -1622,14 +2205,33 @@ export class StellarSplitClient extends TypedEventEmitter { * Submit an arbiter's vote for a dispute. * @param vote - The arbiter vote parameters. * @returns The dispute ID and transaction hash. + * @throws {Error} If the method fails. */ async submitArbiterVote(vote: ArbiterVote): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "submit_arbiter_vote", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(vote.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(vote.arbiter, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(vote.approve, { type: "bool" }), ); const result = await this._submitTx(vote.arbiter, operation); @@ -1651,6 +2253,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The ID of the invoice to resolve dispute for. * @param arbiter - The Stellar address of the arbiter (must sign). * @returns The dispute ID and transaction hash. + * @throws {Error} If the method fails. */ async resolveDispute( invoiceId: string, @@ -1660,6 +2263,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "resolve_dispute", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(arbiter, operation); @@ -1676,12 +2285,19 @@ export class StellarSplitClient extends TypedEventEmitter { * Raise a dispute on an invoice. * @param invoiceId - The ID of the invoice to dispute. * @returns The dispute ID and transaction hash. + * @throws {Error} If the method fails. */ async raiseDispute(invoiceId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "dispute_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(this.config.contractId, operation); @@ -1698,6 +2314,7 @@ export class StellarSplitClient extends TypedEventEmitter { * Get the dispute status for an invoice. * @param invoiceId - The ID of the invoice to query. * @returns The dispute status. + * @throws {Error} If the method fails. */ async getDisputeStatus(invoiceId: string): Promise { return this._withCache("getDisputeStatus", [invoiceId], async () => { @@ -1705,6 +2322,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "get_dispute_status", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const raw = (await this._simulateView(operation)) as Record< @@ -1744,13 +2367,32 @@ export class StellarSplitClient extends TypedEventEmitter { * Submit a vote on a disputed invoice (arbitrator only). * @param params - Vote parameters (invoiceId, arbiter address, approve boolean) * @returns Transaction result with hash + * @throws {Error} If the method fails. */ async voteDispute(params: ArbiterVote): Promise<{ txHash: string }> { return this._withTelemetry("voteDispute", params as unknown as Record, async () => { const operation = this.contract.call( "vote_dispute", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.arbiter, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.approve, { type: "bool" }), ); @@ -1765,6 +2407,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param evidenceCid - IPFS CID of the evidence file * @param fileName - Optional file name for reference * @returns Transaction result with hash + * @throws {Error} If the method fails. */ async addDisputeEvidence( invoiceId: string, @@ -1774,6 +2417,12 @@ export class StellarSplitClient extends TypedEventEmitter { return this._withTelemetry( "addDisputeEvidence", { invoiceId, evidenceCid, fileName } as Record, + /** + * async + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async () => { // Note: This assumes the contract has an add_dispute_evidence method // If not, this would need to be stored off-chain or via memo field @@ -1781,7 +2430,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "add_dispute_note", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(note, { type: "string" }), ); @@ -1802,6 +2463,7 @@ export class StellarSplitClient extends TypedEventEmitter { * This is used by useInvoiceStream hook for live updates. * @param path - The SSE path (e.g., "/invoice/123") * @returns SSE endpoint URL + * @throws {Error} If the method fails. */ getSSEEndpoint(path: string): string { // This would be configured based on your backend SSE server @@ -1826,8 +2488,15 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param xdrBase64 - Base64-encoded transaction envelope XDR. * @returns A parsed envelope, or a notice when debug mode is disabled. + * @throws {Error} If the method fails. */ parseXdrEnvelope(xdrBase64: string): ParsedEnvelope | { error: string } { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this.config.debug) { return { error: "Debug mode is disabled. Set config.debug = true to enable XDR parsing." }; } @@ -1842,6 +2511,10 @@ export class StellarSplitClient extends TypedEventEmitter { * Create a new on-chain invoice. * * @returns The new invoice ID and the transaction hash. + * @example + * const result = await client.createInvoice({ /* params */ }); + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async createInvoice( params: CreateInvoiceParams, @@ -1853,11 +2526,29 @@ export class StellarSplitClient extends TypedEventEmitter { token: params.token, deadline: params.deadline, }, + /** + * async + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async () => { const startTime = Date.now(); params = this._pluginRegistry.runBeforeCall("createInvoice", params); try { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this.config.payloadGuard) { + /** + * validateInvoicePayload + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ validateInvoicePayload(params, this.config.payloadGuard); } @@ -1865,8 +2556,20 @@ export class StellarSplitClient extends TypedEventEmitter { // Pre-submission split ratio validation: catch malformed ratio arrays // early (ratio-sum violations, negative shares, duplicates, zeros). + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.recipients.length > 1) { const total = params.recipients.reduce((s, r) => s + r.amount, 0n); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (total > 0n) { const splitConfig: SplitConfig = { shares: params.recipients.map((r) => ({ @@ -1874,11 +2577,23 @@ export class StellarSplitClient extends TypedEventEmitter { share: Number(r.amount) / Number(total), })), }; + /** + * validateSplitRatiosOrThrow + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ validateSplitRatiosOrThrow(splitConfig); } } const gate = await this.checkNftGate(params.creator); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (gate.gated && !gate.hasNft) { throw new NftGateRequiredError( params.creator, @@ -1887,18 +2602,48 @@ export class StellarSplitClient extends TypedEventEmitter { } const recipientAddresses = params.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.address, { type: "address" }), ); const recipientAmounts = params.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.amount, { type: "i128" }), ); const operation = this.contract.call( "create_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.creator, { type: "address" }), xdr.ScVal.scvVec(recipientAddresses), xdr.ScVal.scvVec(recipientAmounts), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.token, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.deadline, { type: "u64" }), ); @@ -1962,6 +2707,12 @@ export class StellarSplitClient extends TypedEventEmitter { // ------------------------------------------------------------------- // Cloneability pre-flight validation (#486) // ------------------------------------------------------------------- + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!overrides.skipValidation) { const rpcUrl = Array.isArray(this.config.rpcUrl) ? this.config.rpcUrl[0] @@ -1971,6 +2722,12 @@ export class StellarSplitClient extends TypedEventEmitter { rpcUrl, }); const report = await validator.validate(sourceInvoice); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!report.cloneable) { throw new InvoiceNotCloneableError(report); } @@ -1978,6 +2735,12 @@ export class StellarSplitClient extends TypedEventEmitter { const mapEntries: xdr.ScMapEntry[] = []; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (overrides.newDeadline !== undefined) { mapEntries.push( new xdr.ScMapEntry({ @@ -1988,6 +2751,12 @@ export class StellarSplitClient extends TypedEventEmitter { }), ); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (overrides.newAmounts !== undefined) { mapEntries.push( new xdr.ScMapEntry({ @@ -1998,12 +2767,24 @@ export class StellarSplitClient extends TypedEventEmitter { }), ); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (overrides.newRecipients !== undefined) { mapEntries.push( new xdr.ScMapEntry({ key: nativeToScVal("new_recipients", { type: "symbol" }) as xdr.ScVal, val: xdr.ScVal.scvVec( overrides.newRecipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r, { type: "address" }), ), ) as xdr.ScVal, @@ -2021,6 +2802,12 @@ export class StellarSplitClient extends TypedEventEmitter { val: xdr.ScVal.scvVec( overrides.newOverflowBehavior !== undefined ? [ + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(overrides.newOverflowBehavior, { type: "symbol", }) as xdr.ScVal, @@ -2031,6 +2818,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); const args: xdr.ScVal[] = [ + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(sourceId), { type: "u64" }), xdr.ScVal.scvMap(mapEntries), ]; @@ -2049,8 +2842,20 @@ export class StellarSplitClient extends TypedEventEmitter { const id = scValToNative(result.returnValue).toString() as string; newInvoiceId = id; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache) { const cloneDepth = + /** + * typeof + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ typeof (sourceInvoice as unknown as Record) .cloneDepth === "number" ? ((sourceInvoice as unknown as Record) @@ -2076,10 +2881,22 @@ export class StellarSplitClient extends TypedEventEmitter { } catch (error) { telemetry.recordMethod("cloneInvoice", false, Date.now() - startTime); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (cacheWritten && newInvoiceId && this._cache) { this._cache.invalidate(newInvoiceId); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (error instanceof Error && error.message.includes("not found")) { throw new InvoiceNotFoundError(sourceId); } @@ -2091,16 +2908,32 @@ export class StellarSplitClient extends TypedEventEmitter { * Pay toward an invoice. * * @returns The transaction hash. + * @example + * const result = await client.pay({ /* params */ }); + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async pay(params: PayParams): Promise { const startTime = Date.now(); params = this._pluginRegistry.runBeforeCall("pay", params); let optimistic: { commit: CommitFn; rollback: RollbackFn } | null = null; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._optimisticCache) { const current = this._cache?.get(`getInvoice:${JSON.stringify([params.invoiceId])}`) as | Invoice | undefined; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (current) { const predicted = getOptimisticInvoice(current, { payer: params.payer, @@ -2114,9 +2947,33 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "pay", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.payer, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.amount, { type: "i128" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.donateOnFailure ?? false, { type: "bool" }), ); @@ -2155,6 +3012,9 @@ export class StellarSplitClient extends TypedEventEmitter { * Preflight checks before submitting a payment. * * Verifies the invoice is pending, not expired, and the payer has trustline/balance. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async preflightCheck(params: { invoiceId: string; @@ -2166,6 +3026,12 @@ export class StellarSplitClient extends TypedEventEmitter { payerReadiness: import("./preflightChecker.js").PayerReadinessResult; }> { const invoice = await this.getInvoice(params.invoiceId); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (invoice.status !== "Pending") { throw new InvoiceNotPendingError(params.invoiceId); } @@ -2178,6 +3044,12 @@ export class StellarSplitClient extends TypedEventEmitter { getAccount: async (address: string) => { const normalizedBalances = await this.getAccountBalances(address); const balances = normalizedBalances.map((nb) => { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (nb.asset === "native") { return { balance: nb.balance, @@ -2215,11 +3087,20 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Fetch a payment receipt for an invoice and payer. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getReceipt(invoiceId: string, payerAddress: string): Promise { return generatePaymentReceipt(this, invoiceId, payerAddress); } + /** + * submitPayment + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async submitPayment(params: { invoiceId: string; payer: string; @@ -2230,15 +3111,33 @@ export class StellarSplitClient extends TypedEventEmitter { expectedContentHash?: string; }): Promise { // Verify invoice content hash if provided (integrity check) + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.expectedContentHash) { const invoice = await this.getInvoice(params.invoiceId); const valid = await verifyInvoiceHash(invoice, params.expectedContentHash); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!valid) { const computed = await hashInvoice(invoice); throw new InvoiceIntegrityError(params.invoiceId, params.expectedContentHash, computed); } } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!params.waterfallPlan) { return this.pay({ payer: params.payer, @@ -2251,6 +3150,12 @@ export class StellarSplitClient extends TypedEventEmitter { const plan = params.waterfallPlan; const allowPartial = params.allowPartial ?? plan.allowPartial ?? false; const hasUnsatisfiedTier = plan.steps.some((step) => !step.satisfied); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (hasUnsatisfiedTier && !allowPartial) { throw new WaterfallInsufficientFundsError(params.invoiceId, { unsatisfiedTiers: plan.steps.filter((s) => !s.satisfied).map((s) => s.recipient), @@ -2258,6 +3163,12 @@ export class StellarSplitClient extends TypedEventEmitter { } const fundedSteps = plan.steps.filter((step) => step.satisfied && step.amount > 0n); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (fundedSteps.length === 0) { throw new WaterfallInsufficientFundsError(params.invoiceId); } @@ -2265,9 +3176,33 @@ export class StellarSplitClient extends TypedEventEmitter { const operations = fundedSteps.map((step) => this.contract.call( "pay", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.payer, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(step.amount, { type: "i128" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.donateOnFailure ?? false, { type: "bool" }), ), ); @@ -2303,6 +3238,12 @@ export class StellarSplitClient extends TypedEventEmitter { fee: BASE_FEE, networkPassphrase: this.config.networkPassphrase, }); + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const operation of operations) { builder.addOperation(operation); } @@ -2317,6 +3258,12 @@ export class StellarSplitClient extends TypedEventEmitter { sourceAddress: string, ): Promise<{ txHash: string; returnValue: xdr.ScVal }> { const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw parseSorobanError(simResult.error); } @@ -2329,6 +3276,12 @@ export class StellarSplitClient extends TypedEventEmitter { const sendResult = await this.server.sendTransaction( TransactionBuilder.fromXDR(signedXdr, this.config.networkPassphrase), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Waterfall transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -2340,11 +3293,23 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while (getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20) { await new Promise((r) => setTimeout(r, 1500)); getResult = await this.server.getTransaction(txHash); attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -2359,19 +3324,38 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param params - Array of invoice creation parameters (1-5 items) * @returns All created invoice IDs and the transaction hash + * @throws {Error} If the method fails. */ async batchCreateInvoices( params: CreateInvoiceParams[], ): Promise<{ invoiceIds: string[]; txHash: string }> { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.length === 0 || params.length > 5) { throw new InvalidBatchSizeError("1-5 items", params.length); } const invoiceParams = params.map((p) => { const recipientAddresses = p.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.address, { type: "address" }), ); const recipientAmounts = p.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.amount, { type: "i128" }), ); @@ -2407,9 +3391,21 @@ export class StellarSplitClient extends TypedEventEmitter { ); const firstParam = params[0]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!firstParam) throw new InvalidBatchSizeError("non-empty array", 0); const result = await this._submitTx(firstParam.creator, operation); const invoiceIds = ( + /** + * scValToNative + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ scValToNative(result.returnValue) as (string | number)[] ).map((id) => id.toString()); return { invoiceIds, txHash: result.txHash }; @@ -2423,12 +3419,24 @@ export class StellarSplitClient extends TypedEventEmitter { args: any[], fetcher: () => Promise, ): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._cache) { return fetcher(); } const key = `${methodName}:${JSON.stringify(args)}`; const cached = this._cache.get(key); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (cached !== undefined) { return cached as T; } @@ -2445,12 +3453,23 @@ export class StellarSplitClient extends TypedEventEmitter { * with a `tokenGateController`, the caller's token balance is verified before * the invoice data is returned. Throws {@link TokenGateAccessDeniedError} when * the caller does not meet the balance requirement (and `strict !== false`). + * @example + * const result = await client.getInvoice({ /* params */ }); + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getInvoice( invoiceId: string, opts?: { retry?: PerMethodRetryOptions; dedupe?: boolean; traceId?: string; timeout?: number } ): Promise { const optimistic = this._optimisticCache?.get(invoiceId); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (optimistic !== undefined) { return optimistic; } @@ -2466,6 +3485,12 @@ export class StellarSplitClient extends TypedEventEmitter { opts?.retry ?? (this._retryOptions ? {} : undefined); let invoice: Invoice; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._retryOptions && effectiveRetry !== undefined) { invoice = await executeWithRetry( () => @@ -2480,6 +3505,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Token-gate access check: verify caller balance when policy is set. const gateController = this.config.tokenGateController; const callerId = this.config.callerAccountId; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (gateController && callerId && invoice.accessPolicy) { await gateController.verify(callerId, invoice.accessPolicy); } @@ -2491,6 +3522,8 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Returns deduplication statistics for observability. * @returns { deduped: number, total: number } — deduped is how many calls were short-circuited. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ getDedupStats(): { deduped: number; total: number } { return this._dedup.getDedupStats(); @@ -2523,11 +3556,20 @@ export class StellarSplitClient extends TypedEventEmitter { * * When optimisticCache is enabled, the result is written into it * immediately so subsequent getInvoice() calls see the new status. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async updateInvoiceStatus(invoiceId: string, to: InvoiceStatus): Promise { const current = await this.getInvoice(invoiceId); const updated = this._stateMachine.transition(current, to); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._optimisticCache) { this._optimisticCache.applyOptimistic(invoiceId, updated, current).commit(); } @@ -2550,6 +3592,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param updates - Partial invoice fields to apply (merged over the current state). * @param changedBy - The Stellar address responsible for the change. * @returns The updated invoice after all mutations are applied. + * @throws {Error} If the method fails. */ async updateInvoice( invoiceId: string, @@ -2563,6 +3606,12 @@ export class StellarSplitClient extends TypedEventEmitter { | import("./invoiceVersionTracker.js").InvoiceVersionTracker | undefined; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (tracker) { await tracker.record(invoiceId, current, changedBy); } @@ -2571,6 +3620,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Write the updated invoice back into the optimistic cache so subsequent // getInvoice() calls see the new state immediately. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._optimisticCache) { this._optimisticCache.applyOptimistic(invoiceId, updated, current).commit(); } else if (this._cache) { @@ -2591,6 +3646,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param handler - Called with each typed InvoiceEvent as it arrives. * @param opts - Optional per-subscription overrides (poll interval, backoff, storage). * @returns Unsubscribe function scoped to this handler only. + * @throws {Error} If the method fails. */ subscribe( invoiceId: string, @@ -2605,8 +3661,17 @@ export class StellarSplitClient extends TypedEventEmitter { * Stop receiving InvoiceEvents for an invoice ID. Removes every handler * registered via `subscribe()` for that invoice and releases the * underlying poll timer. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ unsubscribe(invoiceId: string): void { + /** + * getSubscriptionManager + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ getSubscriptionManager(this.server, this.config.contractId).unsubscribe(invoiceId); } @@ -2623,8 +3688,17 @@ export class StellarSplitClient extends TypedEventEmitter { /** * The rollback coordinator tracking split-payment leg checkpoints created * by `submitPayment`'s waterfall path. Lazily instantiated on first use. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getRollbackCoordinator(): RollbackCoordinator { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._rollbackCoordinator) { this._rollbackCoordinator = new RollbackCoordinator(this._idempotency ?? undefined); } @@ -2648,6 +3722,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Returns the current circuit breaker state, or null if no circuit breaker * is configured. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getCircuitBreakerState(): import("./circuitBreaker.js").CircuitBreakerState | null { return this._resilientRpc?.circuitBreaker?.state ?? null; @@ -2656,6 +3733,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Returns the number of consecutive failures recorded by the circuit breaker, * or null if no circuit breaker is configured. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getCircuitBreakerFailureCount(): number | null { return this._resilientRpc?.circuitBreaker?.failureCount ?? null; @@ -2664,6 +3744,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Manually reset the circuit breaker to the CLOSED state. * No-op if no circuit breaker is configured. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ resetCircuitBreaker(): void { this._resilientRpc?.circuitBreaker?.reset(); @@ -2681,6 +3764,12 @@ export class StellarSplitClient extends TypedEventEmitter { const fetchFn = async (): Promise => { const operation = this.contract.call( "get_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); @@ -2705,6 +3794,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw parseSorobanError(simResult.error, invoiceId); } @@ -2712,6 +3807,12 @@ export class StellarSplitClient extends TypedEventEmitter { const returnVal = ( simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse ).result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) throw new InvoiceNotFoundError(invoiceId); const invoice = this._parseInvoice(invoiceId, scValToNative(returnVal)); @@ -2721,6 +3822,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { let invoice: Invoice; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._degradation) { const result = await this._degradation.wrapRead(invoiceId, fetchFn); invoice = result.data; @@ -2734,6 +3841,12 @@ export class StellarSplitClient extends TypedEventEmitter { result: invoice, durationMs, }); + /** + * recordCall + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ recordCall(true); return invoice; } catch (error) { @@ -2744,6 +3857,12 @@ export class StellarSplitClient extends TypedEventEmitter { result: undefined, durationMs, }); + /** + * recordCall + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ recordCall(false); throw error; } @@ -2752,6 +3871,8 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Check invoice compliance against built-in and configured rules. * @param invoiceId - Invoice ID to validate + * @returns The result of the method. + * @throws {Error} If the method fails. */ async checkCompliance( invoiceId: string, @@ -2764,6 +3885,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Fetch all payments for an invoice. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getPayments(invoiceId: string): Promise { const startTime = Date.now(); @@ -2784,6 +3908,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param proof - CompletionProof object from the contract. * @returns { valid: boolean, reason?: string } + * @throws {Error} If the method fails. */ verifyCompletionProof(proof: CompletionProof): { valid: boolean; @@ -2794,6 +3919,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Reconcile an invoice's reported funded amount with its payment records and historical payment events. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async reconcilePayments( invoiceId: string, @@ -2816,6 +3944,12 @@ export class StellarSplitClient extends TypedEventEmitter { const rawAmount = raw.amount; let amount: bigint; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof rawAmount === "bigint") { amount = rawAmount; } else if (typeof rawAmount === "number") { @@ -2874,11 +4008,20 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Generate a typed receipt for a released invoice. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async generateReceipt(invoiceId: string): Promise { const startTime = Date.now(); try { const invoice = await this.getInvoice(invoiceId); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (invoice.status !== "Released") { throw new InvoiceNotReleasedError(invoiceId, invoice.status); } @@ -2911,6 +4054,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceId - The invoice ID to snapshot. * @returns An immutable, timestamped snapshot object. + * @throws {Error} If the method fails. */ async snapshotInvoice(invoiceId: string): Promise { const invoice = await this.getInvoice(invoiceId); @@ -2922,6 +4066,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param ids - Invoice IDs to resolve. * @returns Results in the same order as the input IDs. + * @throws {Error} If the method fails. */ async resolveBatch(ids: string[]): Promise { const settled = await Promise.allSettled( @@ -2929,6 +4074,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); return settled.map((result, i) => { const invoiceId = ids[i]!; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.status === "fulfilled") { return { invoiceId, success: true as const, invoice: result.value }; } @@ -2960,12 +4111,19 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param creatorAddress - The Stellar address of the invoice creator. * @returns Gate status including whether gating applies and NFT ownership. + * @throws {Error} If the method fails. */ async checkNftGate(creatorAddress: string): Promise { return this._withCache("checkNftGate", [creatorAddress], async () => { const startTime = Date.now(); const now = Date.now(); const cached = this._nftGateCache.get(creatorAddress); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (cached && now - cached.timestamp < NFT_GATE_CACHE_TTL_MS) { telemetry.recordMethod("checkNftGate", true, Date.now() - startTime); return cached.result; @@ -2974,6 +4132,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "check_nft_gate", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creatorAddress, { type: "address" }), ); @@ -2996,13 +4160,20 @@ export class StellarSplitClient extends TypedEventEmitter { }); } - /** Clears the NFT gate status cache (useful for testing). */ + /** Clears the NFT gate status cache (useful for testing). + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ clearNftGateCache(): void { this._nftGateCache.clear(); } /** * Resolves the forward chain for an invoice. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getForwardChain( invoiceId: string, @@ -3016,10 +4187,28 @@ export class StellarSplitClient extends TypedEventEmitter { let currentId: string | undefined = invoiceId; let depth = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while (currentId) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (depth >= 10) { throw new ForwardChainTooDeepError(10, currentId); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (visited.has(currentId)) { throw new CircularForwardChainError(currentId); } @@ -3041,9 +4230,18 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Gracefully shutdown the SDK client, flush pending operations, and close internal resources. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async shutdown(): Promise { // Tear down plugins in reverse registration order + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const p of this._pluginInstances.reverse()) { try { await p.onDestroy?.(this); @@ -3069,16 +4267,58 @@ export class StellarSplitClient extends TypedEventEmitter { this._pool?.dispose(); this._pool = null; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache && typeof (this._cache as any).persist === "function") { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._cache as any).persist(); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._cache && typeof (this._cache as any).close === "function") { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._cache as any).close(); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if ( this._rpcClient && + /** + * typeof + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ typeof (this._rpcClient as any).close === "function" ) { + /** + * await + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ await (this._rpcClient as any).close(); } @@ -3088,11 +4328,20 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Cancel multiple invoices in parallel without aborting on individual failures. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async bulkCancel(ids: string[]): Promise { return this._executeBulkInvoiceAction(ids, (invoiceId) => { const operation = this.contract.call( "cancel_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); return this._submitTx(this.config.contractId, operation); @@ -3101,11 +4350,20 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Archive multiple invoices in parallel without aborting on individual failures. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async bulkArchive(ids: string[]): Promise { return this._executeBulkInvoiceAction(ids, (invoiceId) => { const operation = this.contract.call( "archive_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); return this._submitTx(this.config.contractId, operation); @@ -3114,6 +4372,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Export multiple invoices in parallel and return formatted results by invoice ID. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async bulkExport( ids: string[], @@ -3128,6 +4389,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); return settled.reduce>((acc, result, index) => { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.status === "fulfilled") { acc[ids[index]!] = result.value.data; } @@ -3144,6 +4411,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); return settled.map((result, index) => { const invoiceId = ids[index]!; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.status === "fulfilled") { return { invoiceId, success: true }; } @@ -3162,6 +4435,8 @@ export class StellarSplitClient extends TypedEventEmitter { * Save an invoice template for reuse. * * @returns The transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async saveTemplate( creator: string, @@ -3170,18 +4445,48 @@ export class StellarSplitClient extends TypedEventEmitter { const startTime = Date.now(); try { const recipientAddresses = template.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.address, { type: "address" }), ); const recipientAmounts = template.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.amount, { type: "i128" }), ); const operation = this.contract.call( "save_template", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(template.name, { type: "string" }), xdr.ScVal.scvVec(recipientAddresses), xdr.ScVal.scvVec(recipientAmounts), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(template.token, { type: "address" }), ); @@ -3198,6 +4503,8 @@ export class StellarSplitClient extends TypedEventEmitter { * Create an invoice from a saved template. * * @returns The new invoice ID and the transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async createFromTemplate( creator: string, @@ -3208,8 +4515,26 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "create_from_template", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(templateName, { type: "string" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(deadline, { type: "u64" }), ); @@ -3233,6 +4558,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * List all template names for a creator. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async listTemplates(creator: string): Promise { return this._withCache("listTemplates", [creator], async () => { @@ -3240,6 +4568,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "list_templates", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), ); @@ -3256,6 +4590,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Get all recurring invoices for a creator. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getRecurringInvoices(creator: string): Promise { const startTime = Date.now(); @@ -3285,13 +4622,27 @@ export class StellarSplitClient extends TypedEventEmitter { * Cancel a recurring invoice. * * @returns The transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async cancelRecurring(invoiceId: string, creator: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "cancel_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), ); @@ -3308,6 +4659,8 @@ export class StellarSplitClient extends TypedEventEmitter { * Update amounts for a recurring invoice. * * @returns The transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async updateRecurringAmount( invoiceId: string, @@ -3320,7 +4673,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "update_recurring_amount", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), xdr.ScVal.scvVec(amountVals), ); @@ -3348,6 +4713,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param creator - Stellar address of the creator. * @param options - Optional pagination options (cursor, limit). Default page size is 20. * @returns A page of invoice IDs with a nextCursor for subsequent pages. + * @throws {Error} If the method fails. */ async getInvoicesByCreator( creator: string, @@ -3356,11 +4722,23 @@ export class StellarSplitClient extends TypedEventEmitter { return this._withCache( "getInvoicesByCreator", [creator, options], + /** + * async + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async () => { const limit = options.limit ?? 20; const operation = this.contract.call( "get_invoices_by_creator", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), ); @@ -3388,6 +4766,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param recipient - Stellar address of the recipient. * @param options - Optional pagination options (cursor, limit). Default page size is 20. * @returns A page of invoice IDs with a nextCursor for subsequent pages. + * @throws {Error} If the method fails. */ async getInvoicesByRecipient( recipient: string, @@ -3396,11 +4775,23 @@ export class StellarSplitClient extends TypedEventEmitter { return this._withCache( "getInvoicesByRecipient", [recipient, options], + /** + * async + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async () => { const limit = options.limit ?? 20; const operation = this.contract.call( "get_invoices_by_recipient", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(recipient, { type: "address" }), ); @@ -3419,6 +4810,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed: ${simResult.error}`, @@ -3430,6 +4827,12 @@ export class StellarSplitClient extends TypedEventEmitter { const returnVal = ( simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse ).result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) throw new NoReturnValueError("getInvoicesByRecipient"); const raw = scValToNative(returnVal); @@ -3452,6 +4855,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Check the health of the RPC endpoint. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async checkRPCHealth(): Promise { return checkRPCHealth(this.server); @@ -3461,17 +4867,31 @@ export class StellarSplitClient extends TypedEventEmitter { * Create a group of linked invoices. * * @returns The new group ID and transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async createGroup( creator: string, invoiceIds: string[], ): Promise<{ groupId: string; txHash: string }> { const invoiceIdsBigInt = invoiceIds.map((id) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(id), { type: "u64" }), ); const operation = this.contract.call( "create_invoice_group", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), xdr.ScVal.scvVec(invoiceIdsBigInt), ); @@ -3483,10 +4903,19 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Get the status of an invoice group. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getGroupStatus(groupId: string): Promise { const operation = this.contract.call( "get_invoice_group", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(groupId), { type: "u64" }), ); @@ -3497,6 +4926,12 @@ export class StellarSplitClient extends TypedEventEmitter { return { groupId, invoiceIds: (raw.invoiceIds as (string | number)[]).map((id) => + /** + * String + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ String(id), ), allFunded: Boolean(raw.allFunded), @@ -3507,11 +4942,25 @@ export class StellarSplitClient extends TypedEventEmitter { * Release all invoices in a group. * * @returns The transaction hash. + * @param params - The parameters for the method. + * @throws {Error} If the method fails. */ async releaseGroup(creator: string, groupId: string): Promise { const operation = this.contract.call( "release_invoice_group", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(creator, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(groupId), { type: "u64" }), ); @@ -3524,6 +4973,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param amount - Gross amount in stroops * @returns Fee breakdown with gross, fee, net, and feeBps + * @throws {Error} If the method fails. */ async calculateFee(amount: bigint): Promise { return calculateFee(amount, this.config); @@ -3534,6 +4984,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param address - Token contract address * @returns Token metadata (symbol, name, decimals) + * @throws {Error} If the method fails. */ async resolveToken(address: string): Promise { return resolveToken(address, this.config); @@ -3544,6 +4995,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param txHash - Transaction hash * @returns Payment proof with deterministic SHA-256 hash + * @throws {Error} If the method fails. */ async generatePaymentProof(txHash: string): Promise { const m = await import("./proof.js"); @@ -3558,6 +5010,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The ID of the invoice. * @param payerAddress - The Stellar address of the payer. * @returns Payment receipt with proofHash and optional JSON serialization. + * @throws {Error} If the method fails. */ async generatePaymentReceipt( invoiceId: string, @@ -3584,13 +5037,32 @@ export class StellarSplitClient extends TypedEventEmitter { * @param payer - Stellar address of the payer (must sign). * @param payments - Array of { invoiceId, amount } (must be non-empty). * @returns The transaction hash. + * @throws {Error} If the method fails. */ async batchPay(payer: string, payments: BatchPayment[]): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (payments.length === 0) { throw new ValidationError("payments array must not be empty"); } + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const p of payments) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!p.invoiceId || isNaN(Number(p.invoiceId))) { throw new ValidationError(`Invalid invoiceId: ${p.invoiceId}`); } @@ -3612,6 +5084,12 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "batch_pay", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(payer, { type: "address" }), xdr.ScVal.scvVec(paymentVals), ); @@ -3633,6 +5111,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param payments - Array of { invoiceId, amount } pairs to verify. * @returns A `BatchVerificationResult` describing per-invoice validity, * the common token (if uniform), and any aggregated errors. + * @throws {Error} If the method fails. */ async verifyBatchPay( payments: BatchPayment[], @@ -3641,8 +5120,20 @@ export class StellarSplitClient extends TypedEventEmitter { const results = await this.resolveBatch(invoiceIds); const resolvedInvoices: Invoice[] = []; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const r of results) { const rr = r as { success: boolean; invoice?: Invoice }; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (rr.success && rr.invoice) { resolvedInvoices.push(rr.invoice); } @@ -3656,6 +5147,8 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceId - Invoice ID to validate against. * @param amount - Payment amount in stroops. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async validatePayment( invoiceId: string, @@ -3665,6 +5158,12 @@ export class StellarSplitClient extends TypedEventEmitter { let balance: bigint | null = null; const payerAddress = await this._getPayerAddress(); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (payerAddress) { try { balance = await this._getTokenBalance(payerAddress, invoice.token); @@ -3677,6 +5176,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Add trustline-check results for non-XLM assets when the config has a // horizon URL set. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this.config.horizonUrl && invoice.token !== "native") { try { const { Horizon } = await import("@stellar/stellar-sdk"); @@ -3687,8 +5192,20 @@ export class StellarSplitClient extends TypedEventEmitter { recipients, invoice.token, ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!trustResult.allReady) { const missing = trustResult.entries.filter((e) => !e.hasTrustline); + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const m of missing) { result.errors.push( `Recipient ${m.address} has no trustline for token ${invoice.token}. Establish a trustline before releasing.`, @@ -3705,6 +5222,12 @@ export class StellarSplitClient extends TypedEventEmitter { } private async _getPayerAddress(): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._adapter && typeof this._adapter.getAddress === "function") { return await this._adapter.getAddress(); } @@ -3718,16 +5241,40 @@ export class StellarSplitClient extends TypedEventEmitter { const tokenContract = new Contract(tokenAddress); const operation = tokenContract.call( "balance", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(address, { type: "address" }), ); const result = await this._simulateView(operation); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof result === "bigint") { return result; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof result === "string" || typeof result === "number") { return BigInt(result); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof result === "object" && result !== null && "balance" in result) { return BigInt( (result as Record).balance as string | number, @@ -3754,6 +5301,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param handler - Called with each single typed `InvoiceEvent` (SSE mode). * @param options - Optional SSE options (base URL, backoff, EventSource factory). * @returns Unsubscribe function that permanently stops the stream. + * @throws {Error} If the method fails. */ subscribeToInvoice( invoiceId: string, @@ -3771,6 +5319,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param handler - Called with InvoiceEvent[] (events since last poll). * @param intervalMs - Poll interval in milliseconds (default: 5000). * @returns Unsubscribe function that stops the stream. + * @throws {Error} If the method fails. */ subscribeToInvoice( invoiceId: string, @@ -3784,12 +5333,19 @@ export class StellarSplitClient extends TypedEventEmitter { * @param callbacks - Typed event callbacks. * @param intervalMs - Poll interval in milliseconds (default: 5000). * @returns Unsubscribe function that stops the stream. + * @throws {Error} If the method fails. */ subscribeToInvoice( invoiceId: string, callbacks: InvoiceEventCallbacks, intervalMs?: number, ): () => void; + /** + * subscribeToInvoice + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ subscribeToInvoice( invoiceId: string, handlerOrCallbacks: @@ -3799,7 +5355,19 @@ export class StellarSplitClient extends TypedEventEmitter { optionsOrInterval?: Partial | number, ): () => void { // WebSocket transport: use the active WebSocket connection when configured + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._wsTransport && this._transportType === 'websocket') { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof handlerOrCallbacks !== "function") { throw new ValidationError( "WebSocket transport requires a function handler. Callbacks object is not supported." @@ -3808,11 +5376,23 @@ export class StellarSplitClient extends TypedEventEmitter { const handler = handlerOrCallbacks as InvoiceEventHandler; const wrappedHandler = (event: unknown) => { + /** + * handler + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ handler(event as SSEInvoiceEvent); }; this._wsTransport.subscribe(invoiceId, wrappedHandler); + /** + * return + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ return () => { this._wsTransport?.unsubscribe(invoiceId, wrappedHandler); }; @@ -3821,8 +5401,20 @@ export class StellarSplitClient extends TypedEventEmitter { // A function handler with options object selects the SSE transport. // A function handler with number interval selects the RPC polling transport (new API). // A callbacks object selects the legacy RPC-polling transport. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof handlerOrCallbacks === "function") { // If second arg is a number, treat as polling + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof optionsOrInterval === "number") { return _subscribeToInvoice( this.server, @@ -3837,6 +5429,12 @@ export class StellarSplitClient extends TypedEventEmitter { (optionsOrInterval as Partial | undefined) ?? {}; const baseUrl = options.baseUrl ?? this.config.horizonUrl; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!baseUrl) { throw new ValidationError( "subscribeToInvoice (SSE) requires a base URL: set `horizonUrl` in the client config or pass `{ baseUrl }` in options.", @@ -3866,8 +5464,17 @@ export class StellarSplitClient extends TypedEventEmitter { * * When `transport: 'websocket'` was configured, returns `{ type: 'websocket', connected, reconnectAttempts }`. * Otherwise returns `{ type: 'http', connected: true, reconnectAttempts: 0 }`. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getTransportStatus(): TransportStatus { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._wsTransport) { return this._wsTransport.getStatus(); } @@ -3878,6 +5485,9 @@ export class StellarSplitClient extends TypedEventEmitter { * Register a callback for the `transport:fallback` event. * Fired when the WebSocket transport fails to connect after 3 attempts * and the client falls back to HTTP polling. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ onTransportFallback(cb: (event: { from: 'websocket'; to: 'http' }) => void): void { this._fallbackListeners.push(cb); @@ -3895,6 +5505,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param sourceAddress - Stellar address of the transaction source. * @param operation - The contract operation to include. * @returns Base64-encoded XDR of the prepared (unsigned) transaction. + * @throws {Error} If the method fails. */ async buildTransaction( sourceAddress: string, @@ -3911,6 +5522,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed: ${simResult.error}`, @@ -3928,6 +5545,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param signedXdr - Base64-encoded signed transaction XDR. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async submitTransaction(signedXdr: string): Promise { const tx = TransactionBuilder.fromXDR( @@ -3936,6 +5554,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); const sendResult = await this.server.sendTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -3946,6 +5570,12 @@ export class StellarSplitClient extends TypedEventEmitter { let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -3955,6 +5585,12 @@ export class StellarSplitClient extends TypedEventEmitter { attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -3971,23 +5607,54 @@ export class StellarSplitClient extends TypedEventEmitter { * * @returns The expected invoice ID and estimated fee in stroops. * @throws StellarSplitError with the simulation error message on failure. + * @param params - The parameters for the method. */ async simulateCreateInvoice( params: CreateInvoiceParams, ): Promise { const recipientAddresses = params.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.address, { type: "address" }), ); const recipientAmounts = params.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.amount, { type: "i128" }), ); const operation = this.contract.call( "create_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.creator, { type: "address" }), xdr.ScVal.scvVec(recipientAddresses), xdr.ScVal.scvVec(recipientAmounts), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.token, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.deadline, { type: "u64" }), ); @@ -4011,6 +5678,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation error: ${simResult.error}`, @@ -4022,6 +5695,12 @@ export class StellarSplitClient extends TypedEventEmitter { const success = simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse; const returnVal = success.result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) throw new NoReturnValueError("simulateCreateInvoice"); const invoiceId = scValToNative(returnVal).toString(); @@ -4035,12 +5714,31 @@ export class StellarSplitClient extends TypedEventEmitter { * * @returns The estimated fee in stroops. * @throws StellarSplitError with the simulation error message on failure. + * @param params - The parameters for the method. */ async simulatePay(params: PayParams): Promise { const operation = this.contract.call( "pay", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.payer, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.amount, { type: "i128" }), ); @@ -4064,6 +5762,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation error: ${simResult.error}`, @@ -4096,6 +5800,12 @@ export class StellarSplitClient extends TypedEventEmitter { sourceAmount: bigint, ): Promise { // Check if DEX is configured + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this.config.dexContractId) { throw new Error( "DEX contract not configured on this client. Set dexContractId in StellarSplitClientConfig.", @@ -4111,8 +5821,26 @@ export class StellarSplitClient extends TypedEventEmitter { // Call the DEX's quote method to get the swap estimate const operation = dexContract.call( "quote", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(sourceToken, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(invoice.token, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(sourceAmount, { type: "i128" }), ); @@ -4133,6 +5861,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Simulate the DEX quote const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `DEX quote simulation failed: ${simResult.error}`, @@ -4144,6 +5878,12 @@ export class StellarSplitClient extends TypedEventEmitter { const success = simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse; const returnVal = success.result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) { throw new NoReturnValueError("previewTokenSwap"); } @@ -4178,12 +5918,19 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param operation - The contract operation to estimate fees for. * @returns FeeEstimate with fee in stroops and a congestion indicator. + * @throws {Error} If the method fails. */ async estimateFee(operation: xdr.Operation): Promise { const simResult = (await this._simulateView(operation)) as { minResourceFee?: string; error?: string; }; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (simResult.error) throw new SimulationFailedError( `Fee estimation failed: ${simResult.error}`, @@ -4220,11 +5967,23 @@ export class StellarSplitClient extends TypedEventEmitter { * @throws If any signer fails to sign. */ async collectSignatures(xdrStr: string, signers: string[]): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (signers.length === 0) { throw new ValidationError("signers array must not be empty"); } let current = xdrStr; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const signer of signers) { try { current = await (this._adapter @@ -4248,7 +6007,11 @@ export class StellarSplitClient extends TypedEventEmitter { // invalidateCache implementation moved up to support MethodCache requirements - /** Clear the entire invoice cache. */ + /** Clear the entire invoice cache. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ clearCache(): void { this._cache?.clear(); } @@ -4262,6 +6025,8 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice ID whose storage entry to extend. * @param extendTo - Target ledger sequence to extend TTL to. * @param source - Stellar address of the account submitting the transaction. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async bumpStorageTtl( invoiceId: string, @@ -4269,6 +6034,12 @@ export class StellarSplitClient extends TypedEventEmitter { source: string, ): Promise { const ledgerKeys = [ + /** + * buildInvoiceDataLedgerKey + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ buildInvoiceDataLedgerKey(this.config.contractId, invoiceId), ]; return extendStorageTtl(this.config, { source, extendTo, ledgerKeys }); @@ -4279,6 +6050,8 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param options - TTL extension parameters including source, target ledger, * and an array of ledger keys to extend. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async bumpStorageTtlBatch( options: TtlExtensionOptions, @@ -4290,12 +6063,26 @@ export class StellarSplitClient extends TypedEventEmitter { * Switch to a different network. * * @param network - Network name ('testnet', 'mainnet') or custom NetworkConfig + * @returns The result of the method. + * @throws {Error} If the method fails. */ switchNetwork(network: string | NetworkConfig): void { let config: NetworkConfig; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof network === "string") { const preset = NETWORKS[network]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!preset) { throw new UnknownNetworkError(network); } @@ -4314,11 +6101,23 @@ export class StellarSplitClient extends TypedEventEmitter { // `this.config.rpcPoolSize` here because `NetworkConfig` doesn't carry a // pool size — reading from `this.config` after `this.config = config` // above would silently disable pooling on every network switch. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._pool) { this._pool.dispose(); this._pool = null; } const wantsPool = !this._standby && this._effectiveRpcPoolSize >= 2; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (wantsPool) { try { this._pool = new ConnectionPool({ @@ -4346,6 +6145,9 @@ export class StellarSplitClient extends TypedEventEmitter { * connection. When `rpcPoolSize >= 2` was set at construction time, the * returned {@link PoolStats} reports pool size, available slots, * cumulative request / error / recycle counters, and per-slot details. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ getPoolStats() { return this._pool ? this._pool.getStats() : null; @@ -4363,16 +6165,29 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice requiring multiple signatures. * @param signers - Stellar addresses of all required co-signers. * @returns Base64-encoded unsigned transaction XDR. + * @throws {Error} If the method fails. */ async collectCoSignatures( invoiceId: string, signers: string[], ): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (signers.length === 0) throw new NoSignerProvidedError(); const firstSigner = signers[0]!; const operation = this.contract.call( "release_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); @@ -4386,6 +6201,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed: ${simResult.error}`, @@ -4413,6 +6234,12 @@ export class StellarSplitClient extends TypedEventEmitter { const invoice = await this.getInvoice(invoiceId); const requiredCount = invoice.recipients.length; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (signatures.length < requiredCount) { throw new InsufficientSignaturesError(signatures.length, requiredCount); } @@ -4423,18 +6250,36 @@ export class StellarSplitClient extends TypedEventEmitter { this.config.networkPassphrase, ) as Transaction; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (let i = 1; i < signatures.length; i++) { const sig = signatures[i]!; const otherTx = TransactionBuilder.fromXDR( sig.signedXdr, this.config.networkPassphrase, ) as Transaction; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const decoratedSig of otherTx.signatures) { mergedTx.addDecoratedSignature(decoratedSig); } } const sendResult = await this.server.sendTransaction(mergedTx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -4444,6 +6289,12 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -4453,6 +6304,12 @@ export class StellarSplitClient extends TypedEventEmitter { attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -4506,9 +6363,21 @@ export class StellarSplitClient extends TypedEventEmitter { private async _needsCoCreatorApproval(invoiceId: string): Promise { const operation = this.contract.call( "needs_co_creator_approval", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const raw = await this._simulateView(operation); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!raw) { throw new CoCreatorApprovalNotRequiredError(invoiceId); } @@ -4536,7 +6405,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "submit_co_creator_approval", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(signer, { type: "address" }), ); const result = await this._submitTx(signer, operation); @@ -4570,6 +6451,12 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "get_co_creator_approvals", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const raw = (await this._simulateView(operation)) as string[]; @@ -4610,7 +6497,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "revoke_co_creator_approval", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(signer, { type: "address" }), ); const result = await this._submitTx(signer, operation); @@ -4641,6 +6540,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice ID to check. * @param payerAddress - Stellar address of the payer. * @returns Cooldown status with inCooldown flag and cooldownEndsAt timestamp. + * @throws {Error} If the method fails. */ async getPaymentCooldown( invoiceId: string, @@ -4650,7 +6550,19 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "payment_cooldown", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(payerAddress, { type: "address" }), ); const raw = (await this._simulateView(operation)) as Record< @@ -4693,10 +6605,17 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceOrTimestamp - An Invoice object or a Unix timestamp (seconds). * @returns A structured countdown with total_seconds, days, hours, minutes, seconds, and whether overdue. Null when no scheduled release date. + * @throws {Error} If the method fails. */ getScheduledReleaseCountdown( invoiceOrTimestamp: Invoice | number, ): ScheduledReleaseCountdown | null { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof invoiceOrTimestamp !== "number") { return getScheduledReleaseCountdown(invoiceOrTimestamp); } @@ -4713,6 +6632,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The ID of the invoice to bid on. * @param amount - Bid amount in stroops. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async placeBid( bidder: string, @@ -4723,8 +6643,26 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "place_bid", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(bidder, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(amount, { type: "i128" }), ); const result = await this._submitTx(bidder, operation); @@ -4749,8 +6687,15 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceId - The invoice ID to fetch payments for. * @returns All payments merged and sorted by timestamp (ascending). + * @throws {Error} If the method fails. */ async getPaymentHistory(invoiceId: string): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._batcher) { return this._batcher.getPaymentHistory(invoiceId); } @@ -4768,7 +6713,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operations = Array.from({ length: NUM_SHARDS }, (_, i) => this.contract.call( "get_payment_shard", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(i, { type: "u32" }), ), ); @@ -4778,8 +6735,26 @@ export class StellarSplitClient extends TypedEventEmitter { ); const allPayments: Payment[] = []; + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const result of shardResults) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (result.status === "fulfilled" && Array.isArray(result.value)) { + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (const raw of result.value as unknown[]) { const p = raw as Record; allPayments.push({ @@ -4817,13 +6792,26 @@ export class StellarSplitClient extends TypedEventEmitter { * @param caller - Stellar address of the caller (must sign). * @param invoiceId - The ID of the invoice to settle. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async settleAuction(caller: string, invoiceId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "settle_auction", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(caller, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(caller, operation); @@ -4839,12 +6827,19 @@ export class StellarSplitClient extends TypedEventEmitter { * Get the auction state for an invoice. * @param invoiceId - The ID of the invoice to query. * @returns Auction information including active state, highest bid, and end time. + * @throws {Error} If the method fails. */ async getAuctionInfo(invoiceId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "get_auction_info", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const raw = (await this._simulateView(operation)) as Record< @@ -4896,6 +6891,12 @@ export class StellarSplitClient extends TypedEventEmitter { expectedAddress: string, ): void { const kpAddress = adminKeypair.publicKey(); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (kpAddress !== expectedAddress) { throw new AdminOperationError( `Admin keypair public key (${kpAddress}) does not match the provided admin address (${expectedAddress})`, @@ -4937,6 +6938,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw parseSorobanError(simResult.error); } @@ -4949,6 +6956,12 @@ export class StellarSplitClient extends TypedEventEmitter { TransactionBuilder.fromXDR(signedXdr, this.config.networkPassphrase), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -4960,6 +6973,12 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -4969,6 +6988,12 @@ export class StellarSplitClient extends TypedEventEmitter { attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -4987,12 +7012,19 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice ID to freeze. * @param admin - Stellar address of the admin (must sign). * @returns The transaction hash. + * @throws {Error} If the method fails. */ async adminFreeze(invoiceId: string, admin: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "admin_freeze", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(admin, operation); @@ -5030,6 +7062,12 @@ export class StellarSplitClient extends TypedEventEmitter { // Verify the keypair is consistent with the effective admin configuration. // When an adminKeypair is configured at construction time, the passed // keypair must have the same public key. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._adminKeypair && this._adminKeypair.publicKey() !== adminAddress) { throw new AdminOperationError( `Provided admin keypair (${adminAddress}) does not match the configured admin keypair (${this._adminKeypair.publicKey()})`, @@ -5040,7 +7078,19 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "admin_freeze", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(reason, { type: "string" }), ); const result = await this._submitTxWithKeypair( @@ -5098,6 +7148,12 @@ export class StellarSplitClient extends TypedEventEmitter { const startTime = Date.now(); // Verify the keypair is consistent with the effective admin configuration. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._adminKeypair && this._adminKeypair.publicKey() !== adminAddress) { throw new AdminOperationError( `Provided admin keypair (${adminAddress}) does not match the configured admin keypair (${this._adminKeypair.publicKey()})`, @@ -5108,6 +7164,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "admin_unfreeze", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTxWithKeypair( @@ -5151,6 +7213,7 @@ export class StellarSplitClient extends TypedEventEmitter { * Queue a treasury or fee change action for execution after a timelock delay. * @param params - Queue action parameters. * @returns The action ID and transaction hash. + * @throws {Error} If the method fails. */ async queueAction( params: QueueActionParams, @@ -5159,10 +7222,40 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "queue_action", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.caller, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.actionType, { type: "symbol" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.target, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.value, { type: "i128" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.eta), { type: "u64" }), ); const result = await this._submitTx(params.caller, operation); @@ -5182,12 +7275,19 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice ID to unfreeze. * @param admin - Stellar address of the admin (must sign). * @returns The transaction hash. + * @throws {Error} If the method fails. */ async adminUnfreeze(invoiceId: string, admin: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "admin_unfreeze", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(admin, operation); @@ -5204,13 +7304,26 @@ export class StellarSplitClient extends TypedEventEmitter { * @param caller - Stellar address of the caller (must sign). * @param actionId - The ID of the action to execute. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async executeAction(caller: string, actionId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "execute_action", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(caller, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(actionId), { type: "u64" }), ); const result = await this._submitTx(caller, operation); @@ -5232,18 +7345,31 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceId - The invoice ID to query. * @returns The parsed CrossChainRef, or null if none is set. + * @throws {Error} If the method fails. */ async getCrossChainRef(invoiceId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "get_cross_chain_ref", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const raw = (await this._simulateView(operation)) as Record< string, unknown > | null; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!raw) { telemetry.recordMethod( "getCrossChainRef", @@ -5275,13 +7401,26 @@ export class StellarSplitClient extends TypedEventEmitter { * @param caller - Stellar address of the caller (must sign). * @param actionId - The ID of the action to cancel. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async cancelAction(caller: string, actionId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "cancel_action", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(caller, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(actionId), { type: "u64" }), ); const result = await this._submitTx(caller, operation); @@ -5298,6 +7437,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param params - Parameters including invoiceId, creator, and the CrossChainRef. * @returns The transaction hash. + * @throws {Error} If the method fails. */ async setCrossChainRef(params: SetCrossChainRefParams): Promise { const startTime = Date.now(); @@ -5314,6 +7454,12 @@ export class StellarSplitClient extends TypedEventEmitter { }) as xdr.ScVal, }), ]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.ref.blockNumber !== undefined) { refMap.push( new xdr.ScMapEntry({ @@ -5327,7 +7473,19 @@ export class StellarSplitClient extends TypedEventEmitter { const operation = this.contract.call( "set_cross_chain_ref", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.creator, { type: "address" }), xdr.ScVal.scvMap(refMap), ); @@ -5344,12 +7502,19 @@ export class StellarSplitClient extends TypedEventEmitter { * Get the status of a queued action. * @param actionId - The ID of the action to query. * @returns Timelock action status. + * @throws {Error} If the method fails. */ async getActionStatus(actionId: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "get_action_status", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(actionId), { type: "u64" }), ); const raw = (await this._simulateView(operation)) as Record< @@ -5387,6 +7552,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - The invoice ID to check. * @param payerAddress - Stellar address of the payer. * @returns The active window state, or `{ limited: false }` if unlimited. + * @throws {Error} If the method fails. */ async getVelocityStatus( invoiceId: string, @@ -5396,7 +7562,19 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "get_velocity_status", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(payerAddress, { type: "address" }), ); const raw = await this._simulateView(operation); @@ -5404,6 +7582,12 @@ export class StellarSplitClient extends TypedEventEmitter { telemetry.recordMethod("getVelocityStatus", true, Date.now() - startTime); // No velocity limit configured: contract returns void/null. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (raw === null || raw === undefined) { return { limited: false }; } @@ -5440,6 +7624,12 @@ export class StellarSplitClient extends TypedEventEmitter { /** Parse the native return value from `check_nft_gate`. */ private _parseNftGateResult(raw: unknown): NftGateResult { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!raw || typeof raw !== "object") { return { gated: false, hasNft: false, contractAddress: null }; } @@ -5473,6 +7663,12 @@ export class StellarSplitClient extends TypedEventEmitter { .setTimeout(30) .build(); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (traceId) { await runRequestInterceptors({ method: "_simulateView", @@ -5482,6 +7678,12 @@ export class StellarSplitClient extends TypedEventEmitter { } const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed: ${simResult.error}`, @@ -5493,6 +7695,12 @@ export class StellarSplitClient extends TypedEventEmitter { const returnVal = ( simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse ).result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) throw new NoReturnValueError("_simulateView"); return scValToNative(returnVal); @@ -5505,10 +7713,22 @@ export class StellarSplitClient extends TypedEventEmitter { priority: RequestPriority = "normal", ): Promise<{ txHash: string; returnValue: xdr.ScVal }> { return this._queue.enqueue(priority, async () => { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._idempotency) { const opXdr = operation.toXDR().toString("base64"); const key = this._idempotency.generateKey(sourceAddress, opXdr); const existing = this._idempotency.getResult(key); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (existing) { return { txHash: existing.txHash, @@ -5524,6 +7744,12 @@ export class StellarSplitClient extends TypedEventEmitter { try { const result = await submit(); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._idempotency) { const opXdr = operation.toXDR().toString("base64"); const key = this._idempotency.generateKey(sourceAddress, opXdr); @@ -5531,9 +7757,21 @@ export class StellarSplitClient extends TypedEventEmitter { } return result; } catch (error) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._standby) { this._standby.failover(); const result = await submit(); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._idempotency) { const opXdr = operation.toXDR().toString("base64"); const key = this._idempotency.generateKey(sourceAddress, opXdr); @@ -5567,6 +7805,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw parseSorobanError(simResult.error); } @@ -5583,6 +7827,12 @@ export class StellarSplitClient extends TypedEventEmitter { TransactionBuilder.fromXDR(signedXdr, this.config.networkPassphrase), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -5594,6 +7844,12 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -5604,6 +7860,12 @@ export class StellarSplitClient extends TypedEventEmitter { } // If still not confirmed, submit a fee-bump transaction with a higher fee + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND) { const multiplier = this.config.feeBumpMultiplier ?? 2; const innerTx = TransactionBuilder.fromXDR( @@ -5629,6 +7891,12 @@ export class StellarSplitClient extends TypedEventEmitter { this.config.networkPassphrase, ), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (bumpSendResult.status === "ERROR") { throw new TransactionFailedError( `Fee-bump transaction failed: ${JSON.stringify(bumpSendResult.errorResult)}`, @@ -5639,6 +7907,12 @@ export class StellarSplitClient extends TypedEventEmitter { const bumpHash = bumpSendResult.hash; let bumpResult = await this.server.getTransaction(bumpHash); let bumpAttempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( bumpResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && bumpAttempts < 20 @@ -5647,6 +7921,12 @@ export class StellarSplitClient extends TypedEventEmitter { bumpResult = await this.server.getTransaction(bumpHash); bumpAttempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (bumpResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(bumpResult.status)); } @@ -5660,10 +7940,22 @@ export class StellarSplitClient extends TypedEventEmitter { result: { txHash: bumpHash, returnValue: bumpReturnValue }, durationMs, }); + /** + * recordCall + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ recordCall(true); return { txHash: bumpHash, returnValue: bumpReturnValue }; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -5678,6 +7970,12 @@ export class StellarSplitClient extends TypedEventEmitter { result: { txHash, returnValue }, durationMs, }); + /** + * recordCall + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ recordCall(true); return { txHash, returnValue }; } catch (error) { @@ -5687,6 +7985,12 @@ export class StellarSplitClient extends TypedEventEmitter { result: undefined, durationMs, }); + /** + * recordCall + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ recordCall(false); throw error; } @@ -5714,6 +8018,12 @@ export class StellarSplitClient extends TypedEventEmitter { const recipients: Recipient[] = (raw.recipients as string[]).map( (addr: string, i: number) => { const amt = amounts[i]; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (amt === undefined) throw new NoReturnValueError(`_parseInvoice ${i}`); return { @@ -5761,6 +8071,12 @@ export class StellarSplitClient extends TypedEventEmitter { private async _getInvoiceExt(invoiceId: string): Promise { const operation = this.contract.call( "get_invoice_ext", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); @@ -5798,10 +8114,28 @@ export class StellarSplitClient extends TypedEventEmitter { let depth = 0; const MAX_DEPTH = 10; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while (currentId) { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (seen.has(currentId)) { throw new CloneChainTooDeepError(currentId); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (depth >= MAX_DEPTH) { throw new CloneChainTooDeepError(); } @@ -5830,6 +8164,8 @@ export class StellarSplitClient extends TypedEventEmitter { * against the Horizon REST API via a two-link FallbackChain. * * @param address - Stellar public key of the account. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getAccount(address: string): Promise { const rpcFetch = async (): Promise => { @@ -5837,6 +8173,12 @@ export class StellarSplitClient extends TypedEventEmitter { return { id: acc.accountId(), sequence: acc.sequenceNumber() }; }; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._horizonReader) { return rpcFetch(); } @@ -5850,6 +8192,12 @@ export class StellarSplitClient extends TypedEventEmitter { }); return chain.execute(async (provider) => { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (provider === "rpc") return rpcFetch(); return horizonReader.getAccount(address); }); @@ -5866,8 +8214,15 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param address - Stellar public key of the account. * @throws If no `horizonUrl` was configured. + * @returns The result of the method. */ async getAccountBalances(address: string): Promise { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!this._horizonReader) { throw new ValidationError( "getAccountBalances requires horizonUrl to be set in StellarSplitClientConfig", @@ -5884,6 +8239,12 @@ export class StellarSplitClient extends TypedEventEmitter { }); return chain.execute(async (provider) => { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (provider === "rpc") { throw new ValidationError( "Soroban RPC does not expose account balances; delegating to Horizon", @@ -5913,6 +8274,8 @@ export class StellarSplitClient extends TypedEventEmitter { * @param creator - Stellar address of the invoice creator (must sign). * @param payerAddress - Stellar address of the payer who receives the refund. * Required for the claimable-balance fallback path. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async refundInvoice( invoiceId: string, @@ -5924,11 +8287,23 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "refund_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const result = await this._submitTx(creator, operation); const invoice = await this.getInvoice(invoiceId).catch(() => null); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (invoice) this._fireOnRefunded(invoice); telemetry.recordMethod("refundInvoice", true, Date.now() - startTime); @@ -5936,7 +8311,19 @@ export class StellarSplitClient extends TypedEventEmitter { } catch (error) { // Fallback path: if transfer failed due to missing account/trustline and // Horizon is configured, create a claimable balance instead. + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if ( + /** + * isRefundTransferError + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ isRefundTransferError(error) && this.config.horizonUrl && payerAddress @@ -5983,6 +8370,8 @@ export class StellarSplitClient extends TypedEventEmitter { * Requires `config.horizonUrl` to be set. * * @param payer - Stellar address of the claimant to query. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getClaimableRefunds(payer: string): Promise { return getClaimableRefunds(payer, this.config); @@ -6014,6 +8403,12 @@ export class StellarSplitClient extends TypedEventEmitter { }); const operation = this.contract.call( "get_invoice", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), ); const account = await server @@ -6029,6 +8424,12 @@ export class StellarSplitClient extends TypedEventEmitter { .setTimeout(30) .build(); const simResult = await server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed on ${url}: ${simResult.error}`, @@ -6039,6 +8440,12 @@ export class StellarSplitClient extends TypedEventEmitter { const returnVal = ( simResult as SorobanRpc.Api.SimulateTransactionSuccessResponse ).result?.retval; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!returnVal) throw new NoReturnValueError(`syncInvoice ${url}`); const raw = scValToNative(returnVal) as Record; const invoice = this._parseInvoice(invoiceId, raw); @@ -6062,6 +8469,12 @@ export class StellarSplitClient extends TypedEventEmitter { ) .map((r) => r.value); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (successful.length === 0) { throw new RpcUnavailableError("syncInvoice"); } @@ -6078,6 +8491,9 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Get the claimable payout amount for a recipient on an invoice. * Returns 0n if no pending payout exists. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getPendingPayout( invoiceId: string, @@ -6087,7 +8503,19 @@ export class StellarSplitClient extends TypedEventEmitter { try { const operation = this.contract.call( "get_pending_payout", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(recipient, { type: "address" }), ); const raw = await this._simulateView(operation); @@ -6104,6 +8532,8 @@ export class StellarSplitClient extends TypedEventEmitter { * Claim a pending payout for a recipient on an invoice. * Emits a `pending_payout_claimed` event on success. * @throws If no pending payout exists for the recipient. + * @param params - The parameters for the method. + * @returns The result of the method. */ async claimPendingPayout( invoiceId: string, @@ -6112,12 +8542,30 @@ export class StellarSplitClient extends TypedEventEmitter { const startTime = Date.now(); try { const pending = await this.getPendingPayout(invoiceId, recipient); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (pending === 0n) { throw new NoPendingPayoutError(recipient, invoiceId); } const operation = this.contract.call( "claim_pending_payout", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(recipient, { type: "address" }), ); const result = await this._submitTx(recipient, operation); @@ -6145,17 +8593,32 @@ export class StellarSplitClient extends TypedEventEmitter { * Pay toward an invoice bound to an off-chain identity attestation. * Validates attestationHash (32 bytes) and signature (64 bytes) before submission. * Returns a payment receipt with the attestation hash included. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async payWithAttestation( params: PayWithAttestationParams, ): Promise { const startTime = Date.now(); try { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.attestationHash.length !== 32) { throw new InvalidAttestationError( `attestationHash must be 32 bytes, got ${params.attestationHash.length}`, ); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (params.signature.length !== 64) { throw new InvalidAttestationError( `signature must be 64 bytes, got ${params.signature.length}`, @@ -6163,11 +8626,35 @@ export class StellarSplitClient extends TypedEventEmitter { } const operation = this.contract.call( "pay_with_attestation", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.payer, { type: "address" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(BigInt(params.invoiceId), { type: "u64" }), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.amount, { type: "i128" }), xdr.ScVal.scvBytes(Buffer.from(params.attestationHash)), xdr.ScVal.scvBytes(Buffer.from(params.signature)), + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(params.signerPubkey, { type: "address" }), ); const result = await this._submitTx(params.payer, operation); @@ -6199,12 +8686,22 @@ export class StellarSplitClient extends TypedEventEmitter { // Issue #276 — Creator volume cap status checker // --------------------------------------------------------------------------- - /** Returns the volume cap for a creator in token units, or null if uncapped. */ + /** Returns the volume cap for a creator in token units, or null if uncapped. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async getCreatorVolumeCap(address: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "get_creator_volume_cap", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(address, { type: "address" }), ); const raw = await this._simulateView(operation); @@ -6225,12 +8722,22 @@ export class StellarSplitClient extends TypedEventEmitter { } } - /** Returns the lifetime volume used by a creator in token units. */ + /** Returns the lifetime volume used by a creator in token units. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async getCreatorVolumeUsed(address: string): Promise { const startTime = Date.now(); try { const operation = this.contract.call( "get_creator_volume_used", + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(address, { type: "address" }), ); const raw = await this._simulateView(operation); @@ -6251,7 +8758,11 @@ export class StellarSplitClient extends TypedEventEmitter { } } - /** Returns remaining volume (cap - used) or Infinity if the creator is uncapped. */ + /** Returns remaining volume (cap - used) or Infinity if the creator is uncapped. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async getRemainingCreatorVolume( address: string, ): Promise { @@ -6259,6 +8770,12 @@ export class StellarSplitClient extends TypedEventEmitter { this.getCreatorVolumeCap(address), this.getCreatorVolumeUsed(address), ]); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (cap === null) return Infinity; return cap > used ? cap - used : 0n; } @@ -6271,29 +8788,80 @@ export class StellarSplitClient extends TypedEventEmitter { * Create up to 10 invoices in a single fee-bump transaction. * Validates all items before submission; fails fast on the first invalid item. * Returns invoice IDs in the same order as the input array. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async createInvoiceBatch( items: CreateInvoiceParams[], ): Promise<{ invoiceIds: string[]; txHash: string }> { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (items.length === 0 || items.length > 10) { throw new InvalidBatchSizeError("1-10 items", items.length); } + /** + * for + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ for (let i = 0; i < items.length; i++) { const item = items[i]!; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!item.creator) throw new ValidationError(`Item ${i}: creator is required`); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!item.token) throw new ValidationError(`Item ${i}: token is required`); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!item.deadline || item.deadline <= 0) throw new ValidationError( `Item ${i}: deadline must be a positive number`, ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!Array.isArray(item.recipients) || item.recipients.length === 0) { throw new ValidationError( `Item ${i}: recipients must be a non-empty array`, ); } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this.config.payloadGuard) { + /** + * validateInvoicePayload + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ validateInvoicePayload(item, this.config.payloadGuard); } } @@ -6309,6 +8877,12 @@ export class StellarSplitClient extends TypedEventEmitter { key: nativeToScVal("recipients", { type: "symbol" }) as xdr.ScVal, val: xdr.ScVal.scvVec( p.recipients.map((r) => + /** + * nativeToScVal + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ nativeToScVal(r.address, { type: "address" }), ), ), @@ -6347,6 +8921,12 @@ export class StellarSplitClient extends TypedEventEmitter { .build(); const simResult = await this.server.simulateTransaction(tx); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (SorobanRpc.Api.isSimulationError(simResult)) { throw new SimulationFailedError( `Simulation failed: ${simResult.error}`, @@ -6358,6 +8938,12 @@ export class StellarSplitClient extends TypedEventEmitter { const preparedTx = SorobanRpc.assembleTransaction(tx, simResult).build(); const bumpedFee = String( Math.ceil( + /** + * Number + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ Number(BASE_FEE) * (this.config.feeBumpMultiplier ?? 2) * items.length, @@ -6382,6 +8968,12 @@ export class StellarSplitClient extends TypedEventEmitter { const sendResult = await this.server.sendTransaction( TransactionBuilder.fromXDR(signedXdr, this.config.networkPassphrase), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -6391,6 +8983,12 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -6399,6 +8997,12 @@ export class StellarSplitClient extends TypedEventEmitter { getResult = await this.server.getTransaction(txHash); attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -6407,6 +9011,12 @@ export class StellarSplitClient extends TypedEventEmitter { (getResult as SorobanRpc.Api.GetSuccessfulTransactionResponse) .returnValue ?? xdr.ScVal.scvVoid(); const invoiceIds = ( + /** + * scValToNative + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ scValToNative(returnVal) as (string | number | bigint)[] ).map((id) => id.toString()); @@ -6435,6 +9045,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param opts - Optional per-call timeout and trace ID overrides. * @returns Array of creator addresses sorted by invoice volume descending. + * @throws {Error} If the method fails. */ async getLeaderboard(opts?: { timeout?: number; @@ -6446,10 +9057,28 @@ export class StellarSplitClient extends TypedEventEmitter { this._withTelemetry( "getLeaderboard", undefined, + /** + * async + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ async () => { const operation = this.contract.call("get_leaderboard"); const raw = await this._simulateView(operation, opts?.traceId); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!Array.isArray(raw)) return []; + /** + * return + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ return (raw as Array>).map((entry) => ({ creator: String(entry.creator ?? ""), invoiceCount: Number(entry.invoice_count ?? 0), @@ -6468,6 +9097,8 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param invoiceId - The invoice ID. * @param opts - Optional per-call timeout and trace ID overrides. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async getInvoiceHistory( invoiceId: string, @@ -6507,6 +9138,7 @@ export class StellarSplitClient extends TypedEventEmitter { * const estimate = await client.estimateBridgeFee("ethereum", 100_000_000n); * console.log(estimate.netAmount); // amount in stroops * ``` + * @throws {Error} If the method fails. */ async estimateBridgeFee( sourceChain: ChainId, @@ -6545,6 +9177,7 @@ export class StellarSplitClient extends TypedEventEmitter { * deadline: Math.floor(Date.now() / 1000) + 3600, * }); * ``` + * @throws {Error} If the method fails. */ buildBridgePayment(params: BridgePaymentParams): BridgePaymentRequest { return _buildBridgePayment(params); @@ -6598,6 +9231,8 @@ export class StellarSplitClient extends TypedEventEmitter { * @param invoiceId - Invoice whose recipient should be updated. * @param oldAddress - The merged (invalid) recipient address. * @param newAddress - The destination account after the merge. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async rerouteRecipient( invoiceId: string, @@ -6609,6 +9244,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); const horizonUrl = this.config.horizonUrl; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!horizonUrl) { throw new Error( "horizonUrl is required in client config to validate reroute destination", @@ -6627,6 +9268,9 @@ export class StellarSplitClient extends TypedEventEmitter { * * Delegates to PaymentGraphChecker. Throws `UnreachableRecipientError` * unless `allowUnreachable` is set. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ async finalizeInvoice( invoiceId: string, @@ -6637,6 +9281,12 @@ export class StellarSplitClient extends TypedEventEmitter { ); const horizonUrl = this.config.horizonUrl; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!horizonUrl) { throw new Error( "horizonUrl is required in client config for payment graph checking", @@ -6658,6 +9308,7 @@ export class StellarSplitClient extends TypedEventEmitter { * * @param adapter - A `WalletAdapter` (e.g. from `WalletSessionManager.detect()`). * @returns The connected Stellar public key. + * @throws {Error} If the method fails. */ async connectWallet(adapter: WalletAdapter): Promise { const address = await adapter.connect(); @@ -6674,8 +9325,17 @@ export class StellarSplitClient extends TypedEventEmitter { /** * Disconnect the currently connected wallet adapter. + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. */ disconnectWallet(): void { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (this._adapter) { this._adapter.disconnect(); const walletName = this._adapter.name; @@ -6699,6 +9359,12 @@ export class StellarSplitClient extends TypedEventEmitter { */ async verifyInvoice(invoice: Invoice, expectedHash: string): Promise { const valid = await verifyInvoiceHash(invoice, expectedHash); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (!valid) { const computed = await hashInvoice(invoice); throw new InvoiceIntegrityError(invoice.id, expectedHash, computed); @@ -6719,6 +9385,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param baseFee - Base fee in stroops. * @param config - Optional surge multiplier config. * @returns The fee bump transaction hash. + * @throws {Error} If the method fails. */ async submitWithFeeBump( innerTxXdr: string, @@ -6742,6 +9409,12 @@ export class StellarSplitClient extends TypedEventEmitter { TransactionBuilder.fromXDR(signedXdr, this.config.networkPassphrase), ); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (sendResult.status === "ERROR") { throw new TransactionFailedError( `Fee bump transaction failed: ${JSON.stringify(sendResult.errorResult)}`, @@ -6751,6 +9424,12 @@ export class StellarSplitClient extends TypedEventEmitter { const txHash = sendResult.hash; let getResult = await this.server.getTransaction(txHash); let attempts = 0; + /** + * while + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ while ( getResult.status === SorobanRpc.Api.GetTransactionStatus.NOT_FOUND && attempts < 20 @@ -6760,6 +9439,12 @@ export class StellarSplitClient extends TypedEventEmitter { attempts++; } + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (getResult.status !== SorobanRpc.Api.GetTransactionStatus.SUCCESS) { throw new TransactionNotConfirmedError(String(getResult.status)); } @@ -6785,6 +9470,7 @@ export class StellarSplitClient extends TypedEventEmitter { * @param escrowVaultId - The vault ID to release (optional). * @param signerSecret - Secret key for signing the claim transaction. * @returns Object with `{ invoiceId, txHash? }`. + * @throws {Error} If the method fails. */ async confirmDelivery( invoiceId: string, @@ -6802,6 +9488,12 @@ export class StellarSplitClient extends TypedEventEmitter { | import("./escrowVaultManager.js").EscrowVaultManager | undefined; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (escrowManager && escrowVaultId && signerSecret) { const result = await escrowManager.release(escrowVaultId, recipientId, signerSecret); txHash = result.txHash; @@ -6813,8 +9505,26 @@ export class StellarSplitClient extends TypedEventEmitter { /** Coerce a native-decoded scalar (bigint | number | string) into a bigint, defaulting to 0n. */ function toBigInt(value: unknown): bigint { + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof value === "bigint") return value; + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof value === "number") return BigInt(Math.trunc(value)); + /** + * if + * @param params - The parameters for the method. + * @returns The result of the method. + * @throws {Error} If the method fails. + */ if (typeof value === "string" && value !== "") return BigInt(value); return 0n; }