@0xfutbol/id
Version:
React component library with shared providers for 0xFutbol ID
486 lines (485 loc) • 18.3 kB
JavaScript
'use strict';var index=require('./index-DwkZmKdT.js');require('react'),require('react/jsx-runtime'),require('@0xfutbol/id-sign'),require('react-use'),require('@0xfutbol/constants'),require('thirdweb'),require('@matchain/matchid-sdk-react'),require('@tanstack/react-query'),require('@matchain/matchid-sdk-react/index.css'),require('react-dom');const getUrl = (url) => url;class RpcRequestError extends index.B {
constructor({ body, error, url, }) {
super('RPC Request failed.', {
cause: error,
details: error.message,
metaMessages: [`URL: ${getUrl(url)}`, `Request body: ${index.q(body)}`],
name: 'RpcRequestError',
});
Object.defineProperty(this, "code", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
Object.defineProperty(this, "data", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.code = error.code;
this.data = error.data;
}
}const unknownErrorCode = -1;
class RpcError extends index.B {
constructor(cause, { code, docsPath, metaMessages, name, shortMessage, }) {
super(shortMessage, {
cause,
docsPath,
metaMessages: metaMessages || cause?.metaMessages,
name: name || 'RpcError',
});
Object.defineProperty(this, "code", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.name = name || cause.name;
this.code = (cause instanceof RpcRequestError ? cause.code : (code ?? unknownErrorCode));
}
}
class ProviderRpcError extends RpcError {
constructor(cause, options) {
super(cause, options);
Object.defineProperty(this, "data", {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this.data = options.data;
}
}
class UserRejectedRequestError extends ProviderRpcError {
constructor(cause) {
super(cause, {
code: UserRejectedRequestError.code,
name: 'UserRejectedRequestError',
shortMessage: 'User rejected the request.',
});
}
}
Object.defineProperty(UserRejectedRequestError, "code", {
enumerable: true,
configurable: true,
writable: true,
value: 4001
});
class SwitchChainError extends ProviderRpcError {
constructor(cause) {
super(cause, {
code: SwitchChainError.code,
name: 'SwitchChainError',
shortMessage: 'An error occurred when attempting to switch chain.',
});
}
}
Object.defineProperty(SwitchChainError, "code", {
enumerable: true,
configurable: true,
writable: true,
value: 4902
});const ADD_ETH_CHAIN_METHOD = "wallet_addEthereumChain";
const defaultShowQrModal = true;
const storageKeys = {
requestedChains: "tw.wc.requestedChains",
lastUsedChainId: "tw.wc.lastUsedChainId",
};
/**
* @internal
*/
async function connectWC(options, emitter, walletId, storage, sessionHandler) {
const provider = await initProvider(options, walletId, sessionHandler);
const wcOptions = options.walletConnect;
let { onDisplayUri } = wcOptions || {};
// use default sessionHandler unless onDisplayUri is explicitly provided
if (!onDisplayUri && sessionHandler) {
const walletInfo = await index.x(walletId);
const deeplinkHandler = (uri) => {
const appUrl = walletInfo.mobile.native || walletInfo.mobile.universal;
if (!appUrl) {
// generic wc uri
sessionHandler(uri);
return;
}
const fullUrl = index.A(appUrl, uri).redirect;
sessionHandler(fullUrl);
};
onDisplayUri = deeplinkHandler;
}
if (onDisplayUri) {
provider.events.addListener("display_uri", onDisplayUri);
}
let optionalChains = wcOptions?.optionalChains;
let chainToRequest = options.chain;
// ignore the given options chains - and set the safe supported chains
if (walletId === "global.safe") {
optionalChains = chainsToRequestForSafe.map(index.h);
if (chainToRequest && !optionalChains.includes(chainToRequest)) {
chainToRequest = undefined;
}
}
const { rpcMap, requiredChain, optionalChains: chainsToRequest, } = getChainsToRequest({
client: options.client,
chain: chainToRequest,
optionalChains: optionalChains,
});
if (provider.session) {
await provider.connect({
...(wcOptions?.pairingTopic
? { pairingTopic: wcOptions?.pairingTopic }
: {}),
optionalChains: chainsToRequest,
chains: requiredChain ? [requiredChain.id] : undefined,
rpcMap: rpcMap,
});
}
setRequestedChainsIds(chainsToRequest, storage);
// If session exists and chains are authorized, enable provider for required chain
const addresses = await provider.enable();
const address = addresses[0];
if (!address) {
throw new Error("No accounts found on provider.");
}
const providerChainId = index.v(provider.chainId);
const chain = options.chain && options.chain.id === providerChainId
? options.chain
: index.h(providerChainId);
if (options) {
const savedParams = {
optionalChains: options.walletConnect?.optionalChains,
chain: options.chain,
pairingTopic: options.walletConnect?.pairingTopic,
};
if (storage) {
index.y(storage, walletId, savedParams);
}
}
if (wcOptions?.onDisplayUri) {
provider.events.removeListener("display_uri", wcOptions.onDisplayUri);
}
return onConnect(address, chain, provider, emitter, storage, options.client);
}
/**
* Auto connect to already connected wallet connect session.
* @internal
*/
async function autoConnectWC(options, emitter, walletId, storage, sessionHandler) {
const savedConnectParams = storage
? await index.u(storage, walletId)
: null;
const provider = await initProvider(savedConnectParams
? {
chain: savedConnectParams.chain,
client: options.client,
walletConnect: {
pairingTopic: savedConnectParams.pairingTopic,
optionalChains: savedConnectParams.optionalChains,
},
}
: {
client: options.client,
walletConnect: {},
}, walletId, sessionHandler, true);
const address = provider.accounts[0];
if (!address) {
throw new Error("No accounts found on provider.");
}
const providerChainId = index.v(provider.chainId);
const chain = options.chain && options.chain.id === providerChainId
? options.chain
: index.h(providerChainId);
return onConnect(address, chain, provider, emitter, storage, options.client);
}
// Connection utils -----------------------------------------------------------------------------------------------
async function initProvider(options, walletId, sessionRequestHandler, isAutoConnect = false) {
const walletInfo = await index.x(walletId);
const wcOptions = options.walletConnect;
const { EthereumProvider, OPTIONAL_EVENTS, OPTIONAL_METHODS } = await Promise.resolve().then(function(){return require('./index.es-oF9YjnI8.js')});
let optionalChains = wcOptions?.optionalChains;
let chainToRequest = options.chain;
// ignore the given options chains - and set the safe supported chains
if (walletId === "global.safe") {
optionalChains = chainsToRequestForSafe.map(index.h);
if (chainToRequest && !optionalChains.includes(chainToRequest)) {
chainToRequest = undefined;
}
}
const { rpcMap, requiredChain, optionalChains: chainsToRequest, } = getChainsToRequest({
client: options.client,
chain: chainToRequest,
optionalChains: optionalChains,
});
const provider = await EthereumProvider.init({
showQrModal: wcOptions?.showQrModal === undefined
? sessionRequestHandler
? false
: defaultShowQrModal
: wcOptions.showQrModal,
projectId: wcOptions?.projectId || index.D,
optionalMethods: OPTIONAL_METHODS,
optionalEvents: OPTIONAL_EVENTS,
optionalChains: chainsToRequest,
chains: requiredChain ? [requiredChain.id] : undefined,
metadata: {
name: wcOptions?.appMetadata?.name || index.z().name,
description: wcOptions?.appMetadata?.description ||
index.z().description,
url: wcOptions?.appMetadata?.url || index.z().url,
icons: [
wcOptions?.appMetadata?.logoUrl || index.z().logoUrl,
],
},
rpcMap: rpcMap,
qrModalOptions: wcOptions?.qrModalOptions,
disableProviderPing: true,
});
provider.events.setMaxListeners(Number.POSITIVE_INFINITY);
// disconnect the provider if chains are stale when (if not auto connecting)
if (!isAutoConnect) {
// const isStale = await isChainsStale(provider, chainsToRequest);
if (provider.session) {
await provider.disconnect();
}
}
if (walletId !== "walletConnect") {
async function handleSessionRequest() {
const walletLinkToOpen = provider.session?.peer?.metadata?.redirect?.native ||
walletInfo.mobile.native ||
walletInfo.mobile.universal;
if (sessionRequestHandler && walletLinkToOpen) {
// TODO: propagate error when this fails
await sessionRequestHandler(walletLinkToOpen);
}
}
provider.signer.client.on("session_request_sent", handleSessionRequest);
provider.events.addListener("disconnect", () => {
provider.signer.client.off("session_request_sent", handleSessionRequest);
});
}
return provider;
}
function createAccount({ provider, address, client, }) {
const account = {
address: address,
async sendTransaction(tx) {
const transactionHash = (await provider.request({
method: "eth_sendTransaction",
params: [
{
gas: tx.gas ? index.H(tx.gas) : undefined,
value: tx.value ? index.H(tx.value) : undefined,
from: index.d(address),
to: tx.to,
data: tx.data,
},
],
}));
index.t({
client: client,
walletAddress: index.d(address),
walletType: "walletConnect",
transactionHash,
chainId: tx.chainId,
contractAddress: tx.to ?? undefined,
gasPrice: tx.gasPrice,
});
return {
transactionHash,
};
},
async signMessage({ message }) {
const messageToSign = (() => {
if (typeof message === "string") {
return index.M(message);
}
if (message.raw instanceof Uint8Array) {
return index.N(message.raw);
}
return message.raw;
})();
return provider.request({
method: "personal_sign",
params: [messageToSign, this.address],
});
},
async signTypedData(_data) {
const data = index.p(_data);
const { domain, message, primaryType } = data;
const types = {
EIP712Domain: index.J({ domain }),
...data.types,
};
// Need to do a runtime validation check on addresses, byte ranges, integer ranges, etc
// as we can't statically check this with TypeScript.
index.K({ domain, message, primaryType, types });
const typedData = index.L({
domain: domain ?? {},
message,
primaryType,
types,
});
return await provider.request({
method: "eth_signTypedData_v4",
params: [this.address, typedData],
});
},
};
return account;
}
function onConnect(address, chain, provider, emitter, storage, client) {
const account = createAccount({ provider, address, client });
async function disconnect() {
provider.removeListener("accountsChanged", onAccountsChanged);
provider.removeListener("chainChanged", onChainChanged);
provider.removeListener("disconnect", onDisconnect);
await provider.disconnect();
}
function onDisconnect() {
setRequestedChainsIds([], storage);
storage?.removeItem(storageKeys.lastUsedChainId);
disconnect();
emitter.emit("disconnect", undefined);
}
function onAccountsChanged(accounts) {
if (accounts[0]) {
const newAccount = createAccount({
provider,
address: index.d(accounts[0]),
client,
});
emitter.emit("accountChanged", newAccount);
emitter.emit("accountsChanged", accounts);
}
else {
onDisconnect();
}
}
function onChainChanged(newChainId) {
const newChain = index.h(index.v(newChainId));
emitter.emit("chainChanged", newChain);
storage?.setItem(storageKeys.lastUsedChainId, String(newChainId));
}
provider.on("accountsChanged", onAccountsChanged);
provider.on("chainChanged", onChainChanged);
provider.on("disconnect", onDisconnect);
provider.on("session_delete", onDisconnect);
return [
account,
chain,
disconnect,
(newChain) => switchChainWC(provider, newChain, storage),
];
}
// Storage utils -----------------------------------------------------------------------------------------------
function getNamespaceMethods(provider) {
return provider.session?.namespaces[index.O]?.methods || [];
}
function getNamespaceChainsIds(provider) {
const chainIds = provider.session?.namespaces[index.O]?.chains?.map((chain) => Number.parseInt(chain.split(":")[1] || ""));
return chainIds ?? [];
}
async function switchChainWC(provider, chain, storage) {
const chainId = chain.id;
try {
const namespaceChains = getNamespaceChainsIds(provider);
const namespaceMethods = getNamespaceMethods(provider);
const isChainApproved = namespaceChains.includes(chainId);
if (!isChainApproved && namespaceMethods.includes(ADD_ETH_CHAIN_METHOD)) {
const apiChain = await index.F(chain);
const blockExplorerUrls = [
...new Set([
...(chain.blockExplorers?.map((x) => x.url) || []),
...(apiChain.explorers?.map((x) => x.url) || []),
]),
];
await provider.request({
method: ADD_ETH_CHAIN_METHOD,
params: [
{
chainId: index.H(apiChain.chainId),
chainName: apiChain.name,
nativeCurrency: apiChain.nativeCurrency,
rpcUrls: index.G(apiChain), // no clientId on purpose
blockExplorerUrls: blockExplorerUrls.length > 0 ? blockExplorerUrls : undefined,
},
],
});
const requestedChains = await getRequestedChainsIds(storage);
requestedChains.push(chainId);
setRequestedChainsIds(requestedChains, storage);
}
await provider.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: index.H(chainId) }],
});
}
catch (error) {
const message = typeof error === "string" ? error : error?.message;
if (/user rejected request/i.test(message)) {
throw new UserRejectedRequestError(error);
}
throw new SwitchChainError(error);
}
}
/**
* Set the requested chains to the storage.
* @internal
*/
function setRequestedChainsIds(chains, storage) {
storage?.setItem(storageKeys.requestedChains, index.s(chains));
}
/**
* Get the last requested chains from the storage.
* @internal
*/
async function getRequestedChainsIds(storage) {
const data = await storage.getItem(storageKeys.requestedChains);
return data ? JSON.parse(data) : [];
}
function getChainsToRequest(options) {
const rpcMap = {};
if (options.chain) {
rpcMap[options.chain.id] = index.E({
chain: options.chain,
client: options.client,
});
}
// limit optional chains to 10
const optionalChains = (options?.optionalChains || []).slice(0, 10);
for (const chain of optionalChains) {
rpcMap[chain.id] = index.E({
chain: chain,
client: options.client,
});
}
if (!options.chain && optionalChains.length === 0) {
rpcMap[1] = index.h(1).rpc;
}
return {
rpcMap,
requiredChain: options.chain ? options.chain : undefined,
optionalChains: optionalChains.length > 0
? optionalChains.map((x) => x.id)
: [1],
};
}
const chainsToRequestForSafe = [
1, // Ethereum Mainnet
11155111, // Sepolia Testnet
42161, // Arbitrum One Mainnet
43114, // Avalanche Mainnet
8453, // Base Mainnet
1313161554, // Aurora Mainnet
84532, // Base Sepolia Testnet
56, // Binance Smart Chain Mainnet
42220, // Celo Mainnet
100, // Gnosis Mainnet
10, // Optimism Mainnet
137, // Polygon Mainnet
1101, // Polygon zkEVM Mainnet
324, // zkSync Era mainnet
534352, // Scroll mainnet
];exports.autoConnectWC=autoConnectWC;exports.connectWC=connectWC;//# sourceMappingURL=controller-Bgbfc-MW.js.map