v17.0.0-rc.2
Pre-releasev17.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