Repository navigation
Release 16.0.0
16.0.0
Major release, recompile required. The first stable release since 15.1.0 (Protocol 26). It brings the SDK up to the network as it runs today: Protocol 27 (CAP-71 Soroban authorization, now defaulting to address-bound v2 credentials) and Protocol 28 (CAP-85 external executable references, CAP-83), and it reads Protocol 29 networks, which reached Mainnet on 2026-10-01 without changing the XDR. It adds SEP-7, SEP-12, SEP-38 and SEP-45 clients, ships multi-target packages (
net10.0,net8.0,netstandard2.1) validated on .NET MAUI for Android, overhauls HTTP retry, and fixes a long list of Soroban RPC wire-format bugs. Everything first previewed in 16.0.0-beta is included. Binaries built against 15.x are not compatible, so recompile, then check the breaking changes below.
Breaking Changes
- Soroban authorization: v2 credentials by default (#244, #187):
StellarRpcServer.SimulateTransactionnow sendsuseUpgradedAuth: trueunless told otherwise, so recording-mode simulation returnsSorobanAddressCredentialsV2entries where it returned legacySorobanAddressCredentials. V2 signatures are bound to the signer's address and cannot be replayed against another account.- If you sign with
SorobanAuthorization.AuthorizeEntry, nothing changes: it signs whichever variant simulation returned.SorobanAddressCredentialsV2is a sibling type, not a subclass, so anis/as SorobanAddressCredentialscheck silently stops matching v2 entries. A hand-rolled signer must build its payload withSorobanAuthorization.BuildAuthorizationEntryPreimageHash, which picks the preimage from the entry. - To keep legacy entries (for a co-signer that cannot sign v2 yet), pass
useUpgradedAuth: falsetoSimulateTransaction, orSorobanCredentialsVersion.V1toAuthorizeEntry. Legacy signatures are not address-bound. Stellar RPC plans to drop the opt-out in a future protocol. - The
useUpgradedAuthparameter (#209) changes the CLR signature ofSimulateTransaction, so code compiled against an earlier release throwsMissingMethodExceptionuntil recompiled. SorobanCredentials.ToXdr()is nowabstract; external subclasses must override it.SorobanSourceAccountCredentials.ToSorobanCredentialsXdr()andSorobanAddressCredentials.ToSorobanCredentialsXdr()are removed: callToXdr().
- Protocol 28 XDR (#252):
SCValType,ContractExecutableTypeandStellarValueTypegain members (SCV_EXECUTABLE_TAG,CONTRACT_EXECUTABLE_EXTERNAL_REF,STELLAR_VALUE_EMPTY_TX_SET). Values that failed to decode withInvalidDataExceptionnow decode, so code that switches over these enums, or overSCVal/ContractExecutablesubclasses, meets cases it has not seen before. - Stellar RPC errors are thrown, not swallowed (#217, #218):
- Every
StellarRpcServermethod throws the newSorobanRpcException(withCode,ErrorMessageandErrorData) on a JSON-RPC error, where it returnednull. Replace null checks on the result with acatch. - A response body holding the JSON literal
nullthrowsClientProtocolExceptioninstead of aNullReferenceException. SorobanRpcResponse<T>.Idis nowstring?, as JSON-RPC allows a null id on an error response.
- Every
- Simulation responses match the RPC contract (#220, #221, #222, #234):
SimulateTransactionResponse.MinResourceFeeis nowlong?(wasuint?): fees above ~429 XLM failed to deserialize.Transaction.AddResourceFeetakes alongand throwsOverflowExceptioninstead of wrapping to a tiny fee.RestorePreamble.SorobanTransactionDatano longer throws on every access, and is typedSorobanTransactionData?.StateChanges,Results,EventsandResults[i].Authrejectnullelements;LedgerEntryChange.TypeandRestorePreamble.MinResourceFeeare required;LedgerEntryChange.Keyis nowstring?, because the server omits an empty key.SorobanAuthorizationis now[JsonIgnore]; it is derived fromResults[0].Auth, which is still serialized.- The decoded XDR properties (
SorobanAuthorization,SorobanTransactionData,RestorePreamble.SorobanTransactionData) throwInvalidDataExceptionfor a malformed blob, where they threwFormatExceptionorIOException.
- Transaction statuses are parsed strictly (#220, #225, #235, #236):
getTransaction/getTransactionsstatuses,sendTransactionstatuses and Horizon's asynctx_statusaccept only their exact wire strings. A bare number was mapped by position, so a malformed"status": 1read asSUCCESS; it is now rejected withJsonException.TransactionInfo.Status,SendTransactionResponse.StatusandSendTransactionResponse.Hashare required, so a response missing them fails instead of reading asNOT_FOUNDorPENDING.- The three status enums carry type-level converters, so they keep their wire format even when serialized on their own with your own
JsonSerializerOptions.
getEventsrequest shape (#219, #220):GetEventsRequest.EventFilter.Typeis now the[Flags]enumEventFilterType(System,Contract) instead of astring, since the server accepts only those literals.PaginationOptions.Cursorand.Limitare now properties instead of fields, which is what finally puts them on the wire.TransactionInfometadata (#228):ResultValue,WasmHashandCreatedContractIdnow read the return value from V3 metas as well as V4, and returnnullinstead of throwing when the meta cannot be decoded.TransactionMetastill returnsnullfor a bad payload, but no longer swallows unrelated failures such asOutOfMemoryException.AuthModeserialization (#209): serializing anAuthModevalue directly now writes the wire spelling ("enforce","record","record_allow_nonroot"). TheauthModerequest field was fixed separately (see Bug Fixes).- HTTP retry overhaul (#184):
- The
ForSoroban()/ForHorizon()presets retry transient HTTP status codes (408/429/500/502/503/504) on POST as well, since Stellar submission is idempotent. Do not use them for SEP clients, whose POSTs are not. - HTTP 429 and 503 throw the new
TooManyRequestsExceptionandServiceUnavailableException. ForSorobanPolling()is deprecated in favour ofForSoroban().
- The
- Stricter JSON (#181, #183, #201):
- Duplicate JSON properties throw
JsonExceptioninstead of last-value-wins, on every target framework and in the SDK's hand-written converters too. - The shared
JsonSerializerOptionsare frozen; clone them before modifying. - The SDK references the standalone
System.Text.Json10 package onnet8.0andnetstandard2.1. - The
Asset,AssetAmount,ReserveandLiquidityPoolClaimableAssetAmountconverters throwJsonExceptionfor malformed values, where they leakedArgumentExceptionorAssetCodeLengthInvalidException.
- Duplicate JSON properties throw
- Stricter XDR decoding (#189):
XdrDataInputStreamthrowsEndOfStreamExceptionon truncated input (wasIndexOutOfRangeException). KeyPairexceptions (#202): constructors and byte-array factories throwArgumentException/ArgumentNullExceptionfor bad key material on every target framework (was NSec'sFormatException).Sign/SignDecoratedwithout a private key throwInvalidOperationException(wasException).
Features
- Protocol 28 (#252):
- CAP-85 external executable references:
SCExecutableTag,ContractExecutableExternalRef,CreateContractOperation.FromExternalRefto deploy from one, andStellarRpcServer.GetExternalRefWasmHashto resolve one, withExternalRefNotFoundExceptiontelling a missing tag entry from an archived one. - CAP-83
STELLAR_VALUE_EMPTY_TX_SETdecodes. - Generated XDR string types (
SCString,SCSymbol,String32,String64) keep the raw wire bytes in a newInnerBytesproperty, so non-UTF-8 strings such as binary executable tags round-trip unchanged.InnerValueremains as a UTF-8 view. - Known-answer tests against
@stellar/stellar-sdk17.2.0, and live Testnet tests.
- CAP-85 external executable references:
- Protocol 27 (CAP-71) Soroban authorization (#187, #209):
SorobanAddressCredentialsV2and delegated credentials (SorobanAddressCredentialsWithDelegates,SorobanDelegateSignature); signing helpersAuthorizeEntry,AuthorizeEntryWithDelegates,BuildWithDelegatesEntryandBuildAuthorizationEntryPreimageHash; theISorobanEntrySignerabstraction withKeyPairEntrySigner; and theuseUpgradedAuthsimulation flag. Signing is verified byte for byte against the JS SDK, and end to end on Testnet. - SEP-7 URI scheme for payment requests and delegated signing (#238):
UriScheme,Sep7Uri, signing and verification, and submission to a callback. - SEP-12 KYC API client (#239):
KycServicefor every customer, file and callback endpoint, andKycCallbackSignatureto verify anchor callbacks. - SEP-38 anchor RFQ client (#243):
QuoteServicefor/info,/prices,/priceand/quote. - SEP-45 web authentication for contract accounts (#190):
ClientWebAuthContractandSep45Challenge. - The SDK now implements 9 SEPs (SEP-1, 6, 7, 9, 10, 12, 24, 38 and 45), each with a compatibility matrix at 100% field coverage. The SEP-12 and SEP-38 clients take the JWT from the SEP-10 or SEP-45 client.
- Multi-target packages (#195): both packages ship
net10.0,net8.0andnetstandard2.1builds, so the SDK installs in Unity 2022.3+, Tizen and othernetstandard2.1hosts. KeyPairimplementsIDisposableto release its native signing key deterministically (#195).- HTTP retry (#184):
ForSoroban()andForHorizon()presets that honourRetry-After, and newHttpResilienceOptionssettings (RetryHttpStatusCodes,RetryHttpMethods,RespectRetryAfter,MaxRetryAfterDelay). GetLatestLedgerResponsegainsCloseTime,HeaderXdrandMetadataXdr, andGetHealthResponsegainsLatestLedgerCloseTimeandOldestLedgerCloseTime(#198).
Bug Fixes
SimulateTransactionsentauthModein a casing Stellar RPC rejects, so every call that set it failed, in every release since 14.0.0 (#209).getEventsdropped the caller's cursor and limit, so paging was impossible (#219).- JSON-RPC errors were returned as
nullresults, hiding the server's message (#217, #218). MinResourceFeeaboveuint.MaxValuestroops broke deserialization of the whole simulation response (#221).RestorePreamble.SorobanTransactionDatathrew on every access, so the archived-entry restore flow did not work (#222).TransactionInfo.ResultValueignored V3 transaction metas, reporting no return value for contract calls recorded before Protocol 23 (#228).- Status enums could read a malformed or missing value as a real status (#225, #235, #236).
- A
getLedgerEntriesresponse with anullentry madeLedgerEntries,LedgerKeysandGetAccountthrowNullReferenceException; it now fails withJsonException(#252). - SEP-45 rejected challenge and token responses that start with a UTF-8 byte order mark (#239).
contract_credited/contract_debitedeffects had no response mapping (#179).- Converters leaked
FormatException,OverflowExceptionandArgumentOutOfRangeExceptionfor malformed input instead ofJsonException, and theAssetandReserveconverters mis-read unknown nested properties (#201, #232). KeyPairconstruction-time validation lost during the multi-target change is restored (#202);Util.Hashno longer leaks aSHA256instance per call (#195).- The assemblies carry the release version: 15.x DLLs reported 12.0.0 (SDK) and 10.0.0 (XDR), and sent
X-Client-Version: 12.0.0.0with every request (#255). - The documentation build (#178).
Security
- Converters that hand-parse JSON reject duplicate properties, closing a parser-differential gap where those fields were last-value-wins (#201).
- The status and event-filter converters clamp and escape a rejected value in their exception messages instead of copying it whole, so a hostile payload cannot bloat or forge log lines (#232).
- The SEP-7, SEP-12 and SEP-38 clients use https only, cap response sizes, don't follow redirects, and reject duplicate JSON properties.
Documentation
- .NET MAUI compatibility report: Android emulator and four physical devices, trimming, and workarounds (#242).
- SEP compatibility matrices (#191, plus the SEP-7, SEP-12 and SEP-38 PRs); the RPC and Horizon matrices are re-pinned to v28.0.1 (#198).
- The 61 XML documentation warnings are fixed, and new ones now fail the build (#254).
Maintenance
- Testnet integration test suite, run in CI on every push to
main(#185, #196). RespectNullableAnnotationsfor JSON deserialization (#182) andFrozenDictionarylookup tables in the JSON converters (#180).- NuGet Trusted Publishing for the release pipeline (#203).
- The XDR generator names any feature-gated
#ifdefblock left in a schema (#252). - Agent skills to verify the SDK at its package boundary and the MAUI harness (#253).
Known limitations
- iOS has not been validated. The MAUI validation covered Android only; iOS simulator and device behaviour remain untested.
- SSE streaming on Android with the default HTTP handler delivers events late (about 47 s in our runs). Give the stream's request builder an
SseEventSourcethat uses aSocketsHttpHandler; the MAUI report has the snippet. - .NET 9 MAUI apps resolve the
net8.0build, whose libsodium has no Android binaries: add a reference toNSec.Cryptography26.4.0. .NET 10 MAUI apps need nothing extra.
Full Changelog: 15.1.0...16.0.0 · CHANGELOG