diff --git a/src/features/multichain/routines/executors/pay.ts b/src/features/multichain/routines/executors/pay.ts index 21b942c1..47857532 100644 --- a/src/features/multichain/routines/executors/pay.ts +++ b/src/features/multichain/routines/executors/pay.ts @@ -228,14 +228,6 @@ async function handleXRPLPay( log.debug("[XMScript Parser] Ripple Pay: connected to the XRP network") try { - // Validate signedPayloads exists and has at least one element - if (!operation.task.signedPayloads || operation.task.signedPayloads.length === 0) { - return { - result: "error", - error: `Missing signed payloads for XRPL operation (${operation.chain}.${operation.subchain})`, - } - } - const signedTx = operation.task.signedPayloads[0] // Extract tx_blob - handle both string and object formats @@ -261,11 +253,8 @@ async function handleXRPLPay( // Submit transaction and wait for validation const res = await xrplInstance.provider.submitAndWait(txBlob) - // Extract transaction result - handle different response formats - const meta = res.result.meta - const txResult = (typeof meta === "object" && meta !== null && "TransactionResult" in meta - ? (meta as { TransactionResult: string }).TransactionResult - : (res.result as any).engine_result) as string | undefined + const meta = res.result.meta as any + const txResult = meta?.TransactionResult || (res.result as any).engine_result const txHash = res.result.hash const resultMessage = ((res.result as any).engine_result_message || "") as string @@ -277,21 +266,48 @@ async function handleXRPLPay( } } - // XRPL transaction result code prefixes and their meanings - const xrplErrorMessages: Record = { - tec: "Transaction failed (fee charged)", // tecUNFUNDED_PAYMENT, tecINSUF_FEE, tecPATH_DRY - tem: "Malformed transaction", // temREDUNDANT, temBAD_FEE, temINVALID - ter: "Transaction provisional/queued", // terQUEUED - tef: "Transaction rejected", // tefPAST_SEQ, tefMAX_LEDGER, tefFAILURE + // tec* codes: Transaction failed but fee was charged + // The transaction was applied to ledger but did not achieve its intended purpose + // Example: tecUNFUNDED_PAYMENT, tecINSUF_FEE, tecPATH_DRY + if (txResult?.startsWith('tec')) { + return { + result: "error", + error: `Transaction failed (fee charged): ${txResult} - ${resultMessage}`, + hash: txHash, + extra: { code: txResult, validated: res.result.validated } + } + } + + // tem* codes: Malformed transaction (not applied to ledger) + // Example: temREDUNDANT (sending to self), temBAD_FEE, temINVALID + if (txResult?.startsWith('tem')) { + return { + result: "error", + error: `Malformed transaction: ${txResult} - ${resultMessage}`, + hash: txHash, + extra: { code: txResult, validated: res.result.validated } + } } - const errorPrefix = txResult?.substring(0, 3) - if (errorPrefix && xrplErrorMessages[errorPrefix]) { + // ter* codes: Provisional/retryable result (not final) + // Example: terQUEUED (transaction queued for future ledger) + if (txResult?.startsWith('ter')) { return { result: "error", - error: `${xrplErrorMessages[errorPrefix]}: ${txResult} - ${resultMessage}`, + error: `Transaction provisional/queued: ${txResult} - ${resultMessage}`, hash: txHash, - extra: { code: txResult, validated: res.result.validated }, + extra: { code: txResult, validated: res.result.validated } + } + } + + // tef* codes: Local failure (not applied to ledger) + // Example: tefPAST_SEQ, tefMAX_LEDGER, tefFAILURE + if (txResult?.startsWith('tef')) { + return { + result: "error", + error: `Transaction rejected: ${txResult} - ${resultMessage}`, + hash: txHash, + extra: { code: txResult, validated: res.result.validated } } } @@ -299,13 +315,13 @@ async function handleXRPLPay( result: "error", error: `Unknown transaction result: ${txResult} - ${resultMessage}`, hash: txHash, - extra: { code: txResult, validated: res.result.validated }, + extra: { code: txResult, validated: res.result.validated } } } catch (error) { console.log("[XMScript Parser] Ripple Pay: error:", error) return { result: "error", - error: error instanceof Error ? error.message : String(error), + error: error.toString(), } } }