Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: readd changes lost in merge PR #1259

Merged
merged 1 commit into from
Jan 3, 2025
Merged
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
8 changes: 4 additions & 4 deletions aa-sdk/core/src/errors/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ export class InvalidNonceKeyError extends BaseError {
* @param {bigint} nonceKey the invalid nonceKey used
*/
constructor(nonceKey: bigint) {
super(`Nonce key is ${nonceKey} but has to be less than 2**152`);
super(
`Nonce key is ${nonceKey} but has to be less than or equal to 2**152`
);
}
}

Expand All @@ -98,8 +100,6 @@ export class EntityIdOverrideError extends BaseError {
* Initializes a new instance of the error message with a default message indicating that the nonce key is invalid.
*/
constructor() {
super(
`Installing entityId of 0 overrides the owner's entity id in the account`
);
super(`EntityId of 0 is reserved for the owner and cannot be used`);
}
}
48 changes: 48 additions & 0 deletions account-kit/smart-contracts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,51 @@ export {
getMAInitializationData,
getMSCAUpgradeToData,
} from "./msca/utils.js";

// ma v2 exports
export { accountFactoryAbi } from "./ma-v2/abis/accountFactoryAbi.js";
export { modularAccountAbi } from "./ma-v2/abis/modularAccountAbi.js";
export { semiModularAccountBytecodeAbi } from "./ma-v2/abis/semiModularAccountBytecodeAbi.js";
export { semiModularAccountStorageAbi } from "./ma-v2/abis/semiModularAccountStorageAbi.js";

export { nativeSMASigner } from "./ma-v2/account/nativeSMASigner.js";
export type * from "./ma-v2/account/semiModularAccountV2.js";
export { createSMAV2Account } from "./ma-v2/account/semiModularAccountV2.js";

export type {
ModuleEntity,
ValidationConfig,
HookConfig,
ValidationData,
} from "./ma-v2/actions/common/types.js";
export { HookType } from "./ma-v2/actions/common/types.js";
export {
serializeValidationConfig,
serializeHookConfig,
serializeModuleEntity,
} from "./ma-v2/actions/common/utils.js";
export type * from "./ma-v2/actions/install-validation/installValidation.js";
export { installValidationActions } from "./ma-v2/actions/install-validation/installValidation.js";

export type * from "./ma-v2/client/client.js";
export { createSMAV2AccountClient } from "./ma-v2/client/client.js";

export {
getDefaultAllowlistModuleAddress,
getDefaultNativeTokenLimitModuleAddress,
getDefaultPaymasterGuardModuleAddress,
getDefaultSingleSignerValidationModuleAddress,
getDefaultTimeRangeModuleAddress,
getDefaultWebauthnValidationModuleAddress,
} from "./ma-v2/modules/utils.js";
export { allowlistModuleAbi } from "./ma-v2/modules/allowlist-module/abis/allowlistModuleAbi.js";
export { AllowlistModule } from "./ma-v2/modules/allowlist-module/module.js";
export { nativeTokenLimitModuleAbi } from "./ma-v2/modules/native-token-limit-module/abis/nativeTokenLimitModuleAbi.js";
export { NativeTokenLimitModule } from "./ma-v2/modules/native-token-limit-module/module.js";
export { paymasterGuardModuleAbi } from "./ma-v2/modules/paymaster-guard-module/abis/paymasterGuardModuleAbi.js";
export { PaymasterGuardModule } from "./ma-v2/modules/paymaster-guard-module/module.js";
export { singleSignerValidationModuleAbi } from "./ma-v2/modules/single-signer-validation/abis/singleSignerValidationModuleAbi.js";
export { SingleSignerValidationModule } from "./ma-v2/modules/single-signer-validation/module.js";
export { timeRangeModuleAbi } from "./ma-v2/modules/time-range-module/abis/timeRangeModuleAbi.js";
export { TimeRangeModule } from "./ma-v2/modules/time-range-module/module.js";
export { webauthnValidationModuleAbi } from "./ma-v2/modules/webauthn-validation/abis/webauthnValidationAbi.js";
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ import {
type Address,
} from "viem";

