Skip to content
Closed
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: 6 additions & 3 deletions packages/sdk/src/client-auth-server/Signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createZksyncSessionClient, type ZksyncSsoSessionClient } from "../clien
import type { Communicator } from "../communicator/index.js";
import { type CustomPaymasterHandler, getTransactionWithPaymasterData } from "../paymaster/index.js";
import type { SessionStateEvent } from "../utils/session.js";
import { StorageItem } from "../utils/storage.js";
import { StorageItem, type StorageLike } from "../utils/storage.js";
import type { AppMetadata, RequestArguments } from "./interface.js";
import type { AuthServerRpcSchema, ExtractParams, ExtractReturnType, Method, RPCRequestMessage, RPCResponseMessage, RpcSchema } from "./rpc.js";
import type { SessionPreferences } from "./session/index.js";
Expand Down Expand Up @@ -44,6 +44,7 @@ type SignerConstructorParams = {
paymasterHandler?: CustomPaymasterHandler;
onSessionStateChange?: (event: { address: Address; chainId: number; state: SessionStateEvent }) => void;
skipPreTransactionStateValidation?: boolean; // Useful if you want to send session transactions really fast
storage?: StorageLike;
};

type ChainsInfo = ExtractReturnType<"eth_requestAccounts", AuthServerRpcSchema>["chainsInfo"];
Expand All @@ -60,10 +61,10 @@ export class Signer implements SignerInterface {
private readonly skipPreTransactionStateValidation?: boolean;

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

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

this.getMetadata = metadata;
Expand All @@ -76,6 +77,7 @@ export class Signer implements SignerInterface {
this.onSessionStateChange = onSessionStateChange;
this.skipPreTransactionStateValidation = skipPreTransactionStateValidation;

this._chainsInfo = new StorageItem<ChainsInfo>(StorageItem.scopedStorageKey("chainsInfo"), [], { storage });
this._account = new StorageItem<Account | null>(StorageItem.scopedStorageKey("account"), null, {
onChange: (newValue) => {
if (newValue) {
Expand All @@ -86,6 +88,7 @@ export class Signer implements SignerInterface {
this.updateListener.onAccountsUpdate([]);
}
},
storage,
});
try {
if (this.account) this.createWalletClient();
Expand Down
9 changes: 7 additions & 2 deletions packages/sdk/src/client-auth-server/WalletProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { EventEmitter } from "eventemitter3";
import type { Address, Chain, Transport } from "viem";
import { toHex } from "viem";

import type { Communicator } from "../communicator/index.js";
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 { SessionStateEvent } from "../utils/session.js";
import type { StorageLike } from "../utils/storage.js";
import type {
AppMetadata,
ProviderInterface,
Expand All @@ -27,15 +29,17 @@ export type WalletProviderConstructorOptions = {
paymasterHandler?: CustomPaymasterHandler;
onSessionStateChange?: (state: { address: Address; chainId: number; state: SessionStateEvent }) => void;
skipPreTransactionStateValidation?: boolean; // Useful if you want to send session transactions really fast
customCommunicator?: Communicator;
storage?: StorageLike;
};

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

constructor({ metadata, chains, transports, session, authServerUrl, paymasterHandler, onSessionStateChange, skipPreTransactionStateValidation }: WalletProviderConstructorOptions) {
constructor({ metadata, chains, transports, session, authServerUrl, paymasterHandler, onSessionStateChange, skipPreTransactionStateValidation, customCommunicator, storage }: WalletProviderConstructorOptions) {
super();
const communicator = new PopupCommunicator(authServerUrl || DEFAULT_AUTH_SERVER_URL);
const communicator = customCommunicator ?? new PopupCommunicator(authServerUrl || DEFAULT_AUTH_SERVER_URL);
this.signer = new Signer({
metadata: () => ({
name: metadata?.name || getWebsiteName() || "Unknown DApp",
Expand All @@ -50,6 +54,7 @@ export class WalletProvider extends EventEmitter implements ProviderInterface {
paymasterHandler,
onSessionStateChange,
skipPreTransactionStateValidation,
storage,
});
}

Expand Down
29 changes: 24 additions & 5 deletions packages/sdk/src/communicator/PopupCommunicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,29 @@ import type { Communicator, Message } from "./index.js";
export interface PopupConfigMessage extends Message {
event: "PopupLoaded" | "PopupUnload";
}
type PositionCalculator = (width: number, height: number) => { left: number; top: number };

export class PopupCommunicator implements Communicator {
private readonly url: URL;
private popup: Window | null = null;
private listeners = new Map<(_: MessageEvent) => void, { reject: (_: Error) => void }>();

constructor(url: string) {
private readonly width: number;
private readonly height: number;
private readonly calculatePosition?: PositionCalculator;

constructor(
url: string,
options?: {
width?: number;
height?: number;
calculatePosition?: PositionCalculator;
},
) {
this.url = new URL(url);
this.width = options?.width ?? 420;
this.height = options?.height ?? 600;
this.calculatePosition = options?.calculatePosition;
}

postMessage = async (message: Message) => {
Expand Down Expand Up @@ -64,14 +79,18 @@ export class PopupCommunicator implements Communicator {
};

openPopup = () => {
const width = 420;
const height = 600;
const width = this.width;
const height = this.height;

const url = new URL(this.url.toString());
url.searchParams.set("origin", window.location.origin);

const left = (window.innerWidth - width) / 2 + window.screenX;
const top = (window.innerHeight - height) / 2 + window.screenY;
const { left, top } = this.calculatePosition
? this.calculatePosition(width, height)
: {
left: (window.innerWidth - width) / 2 + window.screenX,
top: (window.innerHeight - height) / 2 + window.screenY,
};

const popup = window.open(
url,
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 @@ -17,6 +17,7 @@ import {
} from "viem";

import type { ZksyncSsoSessionClient } from "../client/index.js";
import type { Communicator } from "../communicator/interface.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";
Expand All @@ -27,6 +28,7 @@ export type ZksyncSsoConnectorOptions = {
session?: SessionPreferences | (() => SessionPreferences | Promise<SessionPreferences>);
authServerUrl?: string;
paymasterHandler?: CustomPaymasterHandler;
communicator?: Communicator;
};

export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
Expand Down Expand Up @@ -144,6 +146,7 @@ export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
transports: config.transports,
chains: config.chains,
paymasterHandler: parameters.paymasterHandler,
customCommunicator: parameters.communicator,
});
}
return walletProvider;
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/src/utils/storage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface StorageLike {
export interface StorageLike {
getItem(key: string): string | null;
setItem(key: string, value: string): void;
removeItem(key: string): void;
Expand Down
Loading