Releases: stellar/js-stellar-sdk
Release list
v17.0.0-rc.2
v17.0.0-rc.2
Breaking Changes
- CAP-71
SOROBAN_CREDENTIALS_ADDRESS_V2credentials are now the default, on both ends of the auth flow.rpc.Server.simulateTransaction'suseUpgradedAuthandauthorizeInvocation'sauthV2both default totrue, so simulation asks RPC to record v2 entries andauthorizeInvocationbuilds them. Passfalseto either one for the legacySOROBAN_CREDENTIALS_ADDRESSformat. Both flags are transitional and become no-ops when v2 is mandatory in protocol 28. Two consequences: code that reads the credential arm by hand must handleaddressV2and not justaddress(or useinspectAuthEntry), and a hand-rolled signer that hardcodes the legacyENVELOPE_TYPE_SOROBAN_AUTHORIZATIONpreimage now produces signatures the network rejects, so usebuildAuthorizationEntryPreimageorauthorizeEntry, which pick the address-bound payload off the entry. SDK-driven signing (contract.Client,authorizeEntry,signAuthEntries) needs no change (#1562). simulateTransactionnow always sendsuseUpgradedAuthin the JSON-RPC request. It previously omitted the field when the flag was unset (#1562).
Added
xdr.encodeArray/xdr.decodeArray: encode or decode a whole list of XDR values as one length-prefixed blob (a 4-byte count, then the elements). This is the wire format of the array typedefs removed in rc.1, soxdr.LedgerEntryChanges.fromXDR(feeMetaXdr, "base64")becomesxdr.decodeArray(xdr.LedgerEntryChange, feeMetaXdr, "base64"). Both work with any XDR class and take an optionalXdrArrayOptionswithmaxLength(element-count cap, for bounded arrays likepeers<25>) andmaxDepth(#1660).rpc.Server.prepareTransactiontakes an optionaluseUpgradedAuthparameter, since its internal simulation now requests v2 credentials by default. Passfalsefor the legacy v1 format (#1562).
Fixed
-
The legacy
new xdr.SomeUnion(discriminant, value)form throws aTypeErrornaming the arm factory to call instead, on all 115 generated union types (#1640, #1658). Unions are abstract base classes exported as values, andabstractis erased at runtime, so the pre-v17 call built a base instance that silently discarded both arguments —Object.keys(m)was[]andm.typewasundefined. It only failed once something serialized it, withTypeError: this.toXdrObject is not a functionthrown from inside the SDK, naming neither the union nor the call that created it; anewin a module-level constant surfaced as the whole module failing at import. TypeScript already rejected the form (TS2511: Cannot create an instance of an abstract class), so this reaches plain JavaScript and TypeScript run without a type-check pass.xdr.Int64/xdr.Uint64/xdr.Int32/xdr.Uint32have guarded their equivalent legacy form since 17.0.0-rc.1; unions now match.-new xdr.TransactionMeta(3, transactionMetaV3); +xdr.TransactionMeta.v3(transactionMetaV3);
-
XdrLargeIntencoding errors name the actual constraint.toI64()/toI128()/toI256()reportedvalue too large for i64: <v>with no indication of the valid range, and now reportbigint value <v> for i64 out of range [<min>, <max>]. The width check reportedvalue too large for 64 bits (i128)even when the value was1— it rejects the declared type, not the value — and now reportscannot encode i128 as 64 bits.toNumber()printed its safe-integer range with the bounds reversed. For these range violations the error is unchanged apart from its text: the sameRangeErroron the same inputs (#1659). -
XdrLargeIntcoerces atoBigInt()hook result withBigInt(...)instead of requiring an exactbigint. A custom object whosetoBigInt()returns a bigint-convertible value — anumbersuch as5, or""— is now accepted and normalized rather than throwing; a result that cannot be converted ("abc",NaN,null,{}) still throws. This is what keepsvaluea genuinebigint: the range check compares with<and>, which yieldfalsefor a string orNaN, so without the coercion such a value passed every check andtoNumber()returnedNaNinstead of throwing (#1659). -
equals()on XDR values is now callable from TypeScript on union types likexdr.ScVal,xdr.TransactionEnvelope, andxdr.Memo— which is what the SDK's accessors return (#1630, #1637). The parameter was typed as polymorphicthis, which reduces toneveron a union, so every call failed with TS2345 even though the runtime worked. The parameter is nowXdrValue, so comparing two different XDR types compiles and returnsfalse. -
Keypair.verifyandKeypair.verifyMessagethrow aTypeErrorfor arguments whose type they don't accept, instead of returningfalse(#1649). Both previously swallowed every error and reportedfalse, so a caller mistake was indistinguishable from an invalid signature.verifyrequiresdatato be aUint8Arrayandsignatureto be either aUint8Arrayor anxdr.Signature;verifyMessagetakes the samesignatureand amessagethat is a string or aUint8Array. Anything else now throws — a hex/base64 signature string, a plain array of byte values, thexdr.DecoratedSignaturethattx.signatures[0]holds, or amessagethat is neither string nor bytes. A well-formed signature that doesn't match still returnsfalse. Accepting anxdr.Signature— whatDecoratedSignature.signatureholds — meanskp.verify(tx.hash(), tx.signatures[0].signature)works again.authorizeEntrylikewise rejects a signer result it would have passed on unchecked — a callback returning none of its three shapes, a non-bytessignature, a non-stringpublicKey, or asignatureScValthat isn't anxdr.ScVal.-if (kp.verifyMessage(untrustedInput, signature)) { grant(); } +if (typeof untrustedInput === "string" && kp.verifyMessage(untrustedInput, signature)) { grant(); }
Full Changelog: v17.0.0-rc.1...v17.0.0-rc.2
v17.0.0-rc.1
v17.0.0-rc.1
Breaking Changes
-
Public APIs use
Uint8Arrayinstead of Node'sBuffer(#1457). Methods that returnedBuffer(e.g.hash(),Keypair'ssign/rawPublicKey/rawSecretKey,StrKey.decode*,Transaction.hash(),rpc.Server.getContractWasmByHash,getLiquidityPoolId(),AuthEntrySignature.signature, and the signing payload passed to aSigningCallback) now return a plainUint8Array, so Buffer-only conveniences like.toString("hex")and.equals()on results must be replaced — seedocs/UINT8ARRAY_MIGRATION.mdfor method-by-method recipes. Byte inputs still acceptBuffer(it's aUint8Arraysubclass), with three exceptions: aSigningCallbackmay no longer resolve to a rawArrayBuffer(wrap it in aUint8Array),SorobanDataBuilder's constructor no longer accepts non-Uint8Arraytyped arrays, andMemo.textno longer accepts a plainnumber[](see the next entry). Thebufferdependency is gone (base32.js, which needed a Buffer global, is replaced by@exodus/bytes), and browsers/edge runtimes need no Buffer polyfill. -
Memo.textno longer accepts a plainnumber[]. Passnew Uint8Array(arr)instead (#1457). Through 16.2.0 it took astring, a plain array, or aBuffer, and rejected a bareUint8Array. AUint8Arrayis now the canonical byte input, and a plain array is the only input lost.Memo.text([])was a valid zero-byte memo and now throws. The error message is unchanged (Expects string or Uint8Array, max 28 bytes), so code that matches on it still works. Seedocs/UINT8ARRAY_MIGRATION.md§ 3. -
The
xdrnamespace is rebuilt on@stellar/js-xdrv5, and every XDR value now has a different API (#1422). The wire format is unchanged: bytes and base64 written by older SDKs still decode, and vice versa. Any code that reads or buildsxdr.*values must be updated. The main shifts:- Start here:
docs/XDR_MIGRATION.mdcovers every change below with before/after examples and a quick-reference table. - Unions are discriminated classes.
.switch()becomes a.typestring literal, arm getters like.contractData()become properties, andnew xdr.LedgerEntryData(disc, val)becomes a factory call such asxdr.LedgerEntryData.contractData(val). - Enums are singletons, not factory calls:
xdr.ContractDataDurability.persistent()becomesxdr.ContractDataDurability.persistent. - Primitives are plain JS values. Integers are
numberorbigintinstead of class wrappers,LargeIntsubclasses are gone, byte fields areUint8Array, and fields arereadonly. - Absent optional fields decode to
nullinstead ofundefined, so=== undefinedchecks silently stop matching. Prefer== null. - Acronyms in method names collapse to single-initial-cap form, with no back-compat aliases (e.g.
validateXDR()is nowvalidateXdr()). This reaches beyond thexdrnamespace to the wrapper classes:Transaction.toXDR(),TransactionBuilder.fromXDR(),Operation.fromXDRObject(),Asset.toXDRObject(),contract.AssembledTransaction.toXDR()and others all gained theXdrspelling. - Struct field names are unchanged, but a few type names moved:
UInt128Parts/UInt256Partsare nowUint128Parts/Uint256Parts,ThresholdIndicesis nowThresholdIndexes, and the typedef aliasesDuration,TimePoint,SequenceNumber,ScVec,ScMap,LedgerEntryChanges,ContractCostParams,SorobanAuthorizationEntries,ScString,ScSymbol,String32,String64, andSponsorshipDescriptorare gone in favor of what they stood for. - New:
toJson()/fromJson()for SEP-0051 JSON,toXdrObject()/fromXdrObject()on XDR values, andequals()for structural comparison. Failures throwxdr.XdrError, which is now exported. - Removed:
ReaderandWriter; the v4 runtime type constructors (Hyper,UnsignedHyper,Option,Opaque,VarOpaque,XDRArray,XDRString,Bool,SignedInt,UnsignedInt), plus top-levelHyper/UnsignedHyper/cereal; andxdr.scvSortedMap(use the top-levelscvSortedMap). ScIntandXdrLargeIntlost their.intproperty; read.value(abigint) instead, and notevalueOf()now returns abigint.
- Start here:
-
Rebuilding the XDR layer changed a few SDK-level behaviors that don't involve typing
xdr.yourself. Most of these fail silently, so they won't surface as compile errors (#1422):scValToNativereturns aUint8Arrayfor anscvStringwhose contents aren't valid UTF-8. It previously always returned a string, substituting U+FFFD — its byte-returning branch was unreachable. Guards liketypeof result === "string"and calls likeresult.startsWith(...)are now data-dependent. (scvSymbolfollows the same rule, but the host restricts symbols to[_0-9A-Za-z], so a symbol that came off the network always decodes to a string.) The same applies tocontract.Spec.scValToNativeandcontract.Spec.funcResToNativeforBytes/BytesN, which returnUint8Array; those are generically typed, so TypeScript won't flag it.Operation.fromXdrObjectdecodesmanageData'sname,setOptions'shomeDomain, andrevokeSponsorship's data-entry name as UTF-8 rather than ASCII. Only bytes ≥0x80decode differently, and stellar-core rejects those in all three fields, so no valid operation is affected — but snapshots taken over synthetic or forged XDR will change ([0xC3, 0xA9]now decodes to"é", was"C)"). See the migration guide for the round-trip details.SorobanDataBuilderstill chains, and its setters still mutate the builder. What changed is one level down: because XDR fields arereadonlynow,setReadOnly/setReadWrite/setResourcesreplace the internal data rather than edit it in place. Two consequences: a footprint you captured fromgetFootprint()before one of those calls is a stale snapshot, so re-read it afterward; and you can no longer configure the builder through that object (builder.getFootprint().readOnly(keys)) — call the setters instead.MuxedAccount.setIdno longer mutates anxdr.MuxedAccountyou already obtained fromtoXdrObject(); call it again aftersetId.
-
HorizonApi.TransactionFailedExtras'sresult_codes.operationsis now optional (operations?: string[]). Horizon omits the field when a transaction fails a transaction-level check (e.g.tx_bad_seq) and no operations were evaluated, so the type now matches the wire format. UnderstrictNullChecks, unguarded reads of the raw response (extras.result_codes.operations.map(...)) no longer compile; guard them, or useTransactionFailedError.getResultCodes(), which normalizes the omitted field to[](#1527).
Added
rpc.Server.getExternalRefWasmHash(ref): resolves a CAP-85 external executable reference to the 32-byte Wasm hash it names by reading the persistent tag entry on the owner contract (#1577).- The XDR schema covers CAP-83 (empty transaction set values), adding a
stellarValueEmptyTxSetarm toxdr.StellarValueType(#1577). - The XDR schema covers CAP-85 (external contract executables), adding a
contractExecutableExternalRefarm toxdr.ContractExecutableType— anexecutableOwneraddress plus atag— and anscvExecutableTagarm toxdr.ScValType(#1577).
Changed
scValToNativeconverts anscvExecutableTagto its tag: a string when the bytes are valid UTF-8, otherwise the raw bytes (same rule asscvString) (#1577).buildInvocationTreerenders CAP-85 external-executable creations instead of throwing.CreateInvocation.typegains an"external"case, whose details live in a newexternalfield (owner,tag,address,salt, andconstructorArgsforCREATE_CONTRACT_V2).tagisstring | Uint8Array— an executable tag is an unboundedSCString, so a binary one is returned as raw bytes rather than lossily decoded (#1577).StrKey.decode*and the underlyingdecodeChecknow validate the encoded string's length against the requested strkey type before decoding it. Two consequences: a long attacker-supplied string is rejected up front instead of driving a ful...
v16.2.0
v16.2.0
Added
rpc.Server.simulateTransactionaccepts an optionaluseUpgradedAuthflag, andcontract.AssembledTransactionaccepts it as a method option (useUpgradedAuth) or per-call (tx.simulate({ useUpgradedAuth: true })). When set, RPC simulation records v2 address credentials (CAP-71) instead of the legacy v1 credentials. It only affects the recording auth modes and is silently ignored on hosts that cannot emit v2 credentials. The flag is deprecated from the start: it is transitional and becomes a no-op once the network returns v2 credentials by default (protocol 28) (#1562).@stellar/stellar-sdk/basesubpath export: import offline primitives likeStrKeyandKeypairwithout loading Horizon, RPC, or the SEP helpers and their networking dependencies (#1550).authorizeEntry/authorizeInvocationsigning callbacks now receive the 32-byte signing payload (hash(preimage.toXDR())) as a second argument alongside the preimage, so signers — including HSMs and remote signers that only accept a digest — never have to re-derive it. Existing single-argument callbacks are unaffected (#1532).authorizeEntry/authorizeInvocationnow support non-Ed25519 signers: the signing callback may return{ signatureScVal: xdr.ScVal, address?: string }, and the givenScValis written verbatim as the credentials' signature — no Ed25519 verification, no{public_key, signature}map, noscvVecwrapping. This lets smart-wallet / custom-account contracts (whose__check_authexpects its own signature structure) use the helper instead of hand-rolling preimage construction and credential assembly. The optionaladdressroutes the signature to a specific credential node, likeforAddress(#1530).contract.Signer: an interface pairing anaddresswith the SEP-43signTransactionand optionalsignAuthEntrymethods, pluscontract.KeypairSigner, aKeypair-backed implementation. ThesignTransactionandsignAuthEntryoptions — onClientOptions,MethodOptions, andAssembledTransaction'ssign/signAndSend/signAuthEntries— now accept aSigneror a bareKeypairin addition to a callback. Adds thecontract.SignTransactionLikeandcontract.SignAuthEntryLiketypes. WhensignAuthEntriesgets aSignerorKeypair, its default targetaddressis now the signer's own address rather thanpublicKey. Existing callbacks work unchanged; one type-only caveat: the option fields are no longer plain function types, so derive callback shapes fromcontract.SignTransaction/contract.SignAuthEntryinstead of the option field (#1567).contract.Specnow reads SEP-48 event declarations:events()andfindEvent(name, occurrence?)list a contract's declared events,parseEvent(topics, data)decodes a fired event into{ name, data }, with topic-carried params merged intodata(returnsundefinedwhen nothing matches), andeventTopicFilter(name, topicValues?, occurrence?)builds agetEventsfilter row, with"*"for any topic param left unset. Generated client bindings gain a typed<Name>Eventinterface per event, aContractEventunion, aparseEvent()method, and per-event<name>EventFilter()methods. A contract may declare the same event name more than once (composed modules each emitting their owntransfer); each declaration gets its own interface and filter method, andoccurrence— a 0-based index in declaration order — selects among them. Generated names receive a numeric suffix when needed to avoid a collision, andstellar-sdk bindingswarns about duplicate declarations and renames. Adds thecontract.ParsedEventtype (#1556, #1565, #1572).
Fixed
Spec.scValToNativenow handles contract values typed asVal
(scSpecTypeVal) by delegating to the genericscValToNativeconverter,
mirroring the encoding-side support added in [#1485]. Decoding a response
containing aVal-typed string, symbol, vec, or map — e.g. a struct with a
Vec<Val>field — no longer throws
ScSpecType scSpecTypeVal was not string or symbol; each value decodes to
its natural native representation (Address→ string,u32→ number,
Symbol→ string, vecs/maps recurse).
(#1551)
Full Changelog: v16.1.0...v16.2.0
v16.1.0
v16.1.0
Added
inspectAuthEntry(entry): decodes axdr.SorobanAuthorizationEntryinto a typed summary — credential type, authorizing address, nonce,signatureExpirationLedger, and asignerslist covering top-level credentials and CAP-71 delegates. Adds theAuthEntryInfo,AuthEntrySigner,AuthEntrySignature, andAuthEntryCredentialTypetypes (#1529).checkAuthEntryReadiness(entry, currentLedgerSeq): reports whether an auth entry is ready to submit —{ ready, expired, unsignedBy }— as a pure decode with no network call (#1529).Spec.nativeToScValnow supports contract parameters typed asVal(scSpecTypeVal), so raw JS values can be passed toVal-typed arguments without buildingxdr.ScValobjects by hand (#1485).rpc.Server.queryContract<T>(contractId, method, args?, networkPassphrase?): a one-line read-only contract call that returns{ result, isReadCall }, no transaction assembly or signing. Works for Wasm contracts and built-in Stellar Asset Contracts (SACs) (#1502).rpc.Server.getContractMethods(contractId, networkPassphrase?): lists a contract's callable methods and their signatures. Adds theApi.ContractMethodandApi.ContractMethodInputtypes (#1502).rpc.Server.getContractInstance(contractId): returns a contract'sxdr.ScContractInstance(#1501).contract.Client.from,fromWasm, andfromWasmHashare now generic (<T>) and returnClient & T, giving typed contract methods without code generation.Tdefaults tounknown, so untyped calls are unchanged (#1502).ClientOptions.server: pass an existingrpc.Servertocontract.Client.fromto reuse its transport instead of building a new one (#1502).Keypair.signMessage(message)andKeypair.verifyMessage(message, signature): sign and verify arbitrary messages per SEP-53, matching the Python and Java SDKs and stellar-cli (#1513).TransactionFailedError: raised byHorizon.Server.submitTransactionandsubmitAsyncTransactionwhen Horizon rejects a transaction with result codes. ExtendsBadResponseErrorand addsgetResultCodes()andgetTransactionResult()(#1526).
Changed
HorizonApi.TransactionFailedResultCodesgained the transaction result codes it was missing:tx_bad_sponsorship,tx_bad_min_seq_age_or_gap,tx_malformed,tx_soroban_invalid, andtx_frozen_key_accessed(#1526).contract.Client.fromnow supports built-in Stellar Asset Contracts (SACs), building the client from the embedded SAC spec instead of downloading Wasm (#1501).rpc.Server.getContractWasmByContractIdnow rejects a SAC with a structured{ code: 400 }error pointing tocontract.Client.from. The not-found rejection is now{ code: 404, message: "Could not obtain contract instance from server" }(#1501).- The UMD (
dist/) build now setsinlineDynamicImportsso the single-file bundle stays whole despite the SAC spec's lazyimport()(#1501).
Fixed
Horizon.Server.submitTransactionandsubmitAsyncTransactionnow reject with SDK error types on HTTP failures, as documented: aTransactionFailedErrorfor Horizon result codes, aBadResponseErrorotherwise. The wrapping branch used to be unreachable, so failures leaked through as raw HTTP-client errors.err.response.dataanderr.response.statusare unchanged; the original error is now preserved aserr.cause(#1526).Federation.Serverresolution methods (resolveAddress,resolveAccountId,resolveTransactionId,forDomain) had the same unreachable branch and now reject HTTP failures withBadResponseError(#1526).contract.AssembledTransaction.needsNonInvokerSigningBynow treats an emptyscvVecsignature as unsigned, matching the existingscvVoidcheck. Such entries used to count as already signed and were left off the list (#1529).Spec.nativeToScValno longer misclassifies plain objects that have aconstructorkey, and handles null-prototype objects (Object.create(null)) (#1485).
Contributors
- @Shadow-MMN made their first contribution in #1485, @quietbits, @Ryang-21
Full Changelog: v16.0.1...v16.1.0
v16.0.1
v16.0.1
Fixed
- Fixed the ESM library build so the inlined
@stellar/js-xdrsource resolves
correctly under Yarn PnP (and Node's native ESM resolver). Because the build
preserves modules, Rollup emits js-xdr's source into a nested package scope,
but js-xdr does not declaretype: "module", so Node and Yarn PnP parsed those
preserved files as CommonJS and failed to resolve them. Rollup now marks the
emitted js-xdr package astype: "module"so its source is parsed as ESM
#1484.
Full Changelog: v16.0.0...v16.0.1
v16.0.0
v16.0.0
There are a few major updates in this release:
- JS Stellar Base (
@stellar/stellar-base) was rewritten
in TypeScript, which provides proper type definitions and fixes
inconsistencies caused by manual type declarations. ([#1399]) - JS Stellar Base is now merged into the JS Stellar SDK. Everything lives in one
place now. ([#1399]) - The JS SDK now has better tree-shaking, which should result in a lighter
bundle size. ([#1397]) - Protocol 27 support: the XDR was regenerated for CAP-71, and the Soroban
authorization helpers can build and sign the new address-bound
(SOROBAN_CREDENTIALS_ADDRESS_V2) and delegated
(SOROBAN_CREDENTIALS_ADDRESS_WITH_DELEGATES) credential types. The legacy
SOROBAN_CREDENTIALS_ADDRESS(V1) credential remains the default;
ADDRESS_V2is opt-in (see below), as it is only valid on networks that have
activated CAP-71. ([#1429], [#1450])
1. Breaking Changes
These break code, builds, or installs until you change something.
Install & runtime
-
Drop
@stellar/stellar-basefrom your dependencies if you were importing
it manually. It is now bundled into@stellar/stellar-sdk. Remove the package
and switch all imports from@stellar/stellar-baseto@stellar/stellar-sdk.
([#1399]) -
Upgrade to Node 22 or later.
engines.nodeis now>=22.0.0; CI tests
against[22, 24]. ([#1408]) -
Stop using the default import.
import StellarBase from '@stellar/stellar-sdk'no longer works. Use
import * as StellarBaseor named imports. ([#1396]) -
Adjust deep
lib/imports. Library output paths moved:- ESM at
lib/esm/, - CJS at
lib/cjs/, - axios variants at
lib/axios/esm/andlib/axios/cjs/, - type declarations alongside the ESM output at
lib/esm/(e.g.
lib/esm/index.d.ts).
The
dist/UMD bundle filenames are unchanged. ([#1397]) - ESM at
-
The package.json
browserfield and browser export conditions were
removed. Bundlers no longer auto-substitute the prebuilt UMD bundle for the
package entry — they bundle the ESM/CJS source directly. Load the UMD build
from its explicitdist/path if you need it. ([#1396], [#1397])
HTTP client
- Default HTTP client switched from axios to fetch. If you rely on axios
behavior (interceptors, adapters, regression fallback), import from the
alternative entry point@stellar/stellar-sdk/axiosinstead. ([#1394]) - The
no-eventsourcebuild variant is gone.eventsourcewas upgraded to
v4, which usesfetchinternally and works in every supported runtime (Node
22+, browsers, Deno, Bun,workerd). Remove anyno-eventsource
build/import; the default build covers all environments. ([#1395]) - The
/no-axiosand/minimalsubpath exports are removed, along with
their/contractand/rpcvariants. Axios is now opt-in through the
@stellar/stellar-sdk/axiosfamily (/axios,/axios/contract,
/axios/rpc, and@stellar/stellar-sdk/http-client/axios); the minimal build
no longer exists. ([#1394]) Horizon.Server.serverURLandrpc.Server.serverURLare now nativeURL
objects (andreadonly) instead ofurijsURIinstances. Code that called
urijs methods on them (server.serverURL.protocol(),.clone(),.segment(),
.query()) must move to the WHATWGURLAPI (e.g.
serverURL.protocol === "https:",serverURL.hostname). ([#1402])
Transaction & TransactionBuilder
-
Transaction.minAccountSequenceAgeis nowbigint. The underlying XDR
type is 64-bit; consuming code must switch fromnumberto nativebigint
(the runtime value is no longer anxdr.UnsignedHyperobject either). ([#1399]) -
TransactionBuilder.setMinAccountSequenceAgerequiresbigint. Pass
60ninstead of60.TransactionBuilderOptions.minAccountSequenceAgeis
alsobigint. ([#1399]) -
Transaction.extraSignersis nowxdr.SignerKey[]. It always was at
runtime — only the type was wrong. UseSignerKey.encodeSignerKey()to get
StrKey strings. ([#1399]) -
Transactionis no longer generic. Remove<TMemo, TOps>parameters
(e.g.,Transaction<Memo<MemoType.Text>>no longer compiles). ([#1399]) -
Operation.isValidAmount(),Operation.constructAmountRequirementsError(),
andOperation.setSourceAccount()are no longer on the runtimeOperation
class. JavaScript callers that reached for these need to drop them — they
remain only as internal helpers insrc/base/util/operations.ts. ([#1399]) -
Revoke-sponsorship operation
typeis split into seven strings.
"revokeSponsorship"is replaced by"revokeAccountSponsorship",
"revokeTrustlineSponsorship","revokeOfferSponsorship",
"revokeDataSponsorship","revokeClaimableBalanceSponsorship",
"revokeLiquidityPoolSponsorship","revokeSignerSponsorship". The runtime
always returned the specific strings; consumers that switched ontypeshould
update their cases. ([#1399])
Asset, Keypair, signing helpers
Asset.codeandAsset.issuerare nowreadonly. Stop mutating them in
place — construct a newAssetinstead. ([#1399])Asset.issueris typed asstring | undefined. Native assets have no
issuer; add nullish checks. ([#1399])FastSigningconstant removed. Signing now goes through
@noble/ed25519exclusively — drop the import. ([#1401])TransactionIremoved. UseTransactionBaseinstead. ([#1399])authorizeInvocation()takes a single object parameter. Switch from
authorizeInvocation(signer, validUntilLedgerSeq, invocation, publicKey, networkPassphrase)
to
authorizeInvocation({ signer, validUntilLedgerSeq, invocation, networkPassphrase, publicKey }).
([#1399])authorizeEntry()no longer defaultsnetworkPassphraseto
Networks.FUTURENET. Pass the network passphrase explicitly at every call
site. ([#1399])
2. Should know (type-only or behavior changes that may surface)
Won't fail at install. May fail at compile time, or change behavior at runtime,
depending on how you use the API.
TypeScript-only
CreateInvocation.tokenrenamed toCreateInvocation.assetin the type
declarations — runtime was already.asset. ([#1399])ScIntTypeadds'timepoint'and'duration'. Exhaustive switches on
ScIntTypeneed new cases. ([#1399])XdrLargeInt.getType()returnsScIntType | undefinedinstead of a raw
lowercased string; non-integer types yieldundefined. ([#1399])SorobanDataBuilder.fromXDRreturn type corrected to
xdr.SorobanTransactionData. Runtime always returned this — only the type was
wrong. ([#1399])SetOptions.clearFlags/setFlagsaccept arbitrary numeric bitmasks.
The type was widened fromAuthFlagtoAuthFlags(AuthFlag | (number & {})),
so you can now pass combined flag values without a cast. This is a widening —
existing code keeps compiling. ([#1399])supportMuxingparameter removed fromdecodeAddressToMuxedAccount/
encodeMuxedAccountToAddresstype declarations. It was silently ignored at
runtime. ([#1399])
Runtime behavior
Keypair.rawSecretKey()throws on public-key-only instances with
Error("no secret seed available")instead of returningundefined. ([#1399])TransactionBase.txreturns a defensive copy — mutating it is now a SILENT
no-op.txno longer returns the live XDR object, so setting fields through
it (tx.tx.fee(…),tx.tx.operations(…),tx.tx.cond(…), etc.) mutates a
throwaway copy and has no effect on the transaction that gets signed or
serialized. It does not throw and no types change, so code that relied on
in-place mutation keeps compiling and running while silently signing the
unmodified transaction. Rebuild instead viaTransactionBuilder/
TransactionBuilder.cloneFrom. ([#1399])TransactionBuilderconstructor preserves0nfor
minAccountSequenceAgeinstead of coercing falsy values tonull. This may
fliphasV2Preconditions()totruewhen the field is set to0n. ([#1399])toXDRPricerejects more bad input earlier. Zero/negative/NaN/
Infinitynumeric prices now throw"price must be positive"before reaching
best_r(). Zero denominators also rejected (d <= 0). ([#1399])- Constructor and input validation now throw where the SDK was previously
lenient.MuxedAccountvalidates uint64 IDs;Claimantrejects falsy
destinations;AccountrejectsNaNsequences;Memois fully immutable and
throws on invalid types instead of returningnull;Memo.id()rejects
non-plain-digit strings;allow_trustthrows whenauthorizeis missing;
setTrustLineFlagsrejects non-boolean flag values;Asset.getAssetType()
throws for unknown types instead of returning"unknown". (set_optionsalso
no longer mutates the caller's signer fields.) ([#1399]) TransactionBuildernow validates and throws.build()throws on
total-fee overflow pastuint32max;cloneFrom()throws on zero-operation
inputs; the constructor rejects negative or invertedtimebounds/
ledgerbounds. ([#1399])TransactionBuilder.cloneFromexcludes the Soroban resource fee when
deriving the per-operation base fee. Previously the resource fee was treated
as part of the inclusion fee and re-added onbuild(), doubling it (or
overflowinguint32and throwing). If a malformed transaction declares a
resource fee that meets or exceeds its total fee, the subtraction is skipped
and the full fee is used as-is. ([#1478])- **
Operation.setOptions()rejec...
v16.0.0-rc.2
v16.0.0-rc.2
Changed
- Soroban auth defaults back to the legacy
SOROBAN_CREDENTIALS_ADDRESS(V1) credential, with the CAP-71SOROBAN_CREDENTIALS_ADDRESS_V2credential now available behind an opt-in instead of forced on.ADDRESS_V2is only valid on networks that have upgraded to protocol 27, so emitting it before upgrading would fail submission; the opt-in keeps the default safe while letting you exercise V2 against networks that already support it. The default will flip to V2 in protocol 28. (#1450)rpc.Server.simulateTransactiongained a 4th optional argument,authV2(defaultfalse). Whentrue, theauthV2request flag is sent so simulation returnsADDRESS_V2auth entries; otherwise the flag is omitted and legacyADDRESSentries are returned.authorizeInvocationgained an optionalauthV2field on its params object (defaultfalse) selecting betweenADDRESSandADDRESS_V2credentials.contract.Client/AssembledTransactionacceptauthV2inMethodOptions, threaded through to simulation.
Fixed
- Resolved a performance regression in Keypair.random() #1449.
Note: the rpc.Server.simulateTransaction authV2 argument and theMethodOptions.authV2 option were removed before the v16.0.0 final release — authV2 on authorizeInvocation is the supported opt-in. See v16.0.0 above.
v16.0.0-rc.1
v16.0.0-rc.1: Protocol 27
There are a few major updates in this release detailed in the migration guide:
- JS Stellar Base (
@stellar/stellar-base) was rewritten
in TypeScript, which provides proper type definitions and fixes
inconsistencies caused by manual type declarations. ([#1399]) - JS Stellar Base is now merged into the JS Stellar SDK. Everything lives in one
place now. ([#1399]) - The JS SDK now has better tree-shaking, which should result in a lighter
bundle size. ([#1397]) - Protocol 27 support: the XDR was regenerated for CAP-71, and the Soroban
authorization helpers now build and sign the new address-bound
(SOROBAN_CREDENTIALS_ADDRESS_V2) and delegated
(SOROBAN_CREDENTIALS_ADDRESS_WITH_DELEGATES) credential types. ([#1429])
1. Breaking Changes
These break code, builds, or installs until you change something.
Install & runtime
-
Drop
@stellar/stellar-basefrom your dependencies if you were importing
it manually. It is now bundled into@stellar/stellar-sdk. Remove the package
and switch all imports from@stellar/stellar-baseto@stellar/stellar-sdk.
([#1399]) -
Upgrade to Node 22 or later.
engines.nodeis now>=22.0.0; CI tests
against[22, 24]. ([#1408]) -
Stop using the default import.
import StellarBase from '@stellar/stellar-sdk'no longer works. Use
import * as StellarBaseor named imports. ([#1396]) -
Adjust deep
lib/imports. Library output paths moved:- ESM at
lib/esm/, - CJS at
lib/cjs/, - axios variants at
lib/axios/esm/andlib/axios/cjs/, - type declarations alongside the ESM output at
lib/esm/(e.g.
lib/esm/index.d.ts).
The
dist/UMD bundle filenames are unchanged. ([#1397]) - ESM at
-
The package.json
browserfield and browser export conditions were
removed. Bundlers no longer auto-substitute the prebuilt UMD bundle for the
package entry — they bundle the ESM/CJS source directly. Load the UMD build
from its explicitdist/path if you need it. ([#1396], [#1397])
HTTP client
- Default HTTP client switched from axios to fetch. If you rely on axios
behavior (interceptors, adapters, regression fallback), import from the
alternative entry point@stellar/stellar-sdk/axiosinstead. ([#1394]) - The
no-eventsourcebuild variant is gone.eventsourcewas upgraded to
v4, which usesfetchinternally and works in every supported runtime (Node
22+, browsers, Deno, Bun,workerd). Remove anyno-eventsource
build/import; the default build covers all environments. ([#1395]) - The
/no-axiosand/minimalsubpath exports are removed, along with
their/contractand/rpcvariants. Axios is now opt-in through the
@stellar/stellar-sdk/axiosfamily (/axios,/axios/contract,
/axios/rpc, and@stellar/stellar-sdk/http-client/axios); the minimal build
no longer exists. ([#1394]) Horizon.Server.serverURLandrpc.Server.serverURLare now nativeURL
objects (andreadonly) instead ofurijsURIinstances. Code that called
urijs methods on them (server.serverURL.protocol(),.clone(),.segment(),
.query()) must move to the WHATWGURLAPI (e.g.
serverURL.protocol === "https:",serverURL.hostname). ([#1402])
Transaction & TransactionBuilder
-
Transaction.minAccountSequenceAgeis nowbigint. The underlying XDR
type is 64-bit; consuming code must switch fromnumberto nativebigint
(the runtime value is no longer anxdr.UnsignedHyperobject either). ([#1399]) -
TransactionBuilder.setMinAccountSequenceAgerequiresbigint. Pass
60ninstead of60.TransactionBuilderOptions.minAccountSequenceAgeis
alsobigint. ([#1399]) -
Transaction.extraSignersis nowxdr.SignerKey[]. It always was at
runtime — only the type was wrong. UseSignerKey.encodeSignerKey()to get
StrKey strings. ([#1399]) -
Transactionis no longer generic. Remove<TMemo, TOps>parameters
(e.g.,Transaction<Memo<MemoType.Text>>no longer compiles). ([#1399]) -
Operation.isValidAmount(),Operation.constructAmountRequirementsError(),
andOperation.setSourceAccount()are no longer on the runtimeOperation
class. JavaScript callers that reached for these need to drop them — they
remain only as internal helpers insrc/base/util/operations.ts. ([#1399]) -
Revoke-sponsorship operation
typeis split into seven strings.
"revokeSponsorship"is replaced by"revokeAccountSponsorship",
"revokeTrustlineSponsorship","revokeOfferSponsorship",
"revokeDataSponsorship","revokeClaimableBalanceSponsorship",
"revokeLiquidityPoolSponsorship","revokeSignerSponsorship". The runtime
always returned the specific strings; consumers that switched ontypeshould
update their cases. ([#1399])
Asset, Keypair, signing helpers
Asset.codeandAsset.issuerare nowreadonly. Stop mutating them in
place — construct a newAssetinstead. ([#1399])Asset.issueris typed asstring | undefined. Native assets have no
issuer; add nullish checks. ([#1399])FastSigningconstant removed. Signing now goes through
@noble/ed25519exclusively — drop the import. ([#1401])TransactionIremoved. UseTransactionBaseinstead. ([#1399])authorizeInvocation()takes a single object parameter. Switch from
authorizeInvocation(signer, validUntilLedgerSeq, invocation, publicKey, networkPassphrase)
to
authorizeInvocation({ signer, validUntilLedgerSeq, invocation, networkPassphrase, publicKey }).
([#1399])authorizeEntry()no longer defaultsnetworkPassphraseto
Networks.FUTURENET. Pass the network passphrase explicitly at every call
site. ([#1399])
2. Should know (type-only or behavior changes that may surface)
Won't fail at install. May fail at compile time, or change behavior at runtime,
depending on how you use the API.
TypeScript-only
CreateInvocation.tokenrenamed toCreateInvocation.assetin the type
declarations — runtime was already.asset. ([#1399])ScIntTypeadds'timepoint'and'duration'. Exhaustive switches on
ScIntTypeneed new cases. ([#1399])XdrLargeInt.getType()returnsScIntType | undefinedinstead of a raw
lowercased string; non-integer types yieldundefined. ([#1399])SorobanDataBuilder.fromXDRreturn type corrected to
xdr.SorobanTransactionData. Runtime always returned this — only the type was
wrong. ([#1399])SetOptions.clearFlags/setFlagsaccept arbitrary numeric bitmasks.
The type was widened fromAuthFlagtoAuthFlags(AuthFlag | (number & {})),
so you can now pass combined flag values without a cast. This is a widening —
existing code keeps compiling. ([#1399])supportMuxingparameter removed fromdecodeAddressToMuxedAccount/
encodeMuxedAccountToAddresstype declarations. It was silently ignored at
runtime. ([#1399])
Runtime behavior
Keypair.rawSecretKey()throws on public-key-only instances with
Error("no secret seed available")instead of returningundefined. ([#1399])TransactionBase.txreturns a defensive copy. External mutation no longer
affects the transaction that will be signed or serialized. If you were
intentionally mutatingtx, you'll need a different approach. ([#1399])TransactionBuilderconstructor preserves0nfor
minAccountSequenceAgeinstead of coercing falsy values tonull. This may
fliphasV2Preconditions()totruewhen the field is set to0n. ([#1399])toXDRPricerejects more bad input earlier. Zero/negative/NaN/
Infinitynumeric prices now throw"price must be positive"before reaching
best_r(). Zero denominators also rejected (d <= 0). ([#1399])- Constructor and input validation now throw where the SDK was previously
lenient.MuxedAccountvalidates uint64 IDs;Claimantrejects falsy
destinations;AccountrejectsNaNsequences;Memois fully immutable and
throws on invalid types instead of returningnull;Memo.id()rejects
non-plain-digit strings;allow_trustthrows whenauthorizeis missing;
setTrustLineFlagsrejects non-boolean flag values;Asset.getAssetType()
throws for unknown types instead of returning"unknown". (set_optionsalso
no longer mutates the caller's signer fields.) ([#1399]) TransactionBuildernow validates and throws.build()throws on
total-fee overflow pastuint32max;cloneFrom()throws on zero-operation
inputs; the constructor rejects negative or invertedtimebounds/
ledgerbounds. ([#1399])Operation.setOptions()rejects malformed numeric strings. Flag, weight,
and threshold fields (setFlags,clearFlags,masterWeight, the signer
weight, and the*Thresholdoptions) now reject values like"123abc"that
parseFloat()previously accepted by reading only the leading digits. ([#1399])XdrLargeInt/ScIntbuilt from an array of limbs now decode correctly.
Passing multiple big-endian integer parts (fori128/u128/i256/u256)
previously wrapped them in a nested array and produced wrong values; the limbs
are now passed through correctly. ([#1399])- Large-integer conversions reject out-of-range / malformed input.
nativeToScValbounds-checksu32/i32values and rejects non-numeric
strings like"123abc";XdrLargeInt.toI128()/toI256()reject unsigned
values exceeding the signed range instead of silently flipping the sign bit.
([#1399]) - **
bignumber.jsupgraded to v11; v9'sDEBUGguar...
v15.1.0
v15.1.0
Fixed
- Security:
FederationServer.createForDomainand theFederationServerconstructor now validate domains per RFC 1035, rejecting malformed domains before issuing federation orstellar.tomlrequests. Port numbers are also accepted (#1393). RpcServer.pollTransactionoff-by-one: the polling loop used<instead of<=, causing one fewer attempt than configured(#1373).requestAirdroperror path: fixed incorrect property access (error.response.detailinstead oferror.response.data.detail) when checking forcreateAccountAlreadyExist(#1373).Spec.typeRefnow properly handlesscSpecTypeResultby returning the JSON schema for theokType, instead of silently breaking out of the switch (#1373).structToJsonSchemanow placesadditionalProperties: falseon the schema object itself rather than incorrectly nesting it insideproperties(#1373).- Fixed bigint-to-U32/I32 conversion in
SpecusingNumber(val)instead ofval as number(a no-op for bigints) (#1373). - WASM custom section parser: when a section was skipped (invalid name length), the offset was not advanced, causing an infinite loop or incorrect parsing of subsequent sections (#1373).
FederationServerURL mutation:resolveAddress,resolveAccountId, andresolveTransactionIdmutated the sharedserverURLby appending query params on each call. Fixed by cloning the URL before modifying (#1373).CallBuilder.stream()URL mutation:stream()mutated the sharedthis.urlby adding query params, corrupting the builder for subsequent calls. Fixed by cloning the URL (#1373).AssembledTransactionrestore path: whenbuildWithOpwas used and automatic state restoration was needed, the rebuild incorrectly reconstructed the operation viacontract.call()instead of reusing the original operation (#1373).SERVER_TIME_MAPport collision: the Horizon time-sync cache keyed entries by hostname only, so two servers on different ports of the same host shared a cache entry. Fixed by including the port in the key (#1373).Spec.funcResToNativenow correctly returns anErrinstance when a contract function with aResultreturn type returns an error, instead of throwing while decoding it as theOktype (#1373).- SEP-10:
verifyChallengeTxSignersnow rejects challenges signed only by the server andclient_domainkey with no actual client signer, instead of returning an empty signers list (#1372). getAssetBalanceused incorrect flag bitmask constants (AuthRequiredFlag,AuthRevocableFlag,AuthClawbackEnabledFlag) which are account-level flags, not trustline-level flags. Replaced with the correct trustline flag bitmasks (0x1,0x2,0x4) (#1372).AssembledTransaction.simulatedid not clearthis.builtbefore re-simulating after a state restoration rebuild, causing it to assemble stale transaction data (#1372).AssembledTransaction.signAndSendmutated the sharedthis.options.submitflag to prevent double submission. Replaced with a wrapper aroundsignTransactionthat injectssubmit: falsewithout mutating shared state (#1372).- Fetch HTTP client: async request interceptors were not awaited — the synchronous
try/catchloop passed unresolved promise objects as the config. Replaced with a proper.then()chain matching Axios interceptor semantics (#1372). - Fetch HTTP client: cancellation now preserves custom cancel reasons and
isCancelno longer depends on exact error-message text (#1390). - Fetch HTTP client: instance default headers and params now merge correctly with per-request overrides on the no-axios / minimal builds, including requests that use bounded options (#1390).
- Fetch HTTP client:
maxRedirectsandmaxContentLengthwere silently ignored on the no-axios / minimal builds, turning SDK-set SSRF and DoS guards (StellarToml.Resolver.resolve,FederationServer) into no-ops. A new bounded adapter activates when either option is set, refusing redirects pastmaxRedirectsand streaming the response body with a running-total check so oversized responses abort mid-stream (#1390). - Fetch HTTP client: the no-axios bounded path now more closely matches Axios behavior for object request bodies,
baseURL, timeout errors, redirect method/body handling, and stripping credential-bearing headers on cross-origin redirects (#1390). src/bindings/config.tsimported../../package.jsonwith a relative path that resolved incorrectly for thelib/no-axios/andlib/minimal/build outputs, making those libs unloadable. Replaced with the__PACKAGE_VERSION__compile-time define (#1390).- Updated the production
axiosdependency from1.14.0to1.15.0(#1381).
Added
AccountResponseconstructor now uses explicit field-by-field assignment instead ofObject.entriesdynamic assignment for type safety (#1373).- Added
transactionscollection toApi.AccountRecordandAccountResponse(#1373). - Added range checks for U32/I32 values in
Spec: bigint values are now validated against min/max bounds before conversion, throwing aRangeErrorinstead of silently truncating (#1373). rpc.Server.getLatestLedger()now includescloseTime,headerXdr, andmetadataXdrin the typed response, withheaderXdr/metadataXdrparsed into XDR objects instead of raw base64 strings (#1389).
Deprecated
BalanceResponse.revocableis deprecated in favor ofauthorizedToMaintainLiabilities, which correctly reflects the trustline flag semantics (#1372).
Full Changelog: v15.0.1...v15.1.0
v15.0.1: Protocol 26
v15.0.1: Protocol 26
Breaking Changes
- XDR has been upgraded to support Protocol 26, please refer to the
@stellar/stellar-baserelease notes for details and other breaking changes.
Fixed
- Sanitize identifiers and escape string literals in generated TypeScript bindings to prevent code injection via malicious contract spec names.
sanitizeIdentifiernow strips non-identifier characters, and a newescapeStringLiteralhelper escapes quotes and newlines in string contexts (#1345). AssembledTransaction.fromXDR()andfromJSON()now validate that the deserialized transaction targets the expected contract, rejecting mismatched contract IDs and non-invokeContract operations. (#1349).- Pin exact version on axios dependency (#1365)
Contributors
Full Changelog: v14.6.1...v15.0.1