import { packUOSignature, pack1271Signature } from "../utils.js";
import {
packUOSignature,
pack1271Signature,
DEFAULT_OWNER_ENTITY_ID,
} from "../utils.js";
/**
* Creates an object with methods for generating a dummy signature, signing user operation hashes, signing messages, and signing typed data.
*
* @example
* ```ts
* import { singleSignerMessageSigner } from "@account-kit/smart-contracts";
* import { nativeSMASigner } from "@account-kit/smart-contracts";

* import { LocalAccountSigner } from "@aa-sdk/core";
*
Expand All @@ -26,20 +30,18 @@ import { packUOSignature, pack1271Signature } from "../utils.js";
*
* const signer = LocalAccountSigner.mnemonicToAccountSigner(MNEMONIC);
*
* const messageSigner = singleSignerMessageSigner(signer, chain);
* const messageSigner = nativeSMASigner(signer, chain, account.address);
* ```
*
* @param {SmartAccountSigner} signer Signer to use for signing operations
* @param {Chain} chain Chain object for the signer
* @param {Address} accountAddress address of the smart account using this signer
* @param {number} entityId the entity id of the signing validation
* @returns {object} an object with methods for signing operations and managing signatures
*/
export const nativeSMASigner = (
signer: SmartAccountSigner,
chain: Chain,
accountAddress: Address,
entityId: number
accountAddress: Address
) => {
return {
getDummySignature: (): Hex => {
Expand Down Expand Up @@ -79,7 +81,7 @@ export const nativeSMASigner = (
},
primaryType: "ReplaySafeHash",
}),
entityId,
entityId: DEFAULT_OWNER_ENTITY_ID,
});
},

Expand Down Expand Up @@ -112,7 +114,7 @@ export const nativeSMASigner = (
},
primaryType: "ReplaySafeHash",
}),
entityId,
entityId: DEFAULT_OWNER_ENTITY_ID,
});
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ export type ValidationDataParams =
entityId: number;
};

