@aptos-labs/ts-sdk
Version:
Aptos TypeScript SDK
122 lines • 5.21 kB
JavaScript
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0
import { sha3_256 as sha3Hash } from "@noble/hashes/sha3.js";
import { Serializable } from "../../bcs/serializer.js";
import { AccountAddress } from "../../core/index.js";
import { AuthenticationKey } from "../../core/authenticationKey.js";
import { Identifier } from "./identifier.js";
import { ModuleId } from "./moduleId.js";
import { TransactionExecutable } from "./transactionPayload.js";
/** 16-byte decryption nonce for encrypted payloads (aptos-core `DecryptionNonce`). */
export const DECRYPTION_NONCE_LENGTH = 16;
const DECRYPTED_PLAINTEXT_SALT = sha3Hash(new TextEncoder().encode("APTOS::DecryptedPlaintext"));
/**
* Optional claim about the entry function inside an encrypted payload (`claimed_entry_fun` in aptos-core).
* Lets fee payers and multisig co-signers see module and optionally function name without decrypting.
*
* BCS: `module: ModuleId` then `function: Option<Identifier>`. The REST API renames the optional field to `name`.
*/
export class ClaimedEntryFunction extends Serializable {
moduleId;
/** BCS/Rust `function`; JSON API field is `name`. */
functionName;
constructor(moduleId, functionName) {
super();
this.moduleId = moduleId;
this.functionName = functionName;
}
serialize(serializer) {
this.moduleId.serialize(serializer);
serializer.serializeOption(this.functionName);
}
static deserialize(deserializer) {
const moduleId = ModuleId.deserialize(deserializer);
const functionName = deserializer.deserializeOption(Identifier);
return new ClaimedEntryFunction(moduleId, functionName);
}
/**
* @param includeFunctionName - When false, only the module is claimed (`Option::None` for function on wire).
*/
static fromEntryFunction(entry, opts) {
const includeFunctionName = opts?.includeFunctionName !== false;
return new ClaimedEntryFunction(entry.module_name, includeFunctionName ? entry.function_name : undefined);
}
}
/**
* BCS-serializable `DecryptedPlaintext`. Built client-side before encrypting; its BCS hash becomes `payload_hash`.
* Matches Rust: `DecryptedPlaintext { executable, decryption_nonce: [u8; 16] }`.
*/
export class DecryptedPlaintext extends Serializable {
executable;
decryptionNonce;
constructor(executable, decryptionNonce) {
super();
if (decryptionNonce.length !== DECRYPTION_NONCE_LENGTH) {
throw new Error(`decryptionNonce must be ${DECRYPTION_NONCE_LENGTH} bytes`);
}
this.executable = executable;
this.decryptionNonce = decryptionNonce;
}
serialize(serializer) {
this.executable.serialize(serializer);
serializer.serializeFixedBytes(this.decryptionNonce);
}
static deserialize(deserializer) {
const executable = TransactionExecutable.deserialize(deserializer);
const decryptionNonce = deserializer.deserializeFixedBytes(DECRYPTION_NONCE_LENGTH);
return new DecryptedPlaintext(executable, decryptionNonce);
}
/**
* Domain-separated BCS crypto hash (`BCSCryptoHash` in aptos-core):
* SHA3-256( SHA3-256("APTOS::DecryptedPlaintext") || BCS(self) ).
*/
hash() {
const h = sha3Hash.create();
h.update(DECRYPTED_PLAINTEXT_SALT);
h.update(this.bcsToBytes());
return h.digest();
}
}
const PAYLOAD_ASSOCIATED_DATA_V1 = 0;
/**
* AAD for batch-encrypted transaction payloads. BCS matches Rust `PayloadAssociatedData::V1`:
* uleb128 variant | `sender` | `Vec<(AccountAddress, AuthenticationKey)>`.
*/
export class PayloadAssociatedData extends Serializable {
sender;
signerAuthKeys;
constructor(sender, signerAuthKeys) {
super();
this.sender = sender;
this.signerAuthKeys = signerAuthKeys;
if (signerAuthKeys.length === 0) {
throw new Error("PayloadAssociatedData requires at least one signer auth key pair");
}
}
serialize(serializer) {
serializer.serializeU32AsUleb128(PAYLOAD_ASSOCIATED_DATA_V1);
this.sender.serialize(serializer);
serializer.serializeU32AsUleb128(this.signerAuthKeys.length);
for (const { address, authenticationKey } of this.signerAuthKeys) {
address.serialize(serializer);
authenticationKey.serialize(serializer);
}
}
static deserialize(deserializer) {
const variant = deserializer.deserializeUleb128AsU32();
if (variant !== PAYLOAD_ASSOCIATED_DATA_V1) {
throw new Error(`Unknown PayloadAssociatedData variant: ${variant}`);
}
const sender = AccountAddress.deserialize(deserializer);
const len = deserializer.deserializeUleb128AsU32();
const signerAuthKeys = [];
for (let i = 0; i < len; i += 1) {
signerAuthKeys.push({
address: AccountAddress.deserialize(deserializer),
authenticationKey: AuthenticationKey.deserialize(deserializer),
});
}
return new PayloadAssociatedData(sender, signerAuthKeys);
}
}
//# sourceMappingURL=encryptedPayload.js.map