#include #include #include #include #include #include #include namespace xrpl { std::unordered_map> const& transResults() { // clang-format off // Macros are generally ugly, but they can help make code readable to // humans without affecting the compiler. #define MAKE_ERROR(code, desc) { code, { #code, desc } } static std::unordered_map< TERUnderlyingType, std::pair> const results { MAKE_ERROR(tecAMM_BALANCE, "AMM has invalid balance."), MAKE_ERROR(tecAMM_INVALID_TOKENS, "AMM invalid LP tokens."), MAKE_ERROR(tecAMM_FAILED, "AMM transaction failed."), MAKE_ERROR(tecAMM_EMPTY, "AMM is in empty state."), MAKE_ERROR(tecAMM_NOT_EMPTY, "AMM is not in empty state."), MAKE_ERROR(tecAMM_ACCOUNT, "This operation is not allowed on an AMM Account."), MAKE_ERROR(tecCLAIM, "Fee claimed. Sequence used. No action."), MAKE_ERROR(tecDIR_FULL, "Can not add entry to full directory."), MAKE_ERROR(tecFAILED_PROCESSING, "Failed to correctly process transaction."), MAKE_ERROR(tecINSUF_RESERVE_LINE, "Insufficient reserve to add trust line."), MAKE_ERROR(tecINSUF_RESERVE_OFFER, "Insufficient reserve to create offer."), MAKE_ERROR(tecNO_DST, "Destination does not exist. Send XRP to create it."), MAKE_ERROR(tecNO_DST_INSUF_XRP, "Destination does not exist. Too little XRP sent to create it."), MAKE_ERROR(tecNO_LINE_INSUF_RESERVE, "No such line. Too little reserve to create it."), MAKE_ERROR(tecNO_LINE_REDUNDANT, "Can't set non-existent line to default."), MAKE_ERROR(tecPATH_DRY, "Path could not send partial amount."), MAKE_ERROR(tecPATH_PARTIAL, "Path could not send full amount."), MAKE_ERROR(tecNO_ALTERNATIVE_KEY, "The operation would remove the ability to sign transactions with the account."), MAKE_ERROR(tecNO_REGULAR_KEY, "Regular key is not set."), MAKE_ERROR(tecOVERSIZE, "Object exceeded serialization limits."), MAKE_ERROR(tecUNFUNDED, "Not enough XRP to satisfy the reserve requirement."), MAKE_ERROR(tecUNFUNDED_ADD, "DEPRECATED."), MAKE_ERROR(tecUNFUNDED_AMM, "Insufficient balance to fund AMM."), MAKE_ERROR(tecUNFUNDED_OFFER, "Insufficient balance to fund created offer."), MAKE_ERROR(tecUNFUNDED_PAYMENT, "Insufficient XRP balance to send."), MAKE_ERROR(tecOWNERS, "Non-zero owner count."), MAKE_ERROR(tecNO_ISSUER, "Issuer account does not exist."), MAKE_ERROR(tecNO_AUTH, "Not authorized to hold asset."), MAKE_ERROR(tecNO_LINE, "No such line."), MAKE_ERROR(tecINSUFF_FEE, "Insufficient balance to pay fee."), MAKE_ERROR(tecFROZEN, "Asset is frozen."), MAKE_ERROR(tecNO_TARGET, "Target account does not exist."), MAKE_ERROR(tecNO_PERMISSION, "No permission to perform requested operation."), MAKE_ERROR(tecNO_ENTRY, "No matching entry found."), MAKE_ERROR(tecINSUFFICIENT_RESERVE, "Insufficient reserve to complete requested operation."), MAKE_ERROR(tecNEED_MASTER_KEY, "The operation requires the use of the Master Key."), MAKE_ERROR(tecDST_TAG_NEEDED, "A destination tag is required."), MAKE_ERROR(tecINTERNAL, "An internal error has occurred during processing."), MAKE_ERROR(tecCRYPTOCONDITION_ERROR, "Malformed, invalid, or mismatched conditional or fulfillment."), MAKE_ERROR(tecINVARIANT_FAILED, "One or more invariants for the transaction were not satisfied."), MAKE_ERROR(tecEXPIRED, "Expiration time is passed."), MAKE_ERROR(tecDUPLICATE, "Ledger object already exists."), MAKE_ERROR(tecKILLED, "No funds transferred and no offer created."), MAKE_ERROR(tecHAS_OBLIGATIONS, "The account cannot be deleted since it has obligations."), MAKE_ERROR(tecTOO_SOON, "It is too early to attempt the requested operation. Please wait."), MAKE_ERROR(tecMAX_SEQUENCE_REACHED, "The maximum sequence number was reached."), MAKE_ERROR(tecNO_SUITABLE_NFTOKEN_PAGE, "A suitable NFToken page could not be located."), MAKE_ERROR(tecNFTOKEN_BUY_SELL_MISMATCH, "The 'Buy' and 'Sell' NFToken offers are mismatched."), MAKE_ERROR(tecNFTOKEN_OFFER_TYPE_MISMATCH, "The type of NFToken offer is incorrect."), MAKE_ERROR(tecCANT_ACCEPT_OWN_NFTOKEN_OFFER, "An NFToken offer cannot be claimed by its owner."), MAKE_ERROR(tecINSUFFICIENT_FUNDS, "Not enough funds available to complete requested transaction."), MAKE_ERROR(tecOBJECT_NOT_FOUND, "A requested object could not be located."), MAKE_ERROR(tecINSUFFICIENT_PAYMENT, "The payment is not sufficient."), MAKE_ERROR(tecINCOMPLETE, "Some work was completed, but more submissions required to finish."), MAKE_ERROR(tecXCHAIN_BAD_TRANSFER_ISSUE, "Bad xchain transfer issue."), MAKE_ERROR(tecXCHAIN_NO_CLAIM_ID, "No such xchain claim id."), MAKE_ERROR(tecXCHAIN_BAD_CLAIM_ID, "Bad xchain claim id."), MAKE_ERROR(tecXCHAIN_CLAIM_NO_QUORUM, "Quorum was not reached on the xchain claim."), MAKE_ERROR(tecXCHAIN_PROOF_UNKNOWN_KEY, "Unknown key for the xchain proof."), MAKE_ERROR(tecXCHAIN_CREATE_ACCOUNT_NONXRP_ISSUE, "Only XRP may be used for xchain create account."), MAKE_ERROR(tecXCHAIN_WRONG_CHAIN, "XChain Transaction was submitted to the wrong chain."), MAKE_ERROR(tecXCHAIN_REWARD_MISMATCH, "The reward amount must match the reward specified in the xchain bridge."), MAKE_ERROR(tecXCHAIN_NO_SIGNERS_LIST, "The account did not have a signers list."), MAKE_ERROR(tecXCHAIN_SENDING_ACCOUNT_MISMATCH,"The sending account did not match the expected sending account."), MAKE_ERROR(tecXCHAIN_INSUFF_CREATE_AMOUNT, "Insufficient amount to create an account."), MAKE_ERROR(tecXCHAIN_ACCOUNT_CREATE_PAST, "The account create count has already passed."), MAKE_ERROR(tecXCHAIN_ACCOUNT_CREATE_TOO_MANY, "There are too many pending account create transactions to submit a new one."), MAKE_ERROR(tecXCHAIN_PAYMENT_FAILED, "Failed to transfer funds in a xchain transaction."), MAKE_ERROR(tecXCHAIN_SELF_COMMIT, "Account cannot commit funds to itself."), MAKE_ERROR(tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR, "Bad public key account pair in an xchain transaction."), MAKE_ERROR(tecXCHAIN_CREATE_ACCOUNT_DISABLED, "This bridge does not support account creation."), MAKE_ERROR(tecEMPTY_DID, "The DID object did not have a URI or DIDDocument field."), MAKE_ERROR(tecINVALID_UPDATE_TIME, "The Oracle object has invalid LastUpdateTime field."), MAKE_ERROR(tecTOKEN_PAIR_NOT_FOUND, "Token pair is not found in Oracle object."), MAKE_ERROR(tecARRAY_EMPTY, "Array is empty."), MAKE_ERROR(tecARRAY_TOO_LARGE, "Array is too large."), MAKE_ERROR(tecLOCKED, "Fund is locked."), MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."), MAKE_ERROR(tecWRONG_ASSET, "Wrong asset given."), MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."), MAKE_ERROR(tecPSEUDO_ACCOUNT, "This operation is not allowed against a pseudo-account."), MAKE_ERROR(tecPRECISION_LOSS, "The amounts used by the transaction cannot interact."), MAKE_ERROR(tecBAD_PROOF, "Proof cannot be verified"), MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."), MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."), MAKE_ERROR(tefBAD_AUTH, "Transaction's public key is not authorized."), MAKE_ERROR(tefBAD_LEDGER, "Ledger in unexpected state."), MAKE_ERROR(tefBAD_QUORUM, "Signatures provided do not meet the quorum."), MAKE_ERROR(tefBAD_SIGNATURE, "A signature is provided for a non-signer."), MAKE_ERROR(tefCREATED, "Can't add an already created account."), MAKE_ERROR(tefEXCEPTION, "Unexpected program state."), MAKE_ERROR(tefFAILURE, "Failed to apply."), MAKE_ERROR(tefINTERNAL, "Internal error."), MAKE_ERROR(tefMASTER_DISABLED, "Master key is disabled."), MAKE_ERROR(tefMAX_LEDGER, "Ledger sequence too high."), MAKE_ERROR(tefNO_AUTH_REQUIRED, "Auth is not required."), MAKE_ERROR(tefNOT_MULTI_SIGNING, "Account has no appropriate list of multi-signers."), MAKE_ERROR(tefPAST_SEQ, "This sequence number has already passed."), MAKE_ERROR(tefWRONG_PRIOR, "This previous transaction does not match."), MAKE_ERROR(tefBAD_AUTH_MASTER, "Auth for unclaimed account needs correct master key."), MAKE_ERROR(tefINVARIANT_FAILED, "Fee claim violated invariants for the transaction."), MAKE_ERROR(tefTOO_BIG, "Transaction affects too many items."), MAKE_ERROR(tefNO_TICKET, "Ticket is not in ledger."), MAKE_ERROR(tefNFTOKEN_IS_NOT_TRANSFERABLE, "The specified NFToken is not transferable."), MAKE_ERROR(tefINVALID_LEDGER_FIX_TYPE, "The LedgerFixType field has an invalid value."), MAKE_ERROR(telLOCAL_ERROR, "Local failure."), MAKE_ERROR(telBAD_DOMAIN, "Domain too long."), MAKE_ERROR(telBAD_PATH_COUNT, "Malformed: Too many paths."), MAKE_ERROR(telBAD_PUBLIC_KEY, "Public key is not valid."), MAKE_ERROR(telFAILED_PROCESSING, "Failed to correctly process transaction."), MAKE_ERROR(telINSUF_FEE_P, "Fee insufficient."), MAKE_ERROR(telNO_DST_PARTIAL, "Partial payment to create account not allowed."), MAKE_ERROR(telCAN_NOT_QUEUE, "Can not queue at this time."), MAKE_ERROR(telCAN_NOT_QUEUE_BALANCE, "Can not queue at this time: insufficient balance to pay all queued fees."), MAKE_ERROR(telCAN_NOT_QUEUE_BLOCKS, "Can not queue at this time: would block later queued transaction(s)."), MAKE_ERROR(telCAN_NOT_QUEUE_BLOCKED, "Can not queue at this time: blocking transaction in queue."), MAKE_ERROR(telCAN_NOT_QUEUE_FEE, "Can not queue at this time: fee insufficient to replace queued transaction."), MAKE_ERROR(telCAN_NOT_QUEUE_FULL, "Can not queue at this time: queue is full."), MAKE_ERROR(telWRONG_NETWORK, "Transaction specifies a Network ID that differs from that of the local node."), MAKE_ERROR(telREQUIRES_NETWORK_ID, "Transactions submitted to this node/network must include a correct NetworkID field."), MAKE_ERROR(telNETWORK_ID_MAKES_TX_NON_CANONICAL, "Transactions submitted to this node/network must NOT include a NetworkID field."), MAKE_ERROR(telENV_RPC_FAILED, "Unit test RPC failure."), MAKE_ERROR(temMALFORMED, "Malformed transaction."), MAKE_ERROR(temBAD_AMM_TOKENS, "Malformed: Invalid LPTokens."), MAKE_ERROR(temBAD_AMOUNT, "Malformed: Bad amount."), MAKE_ERROR(temBAD_CURRENCY, "Malformed: Bad currency."), MAKE_ERROR(temBAD_EXPIRATION, "Malformed: Bad expiration."), MAKE_ERROR(temBAD_FEE, "Invalid fee, negative or not XRP."), MAKE_ERROR(temBAD_ISSUER, "Malformed: Bad issuer."), MAKE_ERROR(temBAD_LIMIT, "Limits must be non-negative."), MAKE_ERROR(temBAD_MPT, "Malformed: Bad MPT."), MAKE_ERROR(temBAD_OFFER, "Malformed: Bad offer."), MAKE_ERROR(temBAD_PATH, "Malformed: Bad path."), MAKE_ERROR(temBAD_PATH_LOOP, "Malformed: Loop in path."), MAKE_ERROR(temBAD_QUORUM, "Malformed: Quorum is unreachable."), MAKE_ERROR(temBAD_REGKEY, "Malformed: Regular key cannot be same as master key."), MAKE_ERROR(temBAD_SEND_XRP_LIMIT, "Malformed: Limit quality is not allowed for XRP to XRP."), MAKE_ERROR(temBAD_SEND_XRP_MAX, "Malformed: Send max is not allowed for XRP to XRP."), MAKE_ERROR(temBAD_SEND_XRP_NO_DIRECT, "Malformed: No Ripple direct is not allowed for XRP to XRP."), MAKE_ERROR(temBAD_SEND_XRP_PARTIAL, "Malformed: Partial payment is not allowed for XRP to XRP."), MAKE_ERROR(temBAD_SEND_XRP_PATHS, "Malformed: Paths are not allowed for XRP to XRP."), MAKE_ERROR(temBAD_SEQUENCE, "Malformed: Sequence is not in the past."), MAKE_ERROR(temBAD_SIGNATURE, "Malformed: Bad signature."), MAKE_ERROR(temBAD_SIGNER, "Malformed: No signer may duplicate account or other signers."), MAKE_ERROR(temBAD_SRC_ACCOUNT, "Malformed: Bad source account."), MAKE_ERROR(temBAD_TRANSFER_RATE, "Malformed: Transfer rate must be >= 1.0 and <= 2.0"), MAKE_ERROR(temBAD_WEIGHT, "Malformed: Weight must be a positive value."), MAKE_ERROR(temDST_IS_SRC, "Destination may not be source."), MAKE_ERROR(temDST_NEEDED, "Destination not specified."), MAKE_ERROR(temEMPTY_DID, "Malformed: No DID data provided."), MAKE_ERROR(temINVALID, "The transaction is ill-formed."), MAKE_ERROR(temINVALID_FLAG, "The transaction has an invalid flag."), MAKE_ERROR(temREDUNDANT, "The transaction is redundant."), MAKE_ERROR(temRIPPLE_EMPTY, "PathSet with no paths."), MAKE_ERROR(temUNCERTAIN, "In process of determining result. Never returned."), MAKE_ERROR(temUNKNOWN, "The transaction requires logic that is not implemented yet."), MAKE_ERROR(temDISABLED, "The transaction requires logic that is currently disabled."), MAKE_ERROR(temBAD_TICK_SIZE, "Malformed: Tick size out of range."), MAKE_ERROR(temINVALID_ACCOUNT_ID, "Malformed: A field contains an invalid account ID."), MAKE_ERROR(temCANNOT_PREAUTH_SELF, "Malformed: An account may not preauthorize itself."), MAKE_ERROR(temINVALID_COUNT, "Malformed: Count field outside valid range."), MAKE_ERROR(temSEQ_AND_TICKET, "Transaction contains a TicketSequence and a non-zero Sequence."), MAKE_ERROR(temBAD_NFTOKEN_TRANSFER_FEE, "Malformed: The NFToken transfer fee must be between 1 and 5000, inclusive."), MAKE_ERROR(temXCHAIN_EQUAL_DOOR_ACCOUNTS, "Malformed: Bridge must have unique door accounts."), MAKE_ERROR(temXCHAIN_BAD_PROOF, "Malformed: Bad cross-chain claim proof."), MAKE_ERROR(temXCHAIN_BRIDGE_BAD_ISSUES, "Malformed: Bad bridge issues."), MAKE_ERROR(temXCHAIN_BRIDGE_NONDOOR_OWNER, "Malformed: Bridge owner must be one of the door accounts."), MAKE_ERROR(temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT, "Malformed: Bad min account create amount."), MAKE_ERROR(temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT, "Malformed: Bad reward amount."), MAKE_ERROR(temARRAY_EMPTY, "Malformed: Array is empty."), MAKE_ERROR(temARRAY_TOO_LARGE, "Malformed: Array is too large."), MAKE_ERROR(temBAD_TRANSFER_FEE, "Malformed: Transfer fee is outside valid range."), MAKE_ERROR(temINVALID_INNER_BATCH, "Malformed: Invalid inner batch transaction."), MAKE_ERROR(temBAD_CIPHERTEXT, "Malformed: Invalid ciphertext."), MAKE_ERROR(terRETRY, "Retry transaction."), MAKE_ERROR(terFUNDS_SPENT, "DEPRECATED."), MAKE_ERROR(terINSUF_FEE_B, "Account balance can't pay fee."), MAKE_ERROR(terLAST, "DEPRECATED."), MAKE_ERROR(terNO_RIPPLE, "Path does not permit rippling."), MAKE_ERROR(terNO_ACCOUNT, "The source account does not exist."), MAKE_ERROR(terNO_AUTH, "Not authorized to hold IOUs."), MAKE_ERROR(terNO_LINE, "No such line."), MAKE_ERROR(terPRE_SEQ, "Missing/inapplicable prior transaction."), MAKE_ERROR(terOWNERS, "Non-zero owner count."), MAKE_ERROR(terQUEUED, "Held until escalated fee drops."), MAKE_ERROR(terPRE_TICKET, "Ticket is not yet in ledger."), MAKE_ERROR(terNO_AMM, "AMM doesn't exist for the asset pair."), MAKE_ERROR(terADDRESS_COLLISION, "Failed to allocate an unique account address."), MAKE_ERROR(terNO_DELEGATE_PERMISSION, "Delegated account lacks permission to perform this transaction."), MAKE_ERROR(terLOCKED, "Fund is locked."), MAKE_ERROR(tesSUCCESS, "The transaction was applied. Only final in a validated ledger."), }; // clang-format on #undef MAKE_ERROR return results; } bool transResultInfo(TER code, std::string& token, std::string& text) { auto& results = transResults(); auto const r = results.find(TERtoInt(code)); if (r == results.end()) return false; token = r->second.first; text = r->second.second; return true; } std::string transToken(TER code) { std::string token; std::string text; return transResultInfo(code, token, text) ? token : "-"; } std::string transHuman(TER code) { std::string token; std::string text; return transResultInfo(code, token, text) ? text : "-"; } std::optional transCode(std::string const& token) { static auto const results = [] { auto& byTer = transResults(); auto range = boost::make_iterator_range(byTer.begin(), byTer.end()); auto tRange = boost::adaptors::transform( range, [](auto const& r) { return std::make_pair(r.second.first, r.first); }); std::unordered_map const byToken( tRange.begin(), tRange.end()); return byToken; }(); auto const r = results.find(token); if (r == results.end()) return std::nullopt; return TER::fromInt(r->second); } } // namespace xrpl