Skip to content

Commit 59a4c0c

Browse files
cpb8010fallecosaviotx
authored
Sophon-main (#167)
* feat(SOP-1365): allowing custom communicator and storage on wallet provider * feat: allow custom popup positioning --------- Co-authored-by: Israel Crisanto <me@israelcrisanto.com> Co-authored-by: Sávio Fialho <savio@txfusion.io>
1 parent c417ca4 commit 59a4c0c

File tree

5 files changed

+41
-11
lines changed

5 files changed

+41
-11
lines changed

packages/sdk/src/client-auth-server/Signer.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createZksyncSessionClient, type ZksyncSsoSessionClient } from "../clien
55
import type { Communicator } from "../communicator/index.js";
66
import { type CustomPaymasterHandler, getTransactionWithPaymasterData } from "../paymaster/index.js";
77
import type { SessionStateEvent } from "../utils/session.js";
8-
import { StorageItem } from "../utils/storage.js";
8+
import { StorageItem, type StorageLike } from "../utils/storage.js";
99
import type { AppMetadata, RequestArguments } from "./interface.js";
1010
import type { AuthServerRpcSchema, ExtractParams, ExtractReturnType, Method, RPCRequestMessage, RPCResponseMessage, RpcSchema } from "./rpc.js";
1111
import type { SessionPreferences } from "./session/index.js";
@@ -44,6 +44,7 @@ type SignerConstructorParams = {
4444
paymasterHandler?: CustomPaymasterHandler;
4545
onSessionStateChange?: (event: { address: Address; chainId: number; state: SessionStateEvent }) => void;
4646
skipPreTransactionStateValidation?: boolean; // Useful if you want to send session transactions really fast
47+
storage?: StorageLike;
4748
};
4849

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

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

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

