Skip to content
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
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 @@ -63,6 +64,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
14 changes: 14 additions & 0 deletions packages/sdk/src/paymaster/handlers/general.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Address } from "viem";
import { getGeneralPaymasterInput } from "viem/zksync";

import type { CustomPaymasterHandler, CustomPaymasterHandlerResponse, CustomPaymasterParameters } from "../index.js";

export function createGeneralPaymaster(paymaster: Address): CustomPaymasterHandler {
/* eslint-disable @typescript-eslint/no-unused-vars */
return async (_: CustomPaymasterParameters): CustomPaymasterHandlerResponse => {
return {
paymaster,
paymasterInput: getGeneralPaymasterInput({ innerInput: "0x" }),
};
};
}
2 changes: 2 additions & 0 deletions packages/sdk/src/paymaster/handlers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./general.js";
export * from "./zyfi.js";
Loading