Repository navigation
v11.14.0
-
Breaking:
BaseAssetandQuoteAssetofPriceData(Xrpl.BinaryCodec11.14.0.0) encode a three-character code at bytes 12-14, as rippled and xrpl.js encode every Currency field. The codec wrote it at bytes 0-2, which the ledger holds as a different, nonstandard currency: an oracle published by the SDK withUSDwas shown by the node as5553440000000000000000000000000000000000, was not found byget_aggregate_priceforUSD, and did not aggregate with oracles published by other SDKs.Currency.FromOracleJson,Currency.FromOracleStringandCurrency.EncodeOracleCurrencyare removed;Currency.GetCurrencyCodeFromTlcBytesno longer reads text at bytes 0-2 as a standard code, andOracleCurrencyConverterreads such a value as hex instead of as the three characters. Migration: an oracle the SDK published with a three-character code holds the nonstandard code; sendOracleSetagain with the same codes to store the standard ones, and delete the old pairs if they are no longer wanted -
IXrplClient.GetAggregatePricewithGetAggregatePriceRequest,OracleIdentifier,GetAggregatePriceResponseandAggregatePriceSet(get_aggregate_price).AggregatePriceAssetConverterwritesbase_asset/quote_assetin the form rippled displays the stored currency in, which is what the node compares them with. The time filter is sent astime_threshold, the name rippled reads; the xrpl.org reference and xrpl.js name ittrim_threshold -
IXrplClient.BookChangeswithBookChangesRequestandBookChangesResponse(book_changes). Without a ledger, rippled answers for the open ledger, not a validated one -
IXrplClient.ManifestwithManifestRequest,ManifestResponseandManifestDetails(manifest). For a key with no manifest, rippled answers with details naming the key as both master and ephemeral key, withoutmanifestorseq; the xrpl.js model expectsdetailsto be absent instead -
IXrplClient.VersionwithVersionResponseandApiVersionRange(version).first,goodandlastare read as strings: rippled sends the strings1.0.0to API version 1 requests and the numbers of the supported range to later ones -
IXrplClient.GetAggregatePrice,BookChanges,ManifestandVersionhave default implementations that callGRequest, so an existingIXrplClientimplementation compiles without them -
PathFindCreateRequest.Domain(domain): the streamingpath_find createsearches a permissioned domain's books, asRipplePathFindRequest.Domaindoes forripple_path_find. Without it, a search for aPaymentwithDomainIDquoted the open books.PathFindCreateRequest.SendMaxdocuments that rippled accepts it only with aDestinationAmountof -1 -
BookChange(thebook_changesstream and method) gainsMptIssuanceIdA,MptIssuanceIdBandDomain, which rippled sends for an MPT side and for a permissioned-domain book;AssetA/AssetBcarry the MPT issuance ID for an MPT side -
TakerAmount(book_offers) gainsMptIssuanceId(mpt_issuance_id), the MPT side of an order book under MPTokensV2 (XLS-82), andTakerAmount.FromAsset(IssuedCurrency), which builds the side of XRP, an issued currency or an MPT.DexSnapshotLoaderandBookIndexbuild theirbook_offerssides with it, so an MPT side is asked for by its issuance ID rather than with neither currency nor issuer -
BookOffersRequest.Validate()checks a request as rippled develop'sbook_offershandler does, in its order:mpt_issuance_idexcludescurrencyandissuerand is 48 hex digits;currencyandissuerare parsed astoCurrencyandtoIssuerparse them, with XRP taking no issuer and an issued currency requiring one other than account one;takeris an address,domain64 hex digits; and two sides naming one asset arebadMarket. Messages name the field and the rippled error code -
Behaviour change:
IXrplClient.BookOfferscallsValidate()and raisesValidationExceptionbefore sending a request the node would refuse; such a request used to reach the node and fail withRippledException -
OfferCreateCrossing,PaymentFlowandPathFindingcross, pay and find paths through MPT order books (MPTokensV2, XLS-82), ported from rippled 3.4.0; theNotSupportedExceptionthey threw for an MPT side, payment or path step is gone. Ported:MPTEndpointStep(MptEndpointStep),toStrand's MPT path elements and no-rippling rules,BookStep's MPT transfer rate,WeakAuthandcheckMPTDEXchecks, issuer input cap, overflow removal,checkCreateMPTandissuerSelfDebitHookMPT,OfferStream'sissuerFundsToSelfIssue,directSendNoFeeMPTwithPaymentSandbox'screditMPT,balanceHookMPTandbalanceHookSelfIssueMPT,accountHolds/accountFunds/requireAuth/canTrade/canTransferfor MPT,OfferCreate's MPTpreflightandpreclaim(temDISABLED,tecLOCKED, an unfunded MPT issuer,checkAcceptAsset,canTrade), the tick size leaving an MPT side exact and an unrepresentable quality not placed,Payment's pre-MPTokensV2 direct MPT payment with its transfer fee,getBookBase's tagged MPT book keys, and the path finder'sgetMPTs,PathFindMPT::canSend, MPT account links, books and path counts -
DexSnapshot.MptIssuances(DexMptIssuance) andDexSnapshot.MptHoldings(DexMptHolding);DexSnapshot.FromNodeAsyncreads the issuances and MPTokens of the strands, offers and pools it covers, andUnlimitedTakerholds plenty of an MPT it pays -
OfferCrossingResult.MpTokensandPaymentFlowResult.MpTokens(MpTokenChange): the MPTokens a transaction creates.BalanceChangesreport MPT holdings, and an issuer's change as the negated change ofOutstandingAmount, asBalanceChanges.GetBalanceChangesreads the metadata -
OfferRemovalReason.Overflow -
OfferCreateCrossing.RoundToTickSizeleaves an MPT side as given -
BookIndexreads MPT book directories (TakerPaysMPT,TakerGetsMPT), andBookIndex.FromAccountsAsyncadds the MPTs the accounts issue or hold.PathFindRequest.SourceCurrenciesnames an MPT byMptIssuanceId;PathFindResult.DestinationCurrencieslists the destination's MPT issuance IDs -
SourceCurrency.MptIssuanceId(mpt_issuance_id) forripple_path_find -
Docs: "MPTs on the DEX" in the Amounts guide (
DocFx/Amounts-Guide.md,Amounts-Guide.ru.md) -
CI:
MPTEndpointStep.cpp,TokenHelpers.h,MPTokenHelpers.h/.cpp,MPTAmount.h/.cpp,PathAsset.h,Indexes.cppandrpc/detail/MPT.hare on the engine-watch list ofprotocol-watch.yml -
CI:
.ci-config/check-rpc-methods.shwith.ci-config/rpc-methods-ignore.txt, run by therpc-methodsjob ofprotocol-watch.yml, compares rippled develop's RPC method names with the SDK's request models, with no method left as a gap;MethodNames.handhandlers/Handlers.hare on the protocol-watch list.submit_multisignedis listed as covered: a multi-signed blob goes throughsubmit(Signer.Multisign,SubmitMulti) -
Tests:
TestUGetAggregatePrice;TestIOracleaggregates prices with trim, with a nonstandard code and withtime_threshold, and asks for an unpriced pair;TestUOracleSetcompares theOracleSetencoding byte for byte with xrpl.js and replacesTestVerify_CurrencyOracleEncodingwithTestVerify_CurrencyEncoding_StandardCodeAtIsoPosition;TestUOracleCurrencyConverter.Read_HexCode40Chars_ThreeCharsAtByteZero_StaysHex;TestUBookChangesManifestVersion;TestURequestSerializationcoversdomaininpath_find create;TestIPathFinding.PathFindCreateThroughADomainBookchecks thatpath_findquotes the domain's book asripple_path_finddoes;TestIBookChangesManifestVersionreads the trade of an offer crossing back throughbook_changes, the manifest of a key without one, and the API version range;TestISubmitMultisigned, an empty stub that tested nothing, is removed (multi-signed submission is covered byTestIMultisign);TestUBookOffersMpt;TestUMptDexbuilds strands as rippled'sPayStrandMPT_testpins them and crosses and pays MPTs worked out by hand;TestUOfferCreateCrossing.MptSidesAreNotSupportedis removed;TestIMptDexpredicts each crossing and payment withOfferCreateCrossingandPaymentFlowand compares it with the node throughBookCrossingHarness- offers pairing an MPT with XRP and with an issued currency, the taker's MPToken created, a transfer fee rounded up, a walked MPT book, an issuer's own offer at its maximum, an MPT/XRP pool crossed with the book, a locked issuance, payments from XRP and from an issued currency, with a fee and between holders, a locked sender - reads MPT books throughbook_offers, and sends the requestsValidate()refuses to the node and gets the same errors back;TestIPathFindingcompares MPT searches withripple_path_find(XRP to an MPT, an MPT as the source currency, XRP to an issued currency bridged through an MPT book, the holder's MPT among every source asset) and searches at the stand's[path_search]of 7, whichripple_path_finduses, instead of 2;BookCrossingHarness.AdjustRulesturns MPTokensV2 on for a standalone stand, where it is a[features]preset, andAssertMpTokenscompares the MPTokens created -
Breaking (source, named arguments only):
LoanSigningHelpernames its LoanSet parties by role, submitter (Account) and counterparty, instead of broker and borrower (#276). rippled takes the counterparty asCounterparty, or the LoanBroker's owner when the field is omitted, and needs one ofAccountand the counterparty to be the owner, so the borrower may submit and the broker owner co-sign. Renamed parameters:PrepareForSigning(…, submitterWallet),SignLoanSet(…, submitterWallet, counterpartyWallet),CombineLoanSignatures(submitterSignedBlob, counterpartySignedBlob). Migration: a call passing these by name uses the new names; positional calls are unchanged -
LoanSigningHelper.SignLoanSettakes the two wallets in either order and gives the TxnSignature to the one whose address isAccount; it refused a borrower-submitted LoanSet whoseCounterpartyis the broker owner. It throws when neither wallet isAccount, or when the other wallet is notCounterparty. The new overloadSignLoanSet(preparedTx, submitterWallet, counterpartyWallet, brokerOwner)also checks the counterparty whenCounterpartyis omitted and that one of the two parties is the broker owner -
LoanSigningHelper.SubmitterSignreplacesBrokerSign, which is[Obsolete]and forwards to it -
Docs:
ILoanSet.Counterparty,LoanSet,LoanSigningHelper,XrplWallet.SignAsLoanCounterpartyandLendingProtocol-Guide(both languages) describe the two roles -
Tests:
TestULoanSigningRoles;TestILoanBorrowerSubmitssubmits a LoanSet from the borrower withCounterpartyset to the broker owner, with it omitted, and with the broker owner signing first, gated onAmendmentGuard.LendingProtocol -
Validation.ValidateLoanManageaccepts a LoanManage with no action flag, as rippled'sLoanManage::preflightdoes: it rejects only more than one oftfLoanDefault,tfLoanImpairandtfLoanUnimpair(temINVALID_FLAG), anddoApplytreats none as a no-op (#277). It refused a transaction withFlagsabsent, zero, or carrying onlytfInnerBatchTxn.LoanManage,LoanManageFlagsandLendingProtocol-Guidedocument the no-op -
Tests:
TestULoanManage -
Breaking:
ITransactionCommongainsSponsorSignatureandILoanSetgainsCounterpartySignature, bothSignatureObject(#278).TransactionRequestandTransactionResponseimplement the first,LoanSetandLoanSetResponsethe second. A request model dropped either co-signature when deserialized and written back withToJson; a response kept it only as raw JSON inUnknownFields, where it no longer appears. Migration: a class implementingITransactionCommonorILoanSetdirectly adds the property; code reading either field fromUnknownFieldsreads the typed property -
SignatureObjectConverterwrites aSignatureObjectin its wire shape (SigningPubKeyandTxnSignature, orSignerswith each entry wrapped inSigner) and reads one without enforcing a form, so a Batch inner marker - an empty object, or an emptySigningPubKey- writes back as it came.SignatureObject.ValidateShapealso refuses aSignerentry that nestsSigners, whichFromJsonObjectrefused before through its recursive parse. Both fields are not signing fields in the codec, so they change no signing preimage -
SignatureResult.GetTxkeeps both co-signatures instead of refusing a blob that carries them, so a partially signed LoanSet decodes and its submitter'sSignof the typed transaction gives the blobLoanSigningHelper.SubmitterSigngives -
Tests:
TestUCoSignatureFieldsround-trips both fields in single and multisig form through the request and response models, checks that the signing preimage under the transaction, counterparty and sponsor prefixes is unchanged by them, signs a decoded partially signed LoanSet, and round-trips the Batch inner markers;TestUSignatureResultRoundTriprefuses an unmodelled field (Destinationon a LoanSet) and keepsCounterpartySignature -
Validation.ValidateBatch(andBatchUtils.Build, which calls it) no longer rejects Vault, LoanBroker and Loan inner transactions. rippled develop refuses them (kDisabledTxTypes→temINVALID_INNER_BATCH) only whileLendingProtocolV1_2is not enabled (rippled #8244); the offline check has no ledger rules, so the node decides.DisabledInnerTxTypesis removed -
Tests:
TestUBatchCoSigning.TestUValidateBatch_LendingInner_LeftToTheNode(all fifteen types) andTestUBuildBatch_TypedLoanSetAndVaultDeposit_BuildsreplaceTestUValidateBatch_LoanOrVaultInner_Throws;TestIBatchInnerTypes.Batch_Inner_VaultCreate_RejectedByNodeBeforeLendingProtocolV12andBatch_Inner_VaultCreate_WithLendingProtocolV12, gated onAmendmentGuard.LendingProtocolV12; the Sponsorship guide describes the amendment gate -
Xrpl.Amountsports the integer-arithmetic hardening of rippled 3.4.1 in the payment engine:StrandFlow.RunreturnstecPATH_DRYwhen an XRP or MPT sum of the strands' ins or outs leavesint64(checkedStepAddOpt), andBookCrossingStepfails the strand withtecPATH_DRYwhen its sum does (checkedStepAdd). New:StepMath.CheckedAddandStepMath.TrySum -
CI: engine-watch's
baseline_refinprotocol-watch.ymlis3.4.1 -
Docs: the Amounts guide (
DocFx/Amounts-Guide.md,Amounts-Guide.ru.md) and the summaries ofOfferCreateCrossing,PaymentFlow,PathfinderandPathFindingname rippled 3.4.1 as the release the engine follows -
Tests:
TestUCheckedStepAddreplays thecheckedAddassertions ofMathUtilities.hon MPT and XRP amounts and checks the step and flow sums