Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable changes to the Aptos TypeScript SDK will be captured in this file. T

## Fixed

- Fix `serializeAsBytes is not a function` error when wallet extensions (e.g. Petra) bundle an older SDK and serialize v6 transaction objects. Added `serializeEntryFunctionBytesCompat()` helper with runtime fallback to the pre-v6 `bcsToBytes()` + `serializeBytes()` pattern (DVR-143)
- Fix simple function arguments for `Vector<Option<T>>` types: BCS-encoded values (e.g. `AccountAddress.ONE`) passed as elements of `vector<Option<address>>` are now automatically wrapped in `MoveOption` instead of throwing a type mismatch error
- Resolve moderate security advisories in `confidential-assets` dev tooling by pinning transitive `file-type` and `yauzl` (via `@swc/cli` → `@xhmikosr/downloader`) to patched releases
- Remove hardcoded `maxGasAmount: 2000` from e2e tests (Account Derivation APIs, WebAuthn submission) that caused `MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS` failures after the on-chain minimum gas increase
Expand Down
36 changes: 21 additions & 15 deletions src/bcs/serializable/movePrimitives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ import {
MAX_I256_BIG_INT,
} from "../consts";
import { Deserializer } from "../deserializer";
import { Serializable, Serializer, ensureBoolean, validateNumberInRange } from "../serializer";
import {
Serializable,
Serializer,
ensureBoolean,
serializeEntryFunctionBytesCompat,
validateNumberInRange,
} from "../serializer";
import { TransactionArgument } from "../../transactions/instances/transactionArgument";
import { AnyNumber, Uint16, Uint32, Uint8, Int8, Int16, Int32, ScriptTransactionArgumentVariants } from "../../types";

Expand Down Expand Up @@ -76,14 +82,14 @@ export class Bool extends Serializable implements TransactionArgument {
/**
* Serializes the current instance for use in an entry function by converting it to a byte sequence.
* This allows the instance to be properly formatted for serialization in transactions.
* Uses the optimized serializeAsBytes method to reduce allocations.
* Uses serializeAsBytes when available, with a fallback for older Serializer versions.
*
* @param serializer - The serializer instance used to serialize the byte sequence.
* @group Implementation
* @category BCS
*/
serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

/**
Expand Down Expand Up @@ -138,7 +144,7 @@ export class U8 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -174,7 +180,7 @@ export class U16 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -209,7 +215,7 @@ export class U32 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -247,7 +253,7 @@ export class U64 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -283,7 +289,7 @@ export class U128 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -319,7 +325,7 @@ export class U256 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -354,7 +360,7 @@ export class I8 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -390,7 +396,7 @@ export class I16 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -425,7 +431,7 @@ export class I32 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -463,7 +469,7 @@ export class I64 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -499,7 +505,7 @@ export class I128 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -535,7 +541,7 @@ export class I256 extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down
10 changes: 5 additions & 5 deletions src/bcs/serializable/moveStructs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Bool, U128, U16, U256, U32, U64, U8, I8, I16, I32, I64, I128, I256 } from "./movePrimitives";
import { Serializable, Serializer } from "../serializer";
import { Serializable, Serializer, serializeEntryFunctionBytesCompat } from "../serializer";
import { Deserializable, Deserializer } from "../deserializer";
import { AnyNumber, HexInput, ScriptTransactionArgumentVariants } from "../../types";
import { Hex } from "../../core/hex";
Expand Down Expand Up @@ -69,14 +69,14 @@ export class MoveVector<T extends Serializable & EntryFunctionArgument>
/**
* Serializes the current instance into a byte sequence suitable for entry functions.
* This allows the data to be properly formatted for transmission or storage.
* Uses the optimized serializeAsBytes method to reduce allocations.
* Uses serializeAsBytes when available, with a fallback for older Serializer versions.
*
* @param serializer - The serializer instance used to serialize the byte sequence.
* @group Implementation
* @category BCS
*/
serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}
Comment on lines 76 to 80
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc here states this path “Uses the optimized serializeAsBytes method”, but the implementation now calls serializeEntryFunctionBytesCompat() which may use serializeAsBytes or a compatibility fallback depending on the Serializer instance. Please adjust the comment to describe the compatibility behavior so it stays accurate.

Copilot uses AI. Check for mistakes.

/**
Expand Down Expand Up @@ -493,7 +493,7 @@ export class MoveString extends Serializable implements TransactionArgument {
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

serializeForScriptFunction(serializer: Serializer): void {
Expand Down Expand Up @@ -530,7 +530,7 @@ export class MoveOption<T extends Serializable & EntryFunctionArgument>
}

serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
}

/**
Expand Down
19 changes: 19 additions & 0 deletions src/bcs/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,25 @@ export abstract class Serializable {
}
}

/**
* Serialize a Serializable value as length-prefixed bytes into a Serializer,
* with backwards compatibility for older Serializer implementations that lack
* the `serializeAsBytes` method. This is critical for cross-version compatibility
* when SDK objects built with a newer SDK are serialized by an older SDK's Serializer
* (e.g., wallet extensions bundling an older SDK version).
*
* @param serializer - The serializer to write into (may be from any SDK version).
* @param value - The Serializable value to serialize as bytes.
*/
export function serializeEntryFunctionBytesCompat(serializer: Serializer, value: Serializable): void {
if (typeof (serializer as { serializeAsBytes?: unknown }).serializeAsBytes === "function") {
serializer.serializeAsBytes(value);
} else {
const bcsBytes = value.bcsToBytes();
serializer.serializeBytes(bcsBytes);
}
}

/**
* Minimum buffer growth increment to avoid too many small reallocations.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/core/accountAddress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { bytesToHex, hexToBytes } from "@noble/hashes/utils";
import { Serializable, Serializer } from "../bcs/serializer";
import { Serializable, Serializer, serializeEntryFunctionBytesCompat } from "../bcs/serializer";
import { Deserializer } from "../bcs/deserializer";
import { ParsingError, ParsingResult } from "./common";
import { TransactionArgument } from "../transactions/instances/transactionArgument";
Expand Down Expand Up @@ -240,14 +240,14 @@ export class AccountAddress extends Serializable implements TransactionArgument
/**
* Serializes the current instance into a byte sequence suitable for entry functions.
* This allows for the proper encoding of data when interacting with entry functions in the blockchain.
* Uses the optimized serializeAsBytes method to reduce allocations.
* Uses serializeAsBytes when available, with a fallback for older Serializer versions.
*
* @param serializer - The serializer instance used to convert the data into bytes.
* @group Implementation
* @category Serialization
*/
serializeForEntryFunction(serializer: Serializer): void {
serializer.serializeAsBytes(this);
serializeEntryFunctionBytesCompat(serializer, this);
Comment on lines 248 to +250
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc for serializeForEntryFunction still says it “Uses the optimized serializeAsBytes method”, but the implementation now goes through serializeEntryFunctionBytesCompat() which may fall back to bcsToBytes() + serializeBytes() when a legacy Serializer is provided. Please update the doc comment to reflect the new behavior (prefer serializeAsBytes when available, otherwise fallback for compatibility).

Copilot uses AI. Check for mistakes.
}

/**
Expand Down
Loading
Loading