export type SMAV2Account<
export type MAV2Account<
TSigner extends SmartAccountSigner = SmartAccountSigner
> = SmartContractAccountWithSigner<"SMAV2Account", TSigner, "0.7.0"> & {
> = SmartContractAccountWithSigner<"MAV2Account", TSigner, "0.7.0"> & {
signerEntity: SignerEntity;
getExecutionData: (selector: Hex) => Promise<ExecutionDataView>;
getValidationData: (
Expand All @@ -81,7 +81,7 @@ export type CreateSMAV2AccountParams<
TTransport extends Transport = Transport,
TSigner extends SmartAccountSigner = SmartAccountSigner
> = Pick<
ToSmartContractAccountParams<"SMAV2Account", TTransport, Chain, "0.7.0">,
ToSmartContractAccountParams<"MAV2Account", TTransport, Chain, "0.7.0">,
"transport" | "chain" | "accountAddress"
> & {
signer: TSigner;
Expand All @@ -98,11 +98,18 @@ export async function createSMAV2Account<
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
config: CreateSMAV2AccountParams<TTransport, TSigner>
): Promise<SMAV2Account<TSigner>>;
): Promise<MAV2Account<TSigner>>;

/**
* Creates an SMAV2 account using defined parameters including chain, signer, salt, factory address, and more.
* Handles account initialization code, nonce generation, transaction encoding, and more to construct a modular account with optional validation hooks.
*
* @param {CreateSMAV2AccountParams} config Configuration parameters for creating an SMAV2 account. Includes chain details, signer, salt, factory address, and more.
* @returns {Promise<MAV2Account>} A promise that resolves to an `MAV2Account` providing methods for nonce retrieval, transaction execution, and more.
*/
export async function createSMAV2Account(
config: CreateSMAV2AccountParams
): Promise<SMAV2Account> {
): Promise<MAV2Account> {
const {
transport,
chain,
Expand All @@ -117,10 +124,12 @@ export async function createSMAV2Account(
isGlobalValidation: true,
entityId: DEFAULT_OWNER_ENTITY_ID,
},
signerEntity: {
isGlobalValidation = true,
entityId = DEFAULT_OWNER_ENTITY_ID,
} = {},
} = config;

const { isGlobalValidation, entityId } = signerEntity;

if (entityId > Number(maxUint32)) {
throw new InvalidEntityIdError(entityId);
}
Expand Down Expand Up @@ -188,18 +197,18 @@ export async function createSMAV2Account(
chain,
entryPoint,
accountAddress: _accountAddress,
source: `SMAV2Account`,
source: `MAV2Account`,
encodeExecute,
encodeBatchExecute,
getAccountInitCode,
...(entityId === DEFAULT_OWNER_ENTITY_ID
? nativeSMASigner(signer, chain, _accountAddress, entityId)
? nativeSMASigner(signer, chain, _accountAddress)
: singleSignerMessageSigner(signer, chain, _accountAddress, entityId)),
});

// TODO: add deferred action flag
const getAccountNonce = async (nonceKey?: bigint): Promise<bigint> => {
if (nonceKey && nonceKey > maxUint152) {
const getAccountNonce = async (nonceKey: bigint = 0n): Promise<bigint> => {
if (nonceKey > maxUint152) {
throw new InvalidNonceKeyError(nonceKey);
}

Expand All @@ -210,7 +219,7 @@ export async function createSMAV2Account(
});

const fullNonceKey: bigint =
(nonceKey ? nonceKey << 40n : 0n) +
(nonceKey << 40n) +
BigInt(entityId << 8) +
(isGlobalValidation ? 1n : 0n);

Expand Down
71 changes: 71 additions & 0 deletions account-kit/smart-contracts/src/ma-v2/actions/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@ import { type Hex, toHex, concatHex } from "viem";
import type { ValidationConfig, HookConfig, ModuleEntity } from "./types";
import { HookType } from "./types.js";

/**
* Serializes a validation configuration into a hexadecimal string representation. This involves converting boolean flags into bitwise representation and combining them with serialized module entity data.
*
* @example
* ```ts
* import { serializeValidationConfig } from "@account-kit/smart-contracts";
* import { Address } from "viem";
*
* const moduleAddress: Address = "0x1234";
* const entityId: number = 1234;
* const isGlobal: boolean = true;
* const isSignatureValidation: boolean = false;
* const isUserOpValidation: boolean = true;
*
* const validationConfigHex = serializeValidationConfig({
* moduleAddress,
* entityId
* isGlobal,
* isSignatureValidation,
* isUserOpValidation
* });
* ```
* @param {ValidationConfig} config The validation configuration object containing details to serialize
* @returns {Hex} A hexadecimal string representing the serialized configuration
*/
export function serializeValidationConfig(config: ValidationConfig): Hex {
const isUserOpValidationBit = config.isUserOpValidation ? 1 : 0;
const isSignatureValidationBit = config.isSignatureValidation ? 2 : 0;
Expand All @@ -14,6 +39,32 @@ export function serializeValidationConfig(config: ValidationConfig): Hex {
]);
}

/**
* Serializes a `HookConfig` object into a `Hex` format by encoding the hook type, presence of post/pre hooks, address, and entity ID.
*
* @example
* ```ts
* import { type HookType, serializeHookConfig } from "@account-kit/smart-contracts";
* import { Address } from "viem";
*
* const moduleAddress: Address = "0x1234";
* const entityId: number = 1234;
* const hookType: HookType = HookType.Validation;
* const hasPostHooks: boolean = false;
* const hasPreHooks: boolean = true;
*
* const hookConfigHex = serializeHookConfig({
* moduleAddress,
* entityId
* hookType,
* hasPostHooks,
* hasPreHooks
* });
* ```
*
* @param {HookConfig} config The hook configuration containing address, entity ID, hook type, and post/pre hook indicators
* @returns {Hex} The serialized hook configuration in hexadecimal format
*/
export function serializeHookConfig(config: HookConfig): Hex {
const hookTypeBit = config.hookType === HookType.VALIDATION ? 1 : 0;
const hasPostHooksBit = config.hasPostHooks ? 2 : 0;
Expand All @@ -27,6 +78,26 @@ export function serializeHookConfig(config: HookConfig): Hex {
]);
}

/**
* Serializes a module entity into a hexadecimal format by concatenating the module address and entity ID.
*
* @example
* ```ts
* import { serializeModuleEntity } from "@account-kit/smart-contracts";
* import { Address } from "viem";
*
* const moduleAddress: Address = "0x1234";
* const entityId: number = 1234;
*
* const moduleEntityHex = serializeModuleEntity({
* moduleAddress,
* entityId
* });
* ```
*
* @param {ModuleEntity} config The module entity configuration containing the module address and entity ID
* @returns {Hex} A hexadecimal string representation of the serialized module entity
*/
export function serializeModuleEntity(config: ModuleEntity): Hex {
return concatHex([config.moduleAddress, toHex(config.entityId, { size: 4 })]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from "../common/utils.js";

import { type SMAV2AccountClient } from "../../client/client.js";
import { type SMAV2Account } from "../../account/semiModularAccountV2.js";
import { type MAV2Account } from "../../account/semiModularAccountV2.js";
import { DEFAULT_OWNER_ENTITY_ID } from "../../utils.js";

export type InstallValidationParams<
Expand All @@ -38,9 +38,9 @@ export type InstallValidationParams<
hookConfig: HookConfig;
initData: Hex;
}[];
account?: SMAV2Account<TSigner> | undefined;
account?: MAV2Account<TSigner> | undefined;
} & UserOperationOverridesParameter<
GetEntryPointFromAccount<SMAV2Account<TSigner>>
GetEntryPointFromAccount<MAV2Account<TSigner>>
>;

export type UninstallValidationParams<
Expand All @@ -50,9 +50,9 @@ export type UninstallValidationParams<
entityId: number;
uninstallData: Hex;
hookUninstallDatas: Hex[];
account?: SMAV2Account<TSigner> | undefined;
account?: MAV2Account<TSigner> | undefined;
} & UserOperationOverridesParameter<
GetEntryPointFromAccount<SMAV2Account<TSigner>>
GetEntryPointFromAccount<MAV2Account<TSigner>>
>;

export type InstallValidationActions<
Expand All @@ -66,6 +66,50 @@ export type InstallValidationActions<
) => Promise<SendUserOperationResult>;
};

/**
* Provides validation installation and uninstallation functionalities for a MA v2 client, ensuring compatibility with `SmartAccountClient`.
*
* @example
* ```ts
* import { createSMAV2AccountClient, installValidationActions, getDefaultSingleSignerValidationModuleAddress, SingleSignerValidationModule } from "@account-kit/smart-contracts";
* import { Address } from "viem";
*
* const client = (await createSMAV2AccountClient({ ... })).extend(installValidationActions);
* const sessionKeyAddress: Address = "0x1234";
* const sessionKeyEntityId: number = 1;
*
* await client.installValidation({
* validationConfig: {
* moduleAddress: getDefaultSingleSignerValidationModuleAddress(
* client.chain
* ),
* entityId: sessionKeyEntityId,
* isGlobal: true,
* isSignatureValidation: false,
* isUserOpValidation: true,
* },
* selectors: [],
* installData: SingleSignerValidationModule.encodeOnInstallData({
* entityId: sessionKeyEntityId,
* signer: sessionKeyAddress,
* }),
* hooks: [],
* });
*
* await client.uninstallValidation({
* moduleAddress: sessionKeyAddress,
* entityId: sessionKeyEntityId,
* uninstallData: SingleSignerValidationModule.encodeOnUninstallData({
* entityId: sessionKeyEntityId,
* }),
* hookUninstallDatas: [],
* });
*
* ```
*
* @param {object} client - The client instance which provides account and sendUserOperation functionality.
* @returns {object} - An object containing two methods, `installValidation` and `uninstallValidation`.
*/
export const installValidationActions: <
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
Expand Down
Loading
Loading