zksync-sso
Version:
ZKsync Smart Sign On SDK
172 lines • 7.17 kB
JavaScript
import { ChainNotConfiguredError, createConnector, getConnectorClient as wagmiGetConnectorClient, } from "@wagmi/core";
import { getAddress, SwitchChainError, toHex, UserRejectedRequestError, } from "viem";
import { EthereumProviderError } from "../errors/errors.js";
import { WalletProvider } from "../index.js";
export { callPolicy } from "../client-auth-server/index.js";
export const zksyncSsoConnector = (parameters) => {
let walletProvider;
let accountsChanged;
let chainChanged;
let disconnect;
const destroyWallet = () => {
if (walletProvider) {
if (accountsChanged) {
walletProvider.removeListener("accountsChanged", accountsChanged);
accountsChanged = undefined;
}
if (chainChanged) {
walletProvider.removeListener("chainChanged", chainChanged);
chainChanged = undefined;
}
if (disconnect) {
walletProvider.removeListener("disconnect", disconnect);
disconnect = undefined;
}
}
walletProvider = undefined;
};
return createConnector((config) => ({
icon: parameters.connectorMetadata?.icon ?? "https://zksync.io/favicon.ico",
id: parameters.connectorMetadata?.id ?? "zksync-sso",
name: parameters.connectorMetadata?.name ?? "ZKsync",
type: parameters.connectorMetadata?.type ?? "zksync-sso",
// supportsSimulation: true,
async connect({ chainId } = {}) {
try {
const provider = await this.getProvider();
const accounts = (await provider.request({
method: "eth_requestAccounts",
})).map((x) => getAddress(x));
if (!accountsChanged) {
accountsChanged = this.onAccountsChanged.bind(this);
provider.on("accountsChanged", accountsChanged);
}
if (!chainChanged) {
chainChanged = this.onChainChanged.bind(this);
provider.on("chainChanged", chainChanged);
}
if (!disconnect) {
disconnect = this.onDisconnect.bind(this);
provider.on("disconnect", disconnect);
}
// Switch to chain if provided
let walletChainId = await this.getChainId();
if (chainId && walletChainId !== chainId) {
const chain = await this.switchChain({ chainId }).catch((error) => {
if (error.code === UserRejectedRequestError.code)
throw error;
return { id: walletChainId };
});
walletChainId = chain?.id ?? walletChainId;
}
return { accounts, chainId: walletChainId };
}
catch (error) {
console.error(`Error connecting to ${this.name}`, error);
if (/(user closed modal|accounts received is empty|user denied account|request rejected)/i.test(error.message))
throw new UserRejectedRequestError(error);
throw error;
}
},
async disconnect() {
const provider = await this.getProvider();
provider.disconnect();
destroyWallet();
},
async getAccounts() {
const provider = await this.getProvider();
return (await provider.request({
method: "eth_accounts",
})).map((x) => getAddress(x));
},
async getChainId() {
const provider = await this.getProvider();
const chainId = await provider.request({
method: "eth_chainId",
});
if (!chainId)
return config.chains[0].id;
return Number(chainId);
},
async getClient(parameters) {
if (!walletProvider)
throw new Error("Wallet provider not initialized");
return walletProvider.getClient(parameters);
},
async getProvider() {
if (!walletProvider) {
walletProvider = parameters.provider ?? new WalletProvider({
metadata: {
name: parameters.metadata?.name,
icon: parameters.metadata?.icon,
configData: parameters.metadata?.configData,
},
authServerUrl: parameters.authServerUrl,
session: parameters.session,
transports: config.transports,
chains: config.chains,
paymasterHandler: parameters.paymasterHandler,
customCommunicator: parameters.communicator,
});
}
return walletProvider;
},
async isAuthorized() {
try {
const accounts = await this.getAccounts();
return !!accounts.length;
}
catch {
return false;
}
},
async switchChain({ chainId }) {
const chain = config.chains.find((chain) => chain.id === chainId);
if (!chain)
throw new SwitchChainError(new ChainNotConfiguredError());
try {
const provider = await this.getProvider();
await provider.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: toHex(chainId) }],
});
return chain;
}
catch (error) {
throw new SwitchChainError(error);
}
},
onAccountsChanged(accounts) {
if (!accounts.length)
return;
config.emitter.emit("change", {
accounts: accounts.map((x) => getAddress(x)),
});
},
onChainChanged(chain) {
config.emitter.emit("change", { chainId: Number(chain) });
},
async onDisconnect(error) {
config.emitter.emit("disconnect");
if (error instanceof EthereumProviderError && error.code === 4900)
return; // User initiated
console.error("Account disconnected", error);
},
}));
};
export const isSsoSessionClient = (client) => {
return client.key === "zksync-sso-session-wallet";
};
export const isSsoSessionClientConnected = async (config, parameters = {}) => {
const connectorClient = await wagmiGetConnectorClient(config, parameters);
return isSsoSessionClient(connectorClient);
};
export const getConnectedSsoSessionClient = async (config, parameters = {}) => {
const connectorClient = await wagmiGetConnectorClient(config, parameters);
if (!isSsoSessionClient(connectorClient)) {
throw new Error("ZKsync SSO Session Client not connected");
}
const sessionClient = connectorClient;
return sessionClient;
};
//# sourceMappingURL=index.js.map