6970
this.getMetadata = metadata;
@@ -76,6 +77,7 @@ export class Signer implements SignerInterface {
7677
this.onSessionStateChange = onSessionStateChange;
7778
this.skipPreTransactionStateValidation = skipPreTransactionStateValidation;
7879

80+
this._chainsInfo = new StorageItem<ChainsInfo>(StorageItem.scopedStorageKey("chainsInfo"), [], { storage });
7981
this._account = new StorageItem<Account | null>(StorageItem.scopedStorageKey("account"), null, {
8082
onChange: (newValue) => {
8183
if (newValue) {
@@ -86,6 +88,7 @@ export class Signer implements SignerInterface {
8688
this.updateListener.onAccountsUpdate([]);
8789
}
8890
},
91+
storage,
8992
});
9093
try {
9194
if (this.account) this.createWalletClient();

packages/sdk/src/client-auth-server/WalletProvider.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { EventEmitter } from "eventemitter3";
22
import type { Address, Chain, Transport } from "viem";
33
import { toHex } from "viem";
44

5+
import type { Communicator } from "../communicator/index.js";
56
import { PopupCommunicator } from "../communicator/PopupCommunicator.js";
67
import { serializeError, standardErrors } from "../errors/index.js";
78
import type { CustomPaymasterHandler } from "../paymaster/index.js";
89
import { getFavicon, getWebsiteName } from "../utils/helpers.js";
910
import type { SessionStateEvent } from "../utils/session.js";
11+
import type { StorageLike } from "../utils/storage.js";
1012
import type {
1113
AppMetadata,
1214
ProviderInterface,
@@ -27,15 +29,17 @@ export type WalletProviderConstructorOptions = {
2729
paymasterHandler?: CustomPaymasterHandler;
2830
onSessionStateChange?: (state: { address: Address; chainId: number; state: SessionStateEvent }) => void;
2931
skipPreTransactionStateValidation?: boolean; // Useful if you want to send session transactions really fast
32+
customCommunicator?: Communicator;
33+
storage?: StorageLike;
3034
};
3135

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

36-
constructor({ metadata, chains, transports, session, authServerUrl, paymasterHandler, onSessionStateChange, skipPreTransactionStateValidation }: WalletProviderConstructorOptions) {
40+
constructor({ metadata, chains, transports, session, authServerUrl, paymasterHandler, onSessionStateChange, skipPreTransactionStateValidation, customCommunicator, storage }: WalletProviderConstructorOptions) {
3741
super();
38-
const communicator = new PopupCommunicator(authServerUrl || DEFAULT_AUTH_SERVER_URL);
42+
const communicator = customCommunicator ?? new PopupCommunicator(authServerUrl || DEFAULT_AUTH_SERVER_URL);
3943
this.signer = new Signer({
4044
metadata: () => ({
4145
name: metadata?.name || getWebsiteName() || "Unknown DApp",
@@ -50,6 +54,7 @@ export class WalletProvider extends EventEmitter implements ProviderInterface {
5054
paymasterHandler,
5155
onSessionStateChange,
5256
skipPreTransactionStateValidation,
57+
storage,
5358
});
5459
}
5560

packages/sdk/src/communicator/PopupCommunicator.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,29 @@ import type { Communicator, Message } from "./index.js";
44
export interface PopupConfigMessage extends Message {
55
event: "PopupLoaded" | "PopupUnload";
66
}
7+
type PositionCalculator = (width: number, height: number) => { left: number; top: number };
78

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

13-
constructor(url: string) {
14+
private readonly width: number;
15+
private readonly height: number;
16+
private readonly calculatePosition?: PositionCalculator;
17+
18+
constructor(
19+
url: string,
20+
options?: {
21+
width?: number;
22+
height?: number;
23+
calculatePosition?: PositionCalculator;
24+
},
25+
) {
1426
this.url = new URL(url);
27+
this.width = options?.width ?? 420;
28+
this.height = options?.height ?? 600;
29+
this.calculatePosition = options?.calculatePosition;
1530
}
1631

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

6681
openPopup = () => {
67-
const width = 420;
68-
const height = 600;
82+
const width = this.width;
83+
const height = this.height;
6984

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

73-
const left = (window.innerWidth - width) / 2 + window.screenX;
74-
const top = (window.innerHeight - height) / 2 + window.screenY;
88+
const { left, top } = this.calculatePosition
89+
? this.calculatePosition(width, height)
90+
: {
91+
left: (window.innerWidth - width) / 2 + window.screenX,
92+
top: (window.innerHeight - height) / 2 + window.screenY,
93+
};
7594

7695
const popup = window.open(
7796
url,

packages/sdk/src/connector/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from "viem";
1818

1919
import type { ZksyncSsoSessionClient } from "../client/index.js";
20+
import type { Communicator } from "../communicator/interface.js";
2021
import { EthereumProviderError } from "../errors/errors.js";
2122
import { type AppMetadata, type ProviderInterface, type SessionPreferences, WalletProvider } from "../index.js";
2223
import type { CustomPaymasterHandler } from "../paymaster/index.js";
@@ -27,6 +28,7 @@ export type ZksyncSsoConnectorOptions = {
2728
session?: SessionPreferences | (() => SessionPreferences | Promise<SessionPreferences>);
2829
authServerUrl?: string;
2930
paymasterHandler?: CustomPaymasterHandler;
31+
communicator?: Communicator;
3032
};
3133

3234
export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
@@ -144,6 +146,7 @@ export const zksyncSsoConnector = (parameters: ZksyncSsoConnectorOptions) => {
144146
transports: config.transports,
145147
chains: config.chains,
146148
paymasterHandler: parameters.paymasterHandler,
149+
customCommunicator: parameters.communicator,
147150
});
148151
}
149152
return walletProvider;

packages/sdk/src/utils/storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
interface StorageLike {
1+
export interface StorageLike {
22
getItem(key: string): string | null;
33
setItem(key: string, value: string): void;
44
removeItem(key: string): void;

0 commit comments

Comments
 (0)