Skip to content

v17.0.0-rc.2

Pre-release
Pre-release

Choose a tag to compare

@Ryang-21 Ryang-21 released this 17 Aug 21:29
· 4 commits to main since this release
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