Skip to content

Commit

Permalink
Merge branch 'main' into multi-domain-passkey
Browse files Browse the repository at this point in the history
  • Loading branch information
cpb8010 authored Feb 7, 2025
2 parents e145cf9 + e71f93e commit 1bbdb8e
Show file tree
Hide file tree
Showing 15 changed files with 331 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
- name: Deploy Demo-App contracts
run: pnpm nx deploy-contracts demo-app

- name: Run tests
- name: Run tests
run: pnpm test
working-directory: packages/sdk

Expand Down
9 changes: 9 additions & 0 deletions cspell-config/cspell-misc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ testid
vueuse
dockerized
ethereum
foundryup

// examples/bank-demo
ctap
Expand All @@ -28,3 +29,11 @@ usdc
Fren
fren
nfts

// examples/demo-app
zkout
cancun
EVMLA

// paymasters
zyfi
5 changes: 5 additions & 0 deletions packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
"import": "./dist/_esm/abi/index.js",
"require": "./dist/_cjs/abi/index.js"
},
"./paymaster": {
"types": "./dist/_types/paymaster/index.d.ts",
"import": "./dist/_esm/paymaster/index.js",
"require": "./dist/_cjs/paymaster/index.js"
},
"./package.json": "./package.json"
},
"typesVersions": {
Expand Down
25 changes: 24 additions & 1 deletion packages/sdk/src/client-auth-server/Signer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { type Address, type Chain, createWalletClient, custom, type Hash, http, type RpcSchema as RpcSchemaGeneric, type SendTransactionParameters, type Transport, type WalletClient } from "viem";
import type { TransactionRequestEIP712 } from "viem/chains";

import { createZksyncSessionClient, type ZksyncSsoSessionClient } from "../client/index.js";
import type { Communicator } from "../communicator/index.js";
import { type CustomPaymasterHandler, getTransactionWithPaymasterData } from "../paymaster/index.js";
import { StorageItem } from "../utils/storage.js";
import type { AppMetadata, RequestArguments } from "./interface.js";
import type { AuthServerRpcSchema, ExtractParams, ExtractReturnType, Method, RPCRequestMessage, RPCResponseMessage, RpcSchema } from "./rpc.js";
Expand Down Expand Up @@ -38,6 +40,7 @@ type SignerConstructorParams = {
chains: readonly Chain[];
transports?: Record<number, Transport>;
session?: () => SessionPreferences | Promise<SessionPreferences>;
paymasterHandler?: CustomPaymasterHandler;
};

type ChainsInfo = ExtractReturnType<"eth_requestAccounts", AuthServerRpcSchema>["chainsInfo"];
Expand All @@ -49,12 +52,13 @@ export class Signer implements SignerInterface {
private readonly chains: readonly Chain[];
private readonly transports: Record<number, Transport> = {};
private readonly sessionParameters?: () => (SessionPreferences | Promise<SessionPreferences>);
private readonly paymasterHandler?: CustomPaymasterHandler;

private _account: StorageItem<Account | null>;
private _chainsInfo = new StorageItem<ChainsInfo>(StorageItem.scopedStorageKey("chainsInfo"), []);
private client: { instance: ZksyncSsoSessionClient; type: "session" } | { instance: WalletClient; type: "auth-server" } | undefined;

constructor({ metadata, communicator, updateListener, session, chains, transports }: SignerConstructorParams) {
constructor({ metadata, communicator, updateListener, session, chains, transports, paymasterHandler }: SignerConstructorParams) {
if (!chains.length) throw new Error("At least one chain must be included in the config");

this.getMetadata = metadata;
Expand All @@ -63,6 +67,7 @@ export class Signer implements SignerInterface {
this.sessionParameters = session;
this.chains = chains;
this.transports = transports || {};
this.paymasterHandler = paymasterHandler;

this._account = new StorageItem<Account | null>(StorageItem.scopedStorageKey("account"), null, {
onChange: (newValue) => {
Expand Down Expand Up @@ -136,6 +141,7 @@ export class Signer implements SignerInterface {
contracts: chainInfo.contracts,
chain,
transport: this.transports[chain.id] || http(),
paymasterHandler: this.paymasterHandler,
}),
};
} else {
Expand Down Expand Up @@ -266,6 +272,23 @@ export class Signer implements SignerInterface {
// Open popup immediately to make sure popup won't be blocked by Safari
await this.communicator.ready();

if (request.method === "eth_sendTransaction") {
const params = request.params![0] as TransactionRequestEIP712;
if (params) {
/* eslint-disable @typescript-eslint/no-unused-vars */
const { chainId: _, ...transaction } = await getTransactionWithPaymasterData(
this.chain.id,
params.from,
params,
this.paymasterHandler,
);
request = {
method: request.method,
params: [transaction] as ExtractParams<TMethod, TSchema>,
};
}
}

const message = this.createRequestMessage<TMethod, TSchema>({
action: request,
chainId: this.chain.id,
Expand Down
5 changes: 4 additions & 1 deletion packages/sdk/src/client-auth-server/WalletProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { toHex } from "viem";

import { PopupCommunicator } from "../communicator/PopupCommunicator.js";
import { serializeError, standardErrors } from "../errors/index.js";
import type { CustomPaymasterHandler } from "../paymaster/index.js";
import { getFavicon, getWebsiteName } from "../utils/helpers.js";
import type {
AppMetadata,
Expand All @@ -22,13 +23,14 @@ export type WalletProviderConstructorOptions = {
transports?: Record<number, Transport>;
session?: SessionPreferences | (() => SessionPreferences | Promise<SessionPreferences>);
authServerUrl?: string;
paymasterHandler?: CustomPaymasterHandler;
};

export class WalletProvider extends EventEmitter implements ProviderInterface {
readonly isZksyncSso = true;
private signer: Signer;

constructor({ metadata, chains, transports, session, authServerUrl }: WalletProviderConstructorOptions) {
constructor({ metadata, chains, transports, session, authServerUrl, paymasterHandler }: WalletProviderConstructorOptions) {
super();
const communicator = new PopupCommunicator(authServerUrl || DEFAULT_AUTH_SERVER_URL);
this.signer = new Signer({
Expand All @@ -41,6 +43,7 @@ export class WalletProvider extends EventEmitter implements ProviderInterface {
chains,
transports,
session: typeof session === "object" ? () => session : session,
paymasterHandler,
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/sdk/src/client/passkey/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type Account, type Address, type Chain, type Client, createClient, getAddress, type Prettify, type PublicActions, publicActions, type PublicRpcSchema, type RpcSchema, type Transport, type WalletActions, walletActions, type WalletClientConfig, type WalletRpcSchema } from "viem";
import { eip712WalletActions } from "viem/zksync";

import type { CustomPaymasterHandler } from "../../paymaster/index.js";
import { passkeyHashSignatureResponseFormat } from "../../utils/passkey.js";
import { toPasskeyAccount } from "./account.js";
import { requestPasskeyAuthentication } from "./actions/passkey.js";
Expand Down Expand Up @@ -66,6 +67,7 @@ type ZksyncSsoPasskeyData = {
userName: string; // Basically unique user id (which is called `userName` in webauthn)
userDisplayName: string; // Also option required for webauthn
contracts: PasskeyRequiredContracts;
paymasterHandler?: CustomPaymasterHandler;
};

export type ClientWithZksyncSsoPasskeyData<
Expand Down
31 changes: 26 additions & 5 deletions packages/sdk/src/client/passkey/decorators/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { type Account, bytesToHex, type Chain, formatTransaction, type Transport, type WalletActions } from "viem";
import { type Account, bytesToHex, type Chain, type ExactPartial, formatTransaction, type RpcTransaction, type Transport, type WalletActions } from "viem";
import { deployContract, getAddresses, getChainId, sendRawTransaction, signMessage, signTypedData, writeContract } from "viem/actions";
import { signTransaction, type ZksyncEip712Meta } from "viem/zksync";
import { signTransaction, type TransactionRequestEIP712, type ZksyncEip712Meta } from "viem/zksync";

import { getTransactionWithPaymasterData } from "../../../paymaster/index.js";
import { sendEip712Transaction } from "../../session/actions/sendEip712Transaction.js";
import type { ClientWithZksyncSsoPasskeyData } from "../client.js";

Expand Down Expand Up @@ -33,19 +34,39 @@ export function zksyncSsoPasskeyWalletActions<
delete unformattedTx.eip712Meta;
}

/* eslint-disable @typescript-eslint/no-unused-vars */
const { chainId: _, ...unformattedTxWithPaymaster } = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
unformattedTx,
client.paymasterHandler,
);

const formatters = client.chain?.formatters;
const format = formatters?.transaction?.format || formatTransaction;

const tx = {
...format(unformattedTx),
...format(unformattedTxWithPaymaster as ExactPartial<RpcTransaction>),
type: "eip712",
};

return await sendEip712Transaction(client, tx);
},
signMessage: (args) => signMessage(client, args),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
signTransaction: (args) => signTransaction(client, args as any),

signTransaction: async (args) => {
/* eslint-disable @typescript-eslint/no-unused-vars */
const { chainId: _, ...unformattedTxWithPaymaster } = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
args as TransactionRequestEIP712,
client.paymasterHandler,
);
return signTransaction(client, {
...args,
unformattedTxWithPaymaster,
} as any);
},
signTypedData: (args) => signTypedData(client, args),
writeContract: (args) => writeContract(client, args),
};
Expand Down
22 changes: 20 additions & 2 deletions packages/sdk/src/client/session/actions/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { waitForTransactionReceipt } from "viem/actions";
import { getGeneralPaymasterInput, sendTransaction } from "viem/zksync";

import { SessionKeyModuleAbi } from "../../../abi/SessionKeyModule.js";
import { type CustomPaymasterHandler, getTransactionWithPaymasterData } from "../../../paymaster/index.js";
import { noThrow } from "../../../utils/helpers.js";
import type { SessionConfig } from "../../../utils/session.js";

Expand All @@ -16,6 +17,7 @@ export type CreateSessionArgs = {
paymasterInput?: Hex;
};
onTransactionSent?: (hash: Hash) => void;
paymasterHandler?: CustomPaymasterHandler;
};
export type CreateSessionReturnType = {
transactionReceipt: TransactionReceipt;
Expand All @@ -41,7 +43,14 @@ export const createSession = async <
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;

const transactionHash = await sendTransaction(client, sendTransactionArgs);
const transactionWithPaymasterData: any = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
sendTransactionArgs,
args.paymasterHandler,
);

const transactionHash = await sendTransaction(client, transactionWithPaymasterData);
if (args.onTransactionSent) {
noThrow(() => args.onTransactionSent?.(transactionHash));
}
Expand All @@ -64,6 +73,7 @@ export type RevokeSessionArgs = {
paymasterInput?: Hex;
};
onTransactionSent?: (hash: Hash) => void;
paymasterHandler?: CustomPaymasterHandler;
};
export type RevokeSessionReturnType = {
transactionReceipt: TransactionReceipt;
Expand All @@ -89,7 +99,15 @@ export const revokeSession = async <
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;

const transactionHash = await sendTransaction(client, sendTransactionArgs);
const transactionWithPaymasterData: any = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
sendTransactionArgs,
args.paymasterHandler,
);

const transactionHash = await sendTransaction(client, transactionWithPaymasterData);

if (args.onTransactionSent) {
noThrow(() => args.onTransactionSent?.(transactionHash));
}
Expand Down
4 changes: 4 additions & 0 deletions packages/sdk/src/client/session/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type Account, type Address, type Chain, type Client, createClient, crea
import { privateKeyToAccount } from "viem/accounts";
import { zksyncInMemoryNode } from "viem/chains";

import type { CustomPaymasterHandler } from "../../paymaster/index.js";
import { encodeSessionTx } from "../../utils/encoding.js";
import type { SessionConfig } from "../../utils/session.js";
import { toSessionAccount } from "./account.js";
Expand Down Expand Up @@ -88,6 +89,7 @@ export function createZksyncSessionClient<
sessionKey: parameters.sessionKey,
sessionConfig: parameters.sessionConfig,
contracts: parameters.contracts,
paymasterHandler: parameters.paymasterHandler,
}))
.extend(publicActions)
.extend(publicActionsRewrite)
Expand All @@ -102,6 +104,7 @@ type ZksyncSsoSessionData = {
sessionKey: Hash;
sessionConfig: SessionConfig;
contracts: SessionRequiredContracts;
paymasterHandler?: CustomPaymasterHandler;
};

export type ClientWithZksyncSsoSessionData<
Expand Down Expand Up @@ -139,4 +142,5 @@ export interface ZksyncSsoSessionClientConfig<
contracts: SessionRequiredContracts;
key?: string;
name?: string;
paymasterHandler?: CustomPaymasterHandler;
}
40 changes: 33 additions & 7 deletions packages/sdk/src/client/session/decorators/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { type Account, bytesToHex, type Chain, formatTransaction, type Transport, type WalletActions } from "viem";
import { deployContract, getAddresses, getChainId, sendRawTransaction, signMessage, signTypedData, writeContract } from "viem/actions";
import { signTransaction, type ZksyncEip712Meta } from "viem/zksync";

import {
type Account, bytesToHex,
type Chain, type ExactPartial, formatTransaction, type RpcTransaction,
type Transport, type WalletActions } from "viem";
import {
deployContract, getAddresses, getChainId, sendRawTransaction,
signMessage, signTypedData, writeContract,
} from "viem/actions";
import { signTransaction, type TransactionRequestEIP712, type ZksyncEip712Meta } from "viem/zksync";

import { getTransactionWithPaymasterData } from "../../../paymaster/index.js";
import { sendEip712Transaction } from "../actions/sendEip712Transaction.js";
import type { ClientWithZksyncSsoSessionData } from "../client.js";

Expand Down Expand Up @@ -33,19 +40,38 @@ export function zksyncSsoWalletActions<
delete unformattedTx.eip712Meta;
}

/* eslint-disable @typescript-eslint/no-unused-vars */
const { chainId: _, ...unformattedTxWithPaymaster } = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
unformattedTx,
client.paymasterHandler,
);

const formatters = client.chain?.formatters;
const format = formatters?.transaction?.format || formatTransaction;

const tx = {
...format(unformattedTx),
...format(unformattedTxWithPaymaster as ExactPartial<RpcTransaction>),
type: "eip712",
};

return await sendEip712Transaction(client, tx);
},
signMessage: (args) => signMessage(client, args),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
signTransaction: (args) => signTransaction(client, args as any),

signTransaction: async (args) => {
const { chainId: _, ...unformattedTxWithPaymaster } = await getTransactionWithPaymasterData(
client.chain.id,
client.account.address,
args as TransactionRequestEIP712,
client.paymasterHandler,
);
return signTransaction(client, {
...args,
unformattedTxWithPaymaster,
} as any);
},
signTypedData: (args) => signTypedData(client, args),
writeContract: (args) => writeContract(client, args),
};
Expand Down
3 changes: 3 additions & 0 deletions packages/sdk/src/connector/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ import {
import type { ZksyncSsoSessionClient } from "../client/index.js";
import { EthereumProviderError } from "../errors/errors.js";
import { type AppMetadata, type ProviderInterface, type SessionPreferences, WalletProvider } from "../index.js";
import type { CustomPaymasterHandler } from "../paymaster/index.js";
export { callPolicy } from "../client-auth-server/index.js";

export type ZksyncSsoConnectorOptions = {
metadata?: Partial<AppMetadata>;
session?: SessionPreferences | (() => SessionPreferences | Promise<SessionPreferences>);
authServerUrl?: string;
paymasterHandler?: CustomPaymasterHandler;
};

export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
Expand Down Expand Up @@ -140,6 +142,7 @@ export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
session: parameters.session,
transports: config.transports,
chains: config.chains,
paymasterHandler: parameters.paymasterHandler,
});
}
return walletProvider;
Expand Down
Loading

0 comments on commit 1bbdb8e

Please sign in to comment.