Skip to content

Commit

Permalink
feat: add alchemy transport update for the mav2 account client
Browse files Browse the repository at this point in the history
  • Loading branch information
Blu-J committed Jan 13, 2025
1 parent 18a9228 commit c198db3
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 15 deletions.
5 changes: 5 additions & 0 deletions aa-sdk/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export type Deferrable<T> = {
[K in keyof T]: PromiseOrValue<T[K]>;
};

/**
* Used to ensure type doesn't extend another, for use in & chaining of properties
*/
export type NotType<A, B> = A extends B ? never : unknown;

/**
* Await all of the properties of a Deferrable object
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
} from "@account-kit/infra";
import { Alchemy, Network } from "alchemy-sdk";
import { avalanche, type Chain } from "viem/chains";
import { createLightAccountAlchemyClient } from "./alchemyClient.js";
import { createLightAccountClient } from "./client.js";

describe("Light Account Client Tests", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createSmartAccountClient,
type NotType,
type SmartAccountClient,
type SmartAccountClientActions,
type SmartAccountClientConfig,
Expand Down Expand Up @@ -55,7 +56,8 @@ export function createLightAccountClient<
TSigner extends SmartAccountSigner = SmartAccountSigner,
TTransport extends Transport = Transport
>(
args: CreateLightAccountClientParams<TTransport, TChain, TSigner>
args: CreateLightAccountClientParams<TTransport, TChain, TSigner> &
NotType<TTransport, AlchemyTransport>
): Promise<
SmartAccountClient<
CustomTransport,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
} from "@account-kit/infra";
import { Alchemy, Network } from "alchemy-sdk";
import { avalanche, type Chain } from "viem/chains";
import { createMultiOwnerLightAccountAlchemyClient } from "./multiOwnerAlchemyClient.js";
import { createMultiOwnerLightAccountClient } from "./multiOwnerLightAccount.js";

describe("MultiOwnerLightAccount Client Tests", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createSmartAccountClient,
type NotType,
type SmartAccountClient,
type SmartAccountClientActions,
type SmartAccountClientConfig,
Expand Down Expand Up @@ -66,10 +67,12 @@ export async function createMultiOwnerLightAccountClient<
>;

export function createMultiOwnerLightAccountClient<
TTransport extends Transport = Transport,
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateMultiOwnerLightAccountClientParams<Transport, TChain, TSigner>
args: CreateMultiOwnerLightAccountClientParams<TTransport, TChain, TSigner> &
NotType<TTransport, AlchemyTransport>
): Promise<
SmartAccountClient<
CustomTransport,
Expand Down
62 changes: 62 additions & 0 deletions account-kit/smart-contracts/src/ma-v2/client/client.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
erc7677Middleware,
LocalAccountSigner,
type SmartAccountSigner,
} from "@aa-sdk/core";
import { custom } from "viem";
import { createSMAV2AccountClient } from "@account-kit/smart-contracts/experimental";
import { local070Instance } from "~test/instances.js";
import { accounts } from "~test/constants.js";
import { alchemy } from "@account-kit/infra";

// TODO: Include a snapshot to reset to in afterEach.
describe("MA v2 Tests: Types", async () => {
const instance = local070Instance;

const signer: SmartAccountSigner = new LocalAccountSigner(
accounts.fundedAccountOwner
);

it("alchemy client instantiated can specify policy id but not for others ", async () => {
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: alchemy({ apiKey: "AN_API_KEY" }),
policyId: "test-policy-id",
});
// @ts-expect-error // A custom should not be able to specify an policy id
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: custom(instance.getClient()),
policyId: "test-policy-id",
});
});

it("alchemy client instantiated cannot specify paymaster", async () => {
const { paymasterAndData } = erc7677Middleware();
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: alchemy({ apiKey: "AN_API_KEY" }),
});
// @ts-expect-error Should not be able to pass paymasterAndData
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: alchemy({ apiKey: "AN_API_KEY" }),
paymasterAndData,
});
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: custom(instance.getClient()),
});
createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: custom(instance.getClient()),
paymasterAndData,
});
});
});
44 changes: 43 additions & 1 deletion account-kit/smart-contracts/src/ma-v2/client/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as AAInfraModule from "@account-kit/infra";
import * as AACoreModule from "@aa-sdk/core";
import {
erc7677Middleware,
LocalAccountSigner,
Expand Down Expand Up @@ -32,10 +34,12 @@ import { local070Instance } from "~test/instances.js";
import { setBalance } from "viem/actions";
import { accounts } from "~test/constants.js";
import { paymaster070 } from "~test/paymaster/paymaster070.js";
import { alchemy, arbitrumSepolia } from "@account-kit/infra";

// TODO: Include a snapshot to reset to in afterEach.
describe("MA v2 Tests", async () => {
const instance = local070Instance;

let client: ReturnType<typeof instance.getClient> &
ReturnType<typeof publicActions>;

Expand Down Expand Up @@ -214,7 +218,7 @@ describe("MA v2 Tests", async () => {
},
contents: "Hello, Bob!",
},
};
} as const;

const hashedMessageTypedData = hashTypedData(typedData);
let signature = await provider.signTypedData({ typedData });
Expand Down Expand Up @@ -860,4 +864,42 @@ describe("MA v2 Tests", async () => {
transport: custom(instance.getClient()),
...(usePaymaster ? erc7677Middleware() : {}),
});

it("alchemy client calls the createAlchmeySmartAccountClient", async () => {
const alchemyClientSpy = vi
.spyOn(AAInfraModule, "createAlchemySmartAccountClient")
.mockImplementation(() => "fakedAlchemy" as any);
const notAlcmeyClientSpy = vi
.spyOn(AACoreModule, "createSmartAccountClient")
.mockImplementation(() => "faked" as any);
expect(
await createSMAV2AccountClient({
chain: arbitrumSepolia,
signer,
transport: alchemy({ jwt: "AN_API_KEY" }),
accountAddress: "0x86f3B0211764971Ad0Fc8C8898d31f5d792faD84",
})
).toMatch("fakedAlchemy");

expect(alchemyClientSpy).toHaveBeenCalled();
expect(notAlcmeyClientSpy).not.toHaveBeenCalled();
});
it("custom client calls the createAlchmeySmartAccountClient", async () => {
const alchemyClientSpy = vi
.spyOn(AAInfraModule, "createAlchemySmartAccountClient")
.mockImplementation(() => "fakedAlchemy" as any);
const notAlcmeyClientSpy = vi
.spyOn(AACoreModule, "createSmartAccountClient")
.mockImplementation(() => "faked" as any);
expect(
await createSMAV2AccountClient({
chain: instance.chain,
signer,
transport: custom(instance.getClient()),
})
).toMatch("faked");

expect(alchemyClientSpy).not.toHaveBeenCalled();
expect(notAlcmeyClientSpy).toHaveBeenCalled();
});
});
60 changes: 52 additions & 8 deletions account-kit/smart-contracts/src/ma-v2/client/client.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {
createSmartAccountClient,
type SmartAccountClient,
type SmartAccountSigner,
type SmartAccountClientConfig,
type NotType,
createSmartAccountClient,
} from "@aa-sdk/core";
import { type Chain, type Transport } from "viem";

Expand All @@ -11,10 +12,19 @@ import {
type CreateSMAV2AccountParams,
type MAV2Account,
} from "../account/semiModularAccountV2.js";

import {
createAlchemySmartAccountClient,
isAlchemyTransport,
type AlchemySmartAccountClient,
type AlchemySmartAccountClientConfig,
type AlchemyTransport,
} from "@account-kit/infra";
import type { LightAccount } from "../../light-account/accounts/account.js";
export type SMAV2AccountClient<
TSigner extends SmartAccountSigner = SmartAccountSigner
> = SmartAccountClient<Transport, Chain, MAV2Account<TSigner>>;
TSigner extends SmartAccountSigner = SmartAccountSigner,
TChain extends Chain = Chain,
TTransport extends Transport | AlchemyTransport = Transport
> = SmartAccountClient<TTransport, TChain, MAV2Account<TSigner>>;

export type CreateSMAV2AccountClientParams<
TTransport extends Transport = Transport,
Expand All @@ -25,13 +35,34 @@ export type CreateSMAV2AccountClientParams<
SmartAccountClientConfig<TTransport, TChain>,
"transport" | "account" | "chain"
>;
export type CreateSMAV2AlchemyAccountClientParams<
TTransport extends Transport = Transport,
TChain extends Chain = Chain,
TSigner extends SmartAccountSigner = SmartAccountSigner
> = Omit<
CreateSMAV2AccountClientParams<TTransport, TChain, TSigner>,
"transport"
> &
Omit<
AlchemySmartAccountClientConfig<TChain, LightAccount<TSigner>>,
"account"
> & { paymasterAndData?: never };

export function createSMAV2AccountClient<
TChain extends Chain = Chain,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateSMAV2AccountClientParams<Transport, TChain, TSigner>
): Promise<SMAV2AccountClient<TSigner>>;
args: CreateSMAV2AlchemyAccountClientParams<AlchemyTransport, TChain, TSigner>
): Promise<SMAV2AccountClient<TSigner, TChain, AlchemyTransport>>;

export function createSMAV2AccountClient<
TTransport extends Transport = Transport,
TChain extends Chain = Chain,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateSMAV2AccountClientParams<TTransport, TChain, TSigner> &
NotType<TTransport, AlchemyTransport>
): Promise<SMAV2AccountClient<TSigner, TChain>>;

/**
* Creates a SMAv2 account client using the provided configuration parameters.
Expand Down Expand Up @@ -64,8 +95,21 @@ export function createSMAV2AccountClient<
*/
export async function createSMAV2AccountClient(
config: CreateSMAV2AccountClientParams
): Promise<SmartAccountClient> {
const smaV2Account = await createSMAV2Account(config);
): Promise<SmartAccountClient | AlchemySmartAccountClient> {
const { transport, chain } = config;
const smaV2Account = await createSMAV2Account({
...config,
transport,
chain,
});
if (isAlchemyTransport(transport, chain)) {
return createAlchemySmartAccountClient({
...config,
transport,
chain,
account: smaV2Account,
});
}

return createSmartAccountClient({
...config,
Expand Down
13 changes: 11 additions & 2 deletions account-kit/smart-contracts/src/msca/client/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
createSmartAccountClient,
smartAccountClientActions,
type NotType,
type SmartAccountClient,
type SmartAccountClientRpcSchema,
type SmartAccountSigner,
Expand Down Expand Up @@ -104,10 +105,16 @@ export function createMultiOwnerModularAccountClient<
>;

export function createMultiOwnerModularAccountClient<
TTransport extends Transport = Transport,
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateMultiOwnerModularAccountClientParams<Transport, TChain, TSigner>
args: CreateMultiOwnerModularAccountClientParams<
TTransport,
TChain,
TSigner
> &
NotType<TTransport, AlchemyTransport>
): Promise<
SmartAccountClient<
CustomTransport,
Expand Down Expand Up @@ -207,10 +214,12 @@ export function createMultisigModularAccountClient<
>;

export function createMultisigModularAccountClient<
TTransport extends Transport = Transport,
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateMultisigModularAccountClientParams<Transport, TChain, TSigner>
args: CreateMultisigModularAccountClientParams<TTransport, TChain, TSigner> &
NotType<TTransport, AlchemyTransport>
): Promise<
SmartAccountClient<
CustomTransport,
Expand Down

0 comments on commit c198db3

Please sign in to comment.