Skip to content

Releases: stellar/js-stellar-sdk

v17.0.0-rc.2

v17.0.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@Ryang-21 Ryang-21 released this 17 Aug 21:29
27de307

v17.0.0-rc.2

Breaking Changes

  • CAP-71 SOROBAN_CREDENTIALS_ADDRESS_V2 credentials are now the default, on both ends of the auth flow. rpc.Server.simulateTransaction's useUpgradedAuth and authorizeInvocation's authV2 both default to true, so simulation asks RPC to record v2 entries and authorizeInvocation builds them. Pass false to either one for the legacy SOROBAN_CREDENTIALS_ADDRESS format. 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 handle addressV2 and not just address (or use inspectAuthEntry), and a hand-rolled signer that hardcodes the legacy ENVELOPE_TYPE_SOROBAN_AUTHORIZATION preimage now produces signatures the network rejects, so use buildAuthorizationEntryPreimage or authorizeEntry, which pick the address-bound payload off the entry. SDK-driven signing (contract.Client, authorizeEntry, signAuthEntries) needs no change (#1562).
  • simulateTransaction now always sends useUpgradedAuth in 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, so xdr.LedgerEntryChanges.fromXDR(feeMetaXdr, "base64") becomes xdr.decodeArray(xdr.LedgerEntryChange, feeMetaXdr, "base64"). Both work with any XDR class and take an optional XdrArrayOptions with maxLength (element-count cap, for bounded arrays like peers<25>) and maxDepth (#1660).
  • rpc.Server.prepareTransaction takes an optional useUpgradedAuth parameter, since its internal simulation now requests v2 credentials by default. Pass false for the legacy v1 format (#1562).

Fixed

  • The legacy new xdr.SomeUnion(discriminant, value) form throws a TypeError naming the arm factory to call instead, on all 115 generated union types (#1640, #1658). Unions are abstract base classes exported as values, and abstract is erased at runtime, so the pre-v17 call built a base instance that silently discarded both arguments — Object.keys(m) was [] and m.type was undefined. It only failed once something serialized it, with TypeError: this.toXdrObject is not a function thrown from inside the SDK, naming neither the union nor the call that created it; a new in 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.Uint32 have guarded their equivalent legacy form since 17.0.0-rc.1; unions now match.

    -new xdr.TransactionMeta(3, transactionMetaV3);
    +xdr.TransactionMeta.v3(transactionMetaV3);
  • XdrLargeInt encoding errors name the actual constraint. toI64()/toI128()/toI256() reported value too large for i64: <v> with no indication of the valid range, and now report bigint value <v> for i64 out of range [<min>, <max>]. The width check reported value too large for 64 bits (i128) even when the value was 1 — it rejects the declared type, not the value — and now reports cannot 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 same RangeError on the same inputs (#1659).

  • XdrLargeInt coerces a toBigInt() hook result with BigInt(...) instead of requiring an exact bigint. A custom object whose toBigInt() returns a bigint-convertible value — a number such as 5, or "" — is now accepted and normalized rather than throwing; a result that cannot be converted ("abc", NaN, null, {}) still throws. This is what keeps value a genuine bigint: the range check compares with < and >, which yield false for a string or NaN, so without the coercion such a value passed every check and toNumber() returned NaN instead of throwing (#1659).

  • equals() on XDR values is now callable from TypeScript on union types like xdr.ScVal, xdr.TransactionEnvelope, and xdr.Memo — which is what the SDK's accessors return (#1630, #1637). The parameter was typed as polymorphic this, which reduces to never on a union, so every call failed with TS2345 even though the runtime worked. The parameter is now XdrValue, so comparing two different XDR types compiles and returns false.

  • Keypair.verify and Keypair.verifyMessage throw a TypeError for arguments whose type they don't accept, instead of returning false (#1649). Both previously swallowed every error and reported false, so a caller mistake was indistinguishable from an invalid signature. verify requires data to be a Uint8Array and signature to be either a Uint8Array or an xdr.Signature; verifyMessage takes the same signature and a message that is a string or a Uint8Array. Anything else now throws — a hex/base64 signature string, a plain array of byte values, the xdr.DecoratedSignature that tx.signatures[0] holds, or a message that is neither string nor bytes. A well-formed signature that doesn't match still returns false. Accepting an xdr.Signature — what DecoratedSignature.signature holds — means kp.verify(tx.hash(), tx.signatures[0].signature) works again. authorizeEntry likewise rejects a signer result it would have passed on unchecked — a callback returning none of its three shapes, a non-bytes signature, a non-string publicKey, or a signatureScVal that isn't an xdr.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 Pre-release
Pre-release

Choose a tag to compare

@Ryang-21 Ryang-21 released this 11 Aug 00:02
1a6b117

v17.0.0-rc.1

Breaking Changes

  • Public APIs use Uint8Array instead of Node's Buffer (#1457). Methods that returned Buffer (e.g. hash(), Keypair's sign/rawPublicKey/rawSecretKey, StrKey.decode*, Transaction.hash(), rpc.Server.getContractWasmByHash, getLiquidityPoolId(), AuthEntrySignature.signature, and the signing payload passed to a SigningCallback) now return a plain Uint8Array, so Buffer-only conveniences like .toString("hex") and .equals() on results must be replaced — see docs/UINT8ARRAY_MIGRATION.md for method-by-method recipes. Byte inputs still accept Buffer (it's a Uint8Array subclass), with three exceptions: a SigningCallback may no longer resolve to a raw ArrayBuffer (wrap it in a Uint8Array), SorobanDataBuilder's constructor no longer accepts non-Uint8Array typed arrays, and Memo.text no longer accepts a plain number[] (see the next entry). The buffer dependency is gone (base32.js, which needed a Buffer global, is replaced by @exodus/bytes), and browsers/edge runtimes need no Buffer polyfill.

  • Memo.text no longer accepts a plain number[]. Pass new Uint8Array(arr) instead (#1457). Through 16.2.0 it took a string, a plain array, or a Buffer, and rejected a bare Uint8Array. A Uint8Array is 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. See docs/UINT8ARRAY_MIGRATION.md § 3.

  • The xdr namespace is rebuilt on @stellar/js-xdr v5, 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 builds xdr.* values must be updated. The main shifts:

    • Start here: docs/XDR_MIGRATION.md covers every change below with before/after examples and a quick-reference table.
    • Unions are discriminated classes. .switch() becomes a .type string literal, arm getters like .contractData() become properties, and new xdr.LedgerEntryData(disc, val) becomes a factory call such as xdr.LedgerEntryData.contractData(val).
    • Enums are singletons, not factory calls: xdr.ContractDataDurability.persistent() becomes xdr.ContractDataDurability.persistent.
    • Primitives are plain JS values. Integers are number or bigint instead of class wrappers, LargeInt subclasses are gone, byte fields are Uint8Array, and fields are readonly.
    • Absent optional fields decode to null instead of undefined, so === undefined checks silently stop matching. Prefer == null.
    • Acronyms in method names collapse to single-initial-cap form, with no back-compat aliases (e.g. validateXDR() is now validateXdr()). This reaches beyond the xdr namespace to the wrapper classes: Transaction.toXDR(), TransactionBuilder.fromXDR(), Operation.fromXDRObject(), Asset.toXDRObject(), contract.AssembledTransaction.toXDR() and others all gained the Xdr spelling.
    • Struct field names are unchanged, but a few type names moved: UInt128Parts / UInt256Parts are now Uint128Parts / Uint256Parts, ThresholdIndices is now ThresholdIndexes, and the typedef aliases Duration, TimePoint, SequenceNumber, ScVec, ScMap, LedgerEntryChanges, ContractCostParams, SorobanAuthorizationEntries, ScString, ScSymbol, String32, String64, and SponsorshipDescriptor are gone in favor of what they stood for.
    • New: toJson() / fromJson() for SEP-0051 JSON, toXdrObject() / fromXdrObject() on XDR values, and equals() for structural comparison. Failures throw xdr.XdrError, which is now exported.
    • Removed: Reader and Writer; the v4 runtime type constructors (Hyper, UnsignedHyper, Option, Opaque, VarOpaque, XDRArray, XDRString, Bool, SignedInt, UnsignedInt), plus top-level Hyper / UnsignedHyper / cereal; and xdr.scvSortedMap (use the top-level scvSortedMap).
    • ScInt and XdrLargeInt lost their .int property; read .value (a bigint) instead, and note valueOf() now returns a bigint.
  • 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):

    • scValToNative returns a Uint8Array for an scvString whose contents aren't valid UTF-8. It previously always returned a string, substituting U+FFFD — its byte-returning branch was unreachable. Guards like typeof result === "string" and calls like result.startsWith(...) are now data-dependent. (scvSymbol follows 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 to contract.Spec.scValToNative and contract.Spec.funcResToNative for Bytes / BytesN, which return Uint8Array; those are generically typed, so TypeScript won't flag it.
    • Operation.fromXdrObject decodes manageData's name, setOptions's homeDomain, and revokeSponsorship's data-entry name as UTF-8 rather than ASCII. Only bytes ≥ 0x80 decode 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.
    • SorobanDataBuilder still chains, and its setters still mutate the builder. What changed is one level down: because XDR fields are readonly now, setReadOnly / setReadWrite / setResources replace the internal data rather than edit it in place. Two consequences: a footprint you captured from getFootprint() 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.setId no longer mutates an xdr.MuxedAccount you already obtained from toXdrObject(); call it again after setId.
  • HorizonApi.TransactionFailedExtras's result_codes.operations is 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. Under strictNullChecks, unguarded reads of the raw response (extras.result_codes.operations.map(...)) no longer compile; guard them, or use TransactionFailedError.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 stellarValueEmptyTxSet arm to xdr.StellarValueType (#1577).
  • The XDR schema covers CAP-85 (external contract executables), adding a contractExecutableExternalRef arm to xdr.ContractExecutableType — an executableOwner address plus a tag — and an scvExecutableTag arm to xdr.ScValType (#1577).

Changed

  • scValToNative converts an scvExecutableTag to its tag: a string when the bytes are valid UTF-8, otherwise the raw bytes (same rule as scvString) (#1577).
  • buildInvocationTree renders CAP-85 external-executable creations instead of throwing. CreateInvocation.type gains an "external" case, whose details live in a new external field (owner, tag, address, salt, and constructorArgs for CREATE_CONTRACT_V2). tag is string | Uint8Array — an executable tag is an unbounded SCString, so a binary one is returned as raw bytes rather than lossily decoded (#1577).
  • StrKey.decode* and the underlying decodeCheck now 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...
Read more

v16.2.0

Choose a tag to compare

@Ryang-21 Ryang-21 released this 29 Jul 20:51
0336c41

v16.2.0

Added

  • rpc.Server.simulateTransaction accepts an optional useUpgradedAuth flag, and contract.AssembledTransaction accepts 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/base subpath export: import offline primitives like StrKey and Keypair without loading Horizon, RPC, or the SEP helpers and their networking dependencies (#1550).
  • authorizeEntry / authorizeInvocation signing 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 / authorizeInvocation now support non-Ed25519 signers: the signing callback may return { signatureScVal: xdr.ScVal, address?: string }, and the given ScVal is written verbatim as the credentials' signature — no Ed25519 verification, no {public_key, signature} map, no scvVec wrapping. This lets smart-wallet / custom-account contracts (whose __check_auth expects its own signature structure) use the helper instead of hand-rolling preimage construction and credential assembly. The optional address routes the signature to a specific credential node, like forAddress (#1530).
  • contract.Signer: an interface pairing an address with the SEP-43 signTransaction and optional signAuthEntry methods, plus contract.KeypairSigner, a Keypair-backed implementation. The signTransaction and signAuthEntry options — on ClientOptions, MethodOptions, and AssembledTransaction's sign / signAndSend / signAuthEntries — now accept a Signer or a bare Keypair in addition to a callback. Adds the contract.SignTransactionLike and contract.SignAuthEntryLike types. When signAuthEntries gets a Signer or Keypair, its default target address is now the signer's own address rather than publicKey. Existing callbacks work unchanged; one type-only caveat: the option fields are no longer plain function types, so derive callback shapes from contract.SignTransaction / contract.SignAuthEntry instead of the option field (#1567).
  • contract.Spec now reads SEP-48 event declarations: events() and findEvent(name, occurrence?) list a contract's declared events, parseEvent(topics, data) decodes a fired event into { name, data }, with topic-carried params merged into data (returns undefined when nothing matches), and eventTopicFilter(name, topicValues?, occurrence?) builds a getEvents filter row, with "*" for any topic param left unset. Generated client bindings gain a typed <Name>Event interface per event, a ContractEvent union, a parseEvent() method, and per-event <name>EventFilter() methods. A contract may declare the same event name more than once (composed modules each emitting their own transfer); each declaration gets its own interface and filter method, and occurrence — a 0-based index in declaration order — selects among them. Generated names receive a numeric suffix when needed to avoid a collision, and stellar-sdk bindings warns about duplicate declarations and renames. Adds the contract.ParsedEvent type (#1556, #1565, #1572).

Fixed

  • Spec.scValToNative now handles contract values typed as Val
    (scSpecTypeVal) by delegating to the generic scValToNative converter,
    mirroring the encoding-side support added in [#1485]. Decoding a response
    containing a Val-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

Choose a tag to compare

@Ryang-21 Ryang-21 released this 22 Jul 20:16
62830ba

v16.1.0

Added

  • inspectAuthEntry(entry): decodes a xdr.SorobanAuthorizationEntry into a typed summary — credential type, authorizing address, nonce, signatureExpirationLedger, and a signers list covering top-level credentials and CAP-71 delegates. Adds the AuthEntryInfo, AuthEntrySigner, AuthEntrySignature, and AuthEntryCredentialType types (#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.nativeToScVal now supports contract parameters typed as Val (scSpecTypeVal), so raw JS values can be passed to Val-typed arguments without building xdr.ScVal objects 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 the Api.ContractMethod and Api.ContractMethodInput types (#1502).
  • rpc.Server.getContractInstance(contractId): returns a contract's xdr.ScContractInstance (#1501).
  • contract.Client.from, fromWasm, and fromWasmHash are now generic (<T>) and return Client & T, giving typed contract methods without code generation. T defaults to unknown, so untyped calls are unchanged (#1502).
  • ClientOptions.server: pass an existing rpc.Server to contract.Client.from to reuse its transport instead of building a new one (#1502).
  • Keypair.signMessage(message) and Keypair.verifyMessage(message, signature): sign and verify arbitrary messages per SEP-53, matching the Python and Java SDKs and stellar-cli (#1513).
  • TransactionFailedError: raised by Horizon.Server.submitTransaction and submitAsyncTransaction when Horizon rejects a transaction with result codes. Extends BadResponseError and adds getResultCodes() and getTransactionResult() (#1526).

Changed

  • HorizonApi.TransactionFailedResultCodes gained the transaction result codes it was missing: tx_bad_sponsorship, tx_bad_min_seq_age_or_gap, tx_malformed, tx_soroban_invalid, and tx_frozen_key_accessed (#1526).
  • contract.Client.from now supports built-in Stellar Asset Contracts (SACs), building the client from the embedded SAC spec instead of downloading Wasm (#1501).
  • rpc.Server.getContractWasmByContractId now rejects a SAC with a structured { code: 400 } error pointing to contract.Client.from. The not-found rejection is now { code: 404, message: "Could not obtain contract instance from server" } (#1501).
  • The UMD (dist/) build now sets inlineDynamicImports so the single-file bundle stays whole despite the SAC spec's lazy import() (#1501).

Fixed

  • Horizon.Server.submitTransaction and submitAsyncTransaction now reject with SDK error types on HTTP failures, as documented: a TransactionFailedError for Horizon result codes, a BadResponseError otherwise. The wrapping branch used to be unreachable, so failures leaked through as raw HTTP-client errors. err.response.data and err.response.status are unchanged; the original error is now preserved as err.cause (#1526).
  • Federation.Server resolution methods (resolveAddress, resolveAccountId, resolveTransactionId, forDomain) had the same unreachable branch and now reject HTTP failures with BadResponseError (#1526).
  • contract.AssembledTransaction.needsNonInvokerSigningBy now treats an empty scvVec signature as unsigned, matching the existing scvVoid check. Such entries used to count as already signed and were left off the list (#1529).
  • Spec.nativeToScVal no longer misclassifies plain objects that have a constructor key, and handles null-prototype objects (Object.create(null)) (#1485).

Contributors

Full Changelog: v16.0.1...v16.1.0

v16.0.1

Choose a tag to compare

@Ryang-21 Ryang-21 released this 18 Jun 21:45
962fad4

v16.0.1

Fixed

  • Fixed the ESM library build so the inlined @stellar/js-xdr source 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 declare type: "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 as type: "module" so its source is parsed as ESM
    #1484.

Full Changelog: v16.0.0...v16.0.1

v16.0.0

Choose a tag to compare

@Ryang-21 Ryang-21 released this 15 Jun 22:16
9999beb

v16.0.0

Migration guide

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_V2 is 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-base from 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-base to @stellar/stellar-sdk.
    ([#1399])

  • Upgrade to Node 22 or later. engines.node is 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 StellarBase or 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/ and lib/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])

  • The package.json browser field 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 explicit dist/ 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/axios instead. ([#1394])
  • The no-eventsource build variant is gone. eventsource was upgraded to
    v4, which uses fetch internally and works in every supported runtime (Node
    22+, browsers, Deno, Bun, workerd). Remove any no-eventsource
    build/import; the default build covers all environments. ([#1395])
  • The /no-axios and /minimal subpath exports are removed, along with
    their /contract and /rpc variants. Axios is now opt-in through the
    @stellar/stellar-sdk/axios family (/axios, /axios/contract,
    /axios/rpc, and @stellar/stellar-sdk/http-client/axios); the minimal build
    no longer exists. ([#1394])
  • Horizon.Server.serverURL and rpc.Server.serverURL are now native URL
    objects
    (and readonly) instead of urijs URI instances. Code that called
    urijs methods on them (server.serverURL.protocol(), .clone(), .segment(),
    .query()) must move to the WHATWG URL API (e.g.
    serverURL.protocol === "https:", serverURL.hostname). ([#1402])

Transaction & TransactionBuilder

  • Transaction.minAccountSequenceAge is now bigint. The underlying XDR
    type is 64-bit; consuming code must switch from number to native bigint
    (the runtime value is no longer an xdr.UnsignedHyper object either). ([#1399])

  • TransactionBuilder.setMinAccountSequenceAge requires bigint. Pass
    60n instead of 60. TransactionBuilderOptions.minAccountSequenceAge is
    also bigint. ([#1399])

  • Transaction.extraSigners is now xdr.SignerKey[]. It always was at
    runtime — only the type was wrong. Use SignerKey.encodeSignerKey() to get
    StrKey strings. ([#1399])

  • Transaction is no longer generic. Remove <TMemo, TOps> parameters
    (e.g., Transaction<Memo<MemoType.Text>> no longer compiles). ([#1399])

  • Operation.isValidAmount(), Operation.constructAmountRequirementsError(),
    and Operation.setSourceAccount() are no longer on the runtime Operation
    class.
    JavaScript callers that reached for these need to drop them — they
    remain only as internal helpers in src/base/util/operations.ts. ([#1399])

  • Revoke-sponsorship operation type is 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 on type should
    update their cases. ([#1399])

Asset, Keypair, signing helpers

  • Asset.code and Asset.issuer are now readonly. Stop mutating them in
    place — construct a new Asset instead. ([#1399])
  • Asset.issuer is typed as string | undefined. Native assets have no
    issuer; add nullish checks. ([#1399])
  • FastSigning constant removed. Signing now goes through
    @noble/ed25519 exclusively — drop the import. ([#1401])
  • TransactionI removed. Use TransactionBase instead. ([#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 defaults networkPassphrase to
    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.token renamed to CreateInvocation.asset in the type
    declarations — runtime was already .asset. ([#1399])
  • ScIntType adds 'timepoint' and 'duration'. Exhaustive switches on
    ScIntType need new cases. ([#1399])
  • XdrLargeInt.getType() returns ScIntType | undefined instead of a raw
    lowercased string; non-integer types yield undefined. ([#1399])
  • SorobanDataBuilder.fromXDR return type corrected to
    xdr.SorobanTransactionData. Runtime always returned this — only the type was
    wrong. ([#1399])
  • SetOptions.clearFlags / setFlags accept arbitrary numeric bitmasks.
    The type was widened from AuthFlag to AuthFlags (AuthFlag | (number & {})),
    so you can now pass combined flag values without a cast. This is a widening —
    existing code keeps compiling. ([#1399])
  • supportMuxing parameter removed from decodeAddressToMuxedAccount /
    encodeMuxedAccountToAddress type 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 returning undefined. ([#1399])
  • TransactionBase.tx returns a defensive copy — mutating it is now a SILENT
    no-op.
    tx no 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 via TransactionBuilder /
    TransactionBuilder.cloneFrom. ([#1399])
  • TransactionBuilder constructor preserves 0n for
    minAccountSequenceAge
    instead of coercing falsy values to null. This may
    flip hasV2Preconditions() to true when the field is set to 0n. ([#1399])
  • toXDRPrice rejects more bad input earlier. Zero/negative/NaN/
    Infinity numeric 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.
    MuxedAccount validates uint64 IDs; Claimant rejects falsy
    destinations; Account rejects NaN sequences; Memo is fully immutable and
    throws on invalid types instead of returning null; Memo.id() rejects
    non-plain-digit strings; allow_trust throws when authorize is missing;
    setTrustLineFlags rejects non-boolean flag values; Asset.getAssetType()
    throws for unknown types instead of returning "unknown". (set_options also
    no longer mutates the caller's signer fields.) ([#1399])
  • TransactionBuilder now validates and throws. build() throws on
    total-fee overflow past uint32 max; cloneFrom() throws on zero-operation
    inputs; the constructor rejects negative or inverted timebounds /
    ledgerbounds. ([#1399])
  • TransactionBuilder.cloneFrom excludes 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 on build(), doubling it (or
    overflowing uint32 and 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...
Read more

v16.0.0-rc.2

v16.0.0-rc.2 Pre-release
Pre-release

Choose a tag to compare

@Ryang-21 Ryang-21 released this 11 Jun 18:08
21c722e

v16.0.0-rc.2

migration guide:

Changed

  • Soroban auth defaults back to the legacy SOROBAN_CREDENTIALS_ADDRESS (V1) credential, with the CAP-71 SOROBAN_CREDENTIALS_ADDRESS_V2 credential now available behind an opt-in instead of forced on. ADDRESS_V2 is 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.simulateTransaction gained a 4th optional argument, authV2 (default false). When true, the authV2 request flag is sent so simulation returns ADDRESS_V2 auth entries; otherwise the flag is omitted and legacy ADDRESS entries are returned.
    • authorizeInvocation gained an optional authV2 field on its params object (default false) selecting between ADDRESS and ADDRESS_V2 credentials.
    • contract.Client / AssembledTransaction accept authV2 in MethodOptions, 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 Pre-release
Pre-release

Choose a tag to compare

@Ryang-21 Ryang-21 released this 05 Jun 23:29
d0657f1

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-base from 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-base to @stellar/stellar-sdk.
    ([#1399])

  • Upgrade to Node 22 or later. engines.node is 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 StellarBase or 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/ and lib/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])

  • The package.json browser field 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 explicit dist/ 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/axios instead. ([#1394])
  • The no-eventsource build variant is gone. eventsource was upgraded to
    v4, which uses fetch internally and works in every supported runtime (Node
    22+, browsers, Deno, Bun, workerd). Remove any no-eventsource
    build/import; the default build covers all environments. ([#1395])
  • The /no-axios and /minimal subpath exports are removed, along with
    their /contract and /rpc variants. Axios is now opt-in through the
    @stellar/stellar-sdk/axios family (/axios, /axios/contract,
    /axios/rpc, and @stellar/stellar-sdk/http-client/axios); the minimal build
    no longer exists. ([#1394])
  • Horizon.Server.serverURL and rpc.Server.serverURL are now native URL
    objects
    (and readonly) instead of urijs URI instances. Code that called
    urijs methods on them (server.serverURL.protocol(), .clone(), .segment(),
    .query()) must move to the WHATWG URL API (e.g.
    serverURL.protocol === "https:", serverURL.hostname). ([#1402])

Transaction & TransactionBuilder

  • Transaction.minAccountSequenceAge is now bigint. The underlying XDR
    type is 64-bit; consuming code must switch from number to native bigint
    (the runtime value is no longer an xdr.UnsignedHyper object either). ([#1399])

  • TransactionBuilder.setMinAccountSequenceAge requires bigint. Pass
    60n instead of 60. TransactionBuilderOptions.minAccountSequenceAge is
    also bigint. ([#1399])

  • Transaction.extraSigners is now xdr.SignerKey[]. It always was at
    runtime — only the type was wrong. Use SignerKey.encodeSignerKey() to get
    StrKey strings. ([#1399])

  • Transaction is no longer generic. Remove <TMemo, TOps> parameters
    (e.g., Transaction<Memo<MemoType.Text>> no longer compiles). ([#1399])

  • Operation.isValidAmount(), Operation.constructAmountRequirementsError(),
    and Operation.setSourceAccount() are no longer on the runtime Operation
    class.
    JavaScript callers that reached for these need to drop them — they
    remain only as internal helpers in src/base/util/operations.ts. ([#1399])

  • Revoke-sponsorship operation type is 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 on type should
    update their cases. ([#1399])

Asset, Keypair, signing helpers

  • Asset.code and Asset.issuer are now readonly. Stop mutating them in
    place — construct a new Asset instead. ([#1399])
  • Asset.issuer is typed as string | undefined. Native assets have no
    issuer; add nullish checks. ([#1399])
  • FastSigning constant removed. Signing now goes through
    @noble/ed25519 exclusively — drop the import. ([#1401])
  • TransactionI removed. Use TransactionBase instead. ([#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 defaults networkPassphrase to
    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.token renamed to CreateInvocation.asset in the type
    declarations — runtime was already .asset. ([#1399])
  • ScIntType adds 'timepoint' and 'duration'. Exhaustive switches on
    ScIntType need new cases. ([#1399])
  • XdrLargeInt.getType() returns ScIntType | undefined instead of a raw
    lowercased string; non-integer types yield undefined. ([#1399])
  • SorobanDataBuilder.fromXDR return type corrected to
    xdr.SorobanTransactionData. Runtime always returned this — only the type was
    wrong. ([#1399])
  • SetOptions.clearFlags / setFlags accept arbitrary numeric bitmasks.
    The type was widened from AuthFlag to AuthFlags (AuthFlag | (number & {})),
    so you can now pass combined flag values without a cast. This is a widening —
    existing code keeps compiling. ([#1399])
  • supportMuxing parameter removed from decodeAddressToMuxedAccount /
    encodeMuxedAccountToAddress type 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 returning undefined. ([#1399])
  • TransactionBase.tx returns a defensive copy. External mutation no longer
    affects the transaction that will be signed or serialized. If you were
    intentionally mutating tx, you'll need a different approach. ([#1399])
  • TransactionBuilder constructor preserves 0n for
    minAccountSequenceAge
    instead of coercing falsy values to null. This may
    flip hasV2Preconditions() to true when the field is set to 0n. ([#1399])
  • toXDRPrice rejects more bad input earlier. Zero/negative/NaN/
    Infinity numeric 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.
    MuxedAccount validates uint64 IDs; Claimant rejects falsy
    destinations; Account rejects NaN sequences; Memo is fully immutable and
    throws on invalid types instead of returning null; Memo.id() rejects
    non-plain-digit strings; allow_trust throws when authorize is missing;
    setTrustLineFlags rejects non-boolean flag values; Asset.getAssetType()
    throws for unknown types instead of returning "unknown". (set_options also
    no longer mutates the caller's signer fields.) ([#1399])
  • TransactionBuilder now validates and throws. build() throws on
    total-fee overflow past uint32 max; cloneFrom() throws on zero-operation
    inputs; the constructor rejects negative or inverted timebounds /
    ledgerbounds. ([#1399])
  • Operation.setOptions() rejects malformed numeric strings. Flag, weight,
    and threshold fields (setFlags, clearFlags, masterWeight, the signer
    weight, and the *Threshold options) now reject values like "123abc" that
    parseFloat() previously accepted by reading only the leading digits. ([#1399])
  • XdrLargeInt / ScInt built from an array of limbs now decode correctly.
    Passing multiple big-endian integer parts (for i128/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.
    nativeToScVal bounds-checks u32/i32 values 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.js upgraded to v11; v9's DEBUG guar...
Read more

v15.1.0

Choose a tag to compare

@Ryang-21 Ryang-21 released this 04 May 18:42
c5eafa2

v15.1.0

Fixed

  • Security: FederationServer.createForDomain and the FederationServer constructor now validate domains per RFC 1035, rejecting malformed domains before issuing federation or stellar.toml requests. Port numbers are also accepted (#1393).
  • RpcServer.pollTransaction off-by-one: the polling loop used < instead of <=, causing one fewer attempt than configured(#1373).
  • requestAirdrop error path: fixed incorrect property access (error.response.detail instead of error.response.data.detail) when checking for createAccountAlreadyExist (#1373).
  • Spec.typeRef now properly handles scSpecTypeResult by returning the JSON schema for the okType, instead of silently breaking out of the switch (#1373).
  • structToJsonSchema now places additionalProperties: false on the schema object itself rather than incorrectly nesting it inside properties (#1373).
  • Fixed bigint-to-U32/I32 conversion in Spec using Number(val) instead of val 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).
  • FederationServer URL mutation: resolveAddress, resolveAccountId, and resolveTransactionId mutated the shared serverURL by appending query params on each call. Fixed by cloning the URL before modifying (#1373).
  • CallBuilder.stream() URL mutation: stream() mutated the shared this.url by adding query params, corrupting the builder for subsequent calls. Fixed by cloning the URL (#1373).
  • AssembledTransaction restore path: when buildWithOp was used and automatic state restoration was needed, the rebuild incorrectly reconstructed the operation via contract.call() instead of reusing the original operation (#1373).
  • SERVER_TIME_MAP port 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.funcResToNative now correctly returns an Err instance when a contract function with a Result return type returns an error, instead of throwing while decoding it as the Ok type (#1373).
  • SEP-10: verifyChallengeTxSigners now rejects challenges signed only by the server and client_domain key with no actual client signer, instead of returning an empty signers list (#1372).
  • getAssetBalance used 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.simulate did not clear this.built before re-simulating after a state restoration rebuild, causing it to assemble stale transaction data (#1372).
  • AssembledTransaction.signAndSend mutated the shared this.options.submit flag to prevent double submission. Replaced with a wrapper around signTransaction that injects submit: false without mutating shared state (#1372).
  • Fetch HTTP client: async request interceptors were not awaited — the synchronous try/catch loop 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 isCancel no 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: maxRedirects and maxContentLength were 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 past maxRedirects and 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.ts imported ../../package.json with a relative path that resolved incorrectly for the lib/no-axios/ and lib/minimal/ build outputs, making those libs unloadable. Replaced with the __PACKAGE_VERSION__ compile-time define (#1390).
  • Updated the production axios dependency from 1.14.0 to 1.15.0 (#1381).

Added

  • AccountResponse constructor now uses explicit field-by-field assignment instead of Object.entries dynamic assignment for type safety (#1373).
  • Added transactions collection to Api.AccountRecord and AccountResponse (#1373).
  • Added range checks for U32/I32 values in Spec: bigint values are now validated against min/max bounds before conversion, throwing a RangeError instead of silently truncating (#1373).
  • rpc.Server.getLatestLedger() now includes closeTime, headerXdr, and metadataXdr in the typed response, with headerXdr/metadataXdr parsed into XDR objects instead of raw base64 strings (#1389).

Deprecated

  • BalanceResponse.revocable is deprecated in favor of authorizedToMaintainLiabilities, which correctly reflects the trustline flag semantics (#1372).

Full Changelog: v15.0.1...v15.1.0

v15.0.1: Protocol 26

Choose a tag to compare

@Shaptic Shaptic released this 31 Mar 03:50
00e3c70

v15.0.1: Protocol 26

Breaking Changes

  • XDR has been upgraded to support Protocol 26, please refer to the @stellar/stellar-base release 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. sanitizeIdentifier now strips non-identifier characters, and a new escapeStringLiteral helper escapes quotes and newlines in string contexts (#1345).
  • AssembledTransaction.fromXDR() and fromJSON() 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