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

feat(aa-sdk): sdk light client can call the alchemy client #1236

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ import {
erc7677Middleware,
LocalAccountSigner,
type BatchUserOperationCallData,
type SmartAccountClient,
type SmartAccountSigner,
type UserOperationCallData,
type UserOperationOverrides,
type UserOperationStruct,
} from "@aa-sdk/core";
import { custom, parseEther, type Address, publicActions } from "viem";
import {
custom,
parseEther,
type Address,
publicActions,
type Chain,
type Client,
type CustomTransport,
} from "viem";
import { setBalance } from "viem/actions";
import { resetBalance } from "~test/accounts.js";
import { accounts } from "~test/constants.js";
Expand All @@ -21,6 +30,15 @@ import { getMSCAUpgradeToData } from "../../msca/utils.js";
import type { LightAccountVersion } from "../types.js";
import { AccountVersionRegistry } from "../utils.js";
import { createLightAccountClient } from "./client.js";
import {
alchemy,
polygonMumbai,
alchemyEnhancedApiActions,
type AlchemyTransport,
type AlchemySmartAccountClient,
type AlchemyEnhancedApis,
} from "@account-kit/infra";
import { Alchemy, Network } from "alchemy-sdk";

const versions = Object.keys(
AccountVersionRegistry.LightAccount
Expand Down Expand Up @@ -387,4 +405,76 @@ describe("Light Account Tests", () => {
chain: instance.chain,
...(usePaymaster ? erc7677Middleware() : {}),
});

const givenAlchemyConnectedProvider = async ({
signer,
chain,
}: {
signer: SmartAccountSigner;
chain: Chain;
}) =>
createLightAccountClient({
transport: alchemy({
jwt: "test",
}),
chain,
signer,
accountAddress: "0x86f3B0211764971Ad0Fc8C8898d31f5d792faD84",
});
it("Should have some alchemy specific types", async () => {
const alchemy = new Alchemy({
network: Network.MATIC_MUMBAI,
apiKey: "test",
});
const chain = polygonMumbai;

const provider = (
await givenAlchemyConnectedProvider({ signer, chain })
).extend(alchemyEnhancedApiActions(alchemy));

assertType<Client<AlchemyTransport>>(provider);
assertType<AlchemySmartAccountClient>(provider);
assertType<SmartAccountClient>(provider);
assertType<AlchemyEnhancedApis>(provider);
assertType<AlchemyEnhancedApis>(
// @ts-expect-error
await givenAlchemyConnectedProvider({ signer, chain })
);
// @ts-expect-error
assertType<Client<CustomTransport>>(provider);
});
it("Should have some non-alchemy specific types", async () => {
const chain = polygonMumbai;

const signer: SmartAccountSigner = new LocalAccountSigner(
accounts.fundedAccountOwner
);
const provider = await givenConnectedProvider({
signer,
version: "v1.0.1",
});

assertType<SmartAccountClient>(provider);
assertType<Client<CustomTransport>>(provider);
assertType<AlchemyEnhancedApis>(
// @ts-expect-error
await givenAlchemyConnectedProvider({ signer, chain })
);
// @ts-expect-error
assertType<Client<AlchemyTransport>>(provider);
// @ts-expect-error
assertType<AlchemySmartAccountClient>(provider);
// @ts-expect-error
assertType<AlchemyEnhancedApis>(provider);

expect(() => {
const alchemy = new Alchemy({
network: Network.MATIC_MUMBAI,
apiKey: "test",
});

// @ts-expect-error
provider.extend(alchemyEnhancedApiActions(alchemy));
}).not.toBeFalsy();
});
});
48 changes: 43 additions & 5 deletions account-kit/smart-contracts/src/light-account/clients/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ import {
lightAccountClientActions,
type LightAccountClientActions,
} from "../decorators/lightAccount.js";
import {
type AlchemySmartAccountClient,
type AlchemyTransport,
} from "@account-kit/infra";
import {
createLightAccountAlchemyClient,
type AlchemyLightAccountClientConfig,
} from "./alchemyClient.js";

export type CreateLightAccountClientParams<
TTransport extends Transport = Transport,
TTransport extends Transport | AlchemyTransport = Transport,
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner
> = {
Expand All @@ -31,14 +39,28 @@ export type CreateLightAccountClientParams<
>;

export function createLightAccountClient<
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner
>(
args: CreateLightAccountClientParams<Transport, TChain, TSigner>
params: AlchemyLightAccountClientConfig<TSigner> & {
transport: AlchemyTransport;
}
): Promise<
AlchemySmartAccountClient<
Chain | undefined,
LightAccount<TSigner>,
LightAccountClientActions<TSigner>
>
>;
export function createLightAccountClient<
TChain extends Chain | undefined = Chain | undefined,
TSigner extends SmartAccountSigner = SmartAccountSigner,
TTransport extends Transport = Transport
>(
args: CreateLightAccountClientParams<TTransport, TChain, TSigner>
): Promise<
SmartAccountClient<
CustomTransport,
Chain,
TChain,
LightAccount<TSigner>,
SmartAccountClientActions<Chain, SmartContractAccount> &
LightAccountClientActions<TSigner, LightAccount<TSigner>>
Expand All @@ -48,6 +70,8 @@ export function createLightAccountClient<
/**
* Creates a light account client using the provided parameters, including account information, transport mechanism, blockchain chain, and additional client configurations. This function first creates a light account and then uses it to create a smart account client, extending it with light account client actions.
*
* Also, we modified the return type to be the light account alchemy client if the transport is alchemy.
*
* @example
* ```ts
* import { createLightAccountClient } from "@account-kit/smart-contracts";
Expand All @@ -67,9 +91,16 @@ export function createLightAccountClient<
*/
export async function createLightAccountClient(
params: CreateLightAccountClientParams
): Promise<SmartAccountClient> {
): Promise<SmartAccountClient | AlchemySmartAccountClient> {
const { transport, chain } = params;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I originally called something like this
But the code in

Suggested change
if (isAlchemyTransport(transport)) {
return await createLightAccountAlchemyClient({
...params,
transport,
});
}

Since the code is the same?
Here is the snapshot of current alchemy client, I don't see a difference
image

Copy link
Collaborator

Choose a reason for hiding this comment

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

oh the difference is that this by default calls createSmartAccountClient and the alchemy calls createAlchemySmartAccountClient they take slightly different config params (createSCAClient takes in a paymasterMiddleware and createAlchemySCAClient takes in a gasManagerConfig or I think just a policyId)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Okay, I'll go down the side of testing the params to check the transport as alchemyTransport

if (isAlchemyTransport(transport, chain)) {
return await createLightAccountAlchemyClient({
...params,
transport,
});
}

const lightAccount = await createLightAccount({
...params,
transport,
Expand All @@ -83,3 +114,10 @@ export async function createLightAccountClient(
account: lightAccount,
}).extend(lightAccountClientActions);
}

function isAlchemyTransport(
transport: Transport,
chain: Chain
): transport is AlchemyTransport {
return transport({ chain }).config.type === "alchemy";
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading