UNPKG

burner-connector

Version:
169 lines 7.45 kB
import { createConnector, normalizeChainId } from "wagmi"; import { http, BaseError, RpcRequestError, SwitchChainError, createWalletClient, custom, fromHex, getAddress, } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { getHttpRpcClient, hexToBigInt, hexToNumber, numberToHex } from "viem/utils"; import { burnerWalletId, burnerWalletName, loadBurnerPK } from "../utils/index.js"; export class ConnectorNotConnectedError extends BaseError { constructor() { super("Connector not connected."); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: "ConnectorNotConnectedError" }); } } export class ChainNotConfiguredError extends BaseError { constructor() { super("Chain not configured."); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: "ChainNotConfiguredError" }); } } export const burner = ({ useSessionStorage = false, rpcUrls = {} } = {}) => { let connected = true; let connectedChainId; return createConnector((config) => ({ id: burnerWalletId, name: burnerWalletName, type: burnerWalletId, async connect({ chainId } = {}) { const provider = await this.getProvider(); const accounts = await provider.request({ method: "eth_accounts", }); let currentChainId = await this.getChainId(); if (chainId && currentChainId !== chainId && this.switchChain) { const chain = await this.switchChain({ chainId }); currentChainId = chain.id; } connected = true; return { accounts, chainId: currentChainId }; }, async getProvider({ chainId } = {}) { const chain = config.chains.find((x) => x.id === chainId) ?? config.chains[0]; // Use custom RPC URL if provided, otherwise fallback to default const url = rpcUrls[chain.id] || chain.rpcUrls.default.http[0]; if (!url) throw new Error("No rpc url found for chain"); const burnerAccount = privateKeyToAccount(loadBurnerPK({ useSessionStorage })); const client = createWalletClient({ chain: chain, account: burnerAccount, transport: http(url), }); const request = async ({ method, params }) => { if (method === "eth_sendTransaction") { const actualParams = params[0]; const hash = await client.sendTransaction({ account: burnerAccount, data: actualParams?.data, to: actualParams?.to, value: actualParams?.value ? hexToBigInt(actualParams.value) : undefined, gas: actualParams?.gas ? hexToBigInt(actualParams.gas) : undefined, nonce: actualParams?.nonce ? hexToNumber(actualParams.nonce) : undefined, maxPriorityFeePerGas: actualParams?.maxPriorityFeePerGas ? hexToBigInt(actualParams.maxPriorityFeePerGas) : undefined, maxFeePerGas: actualParams?.maxFeePerGas ? hexToBigInt(actualParams.maxFeePerGas) : undefined, gasPrice: (actualParams?.gasPrice ? hexToBigInt(actualParams.gasPrice) : undefined), }); return hash; } if (method === "personal_sign") { // first param is Hex data representation of message, // second param is address of the signer const rawMessage = params[0]; const signature = await client.signMessage({ account: burnerAccount, message: { raw: rawMessage }, }); return signature; } if (method === "eth_signTypedData_v4") { // first param is address of the signer // second param is stringified typed data const stringifiedData = params[1]; const signature = await client.signTypedData(JSON.parse(stringifiedData)); return signature; } if (method === "eth_accounts") { return [burnerAccount.address]; } if (method === "wallet_switchEthereumChain") { connectedChainId = fromHex(params[0].chainId, "number"); this.onChainChanged(connectedChainId.toString()); return; } const body = { method, params }; const httpClient = getHttpRpcClient(url); const { error, result } = await httpClient.request({ body }); if (error) throw new RpcRequestError({ body, error, url }); return result; }; return custom({ request })({ retryCount: 0 }); }, onChainChanged(chain) { const chainId = normalizeChainId(chain); config.emitter.emit("change", { chainId }); }, async getAccounts() { if (!connected) throw new ConnectorNotConnectedError(); const provider = await this.getProvider(); const accounts = await provider.request({ method: "eth_accounts" }); const burnerAddress = accounts.map((x) => getAddress(x))[0]; return [burnerAddress]; }, async onDisconnect() { config.emitter.emit("disconnect"); connected = false; }, async getChainId() { const provider = await this.getProvider(); const hexChainId = await provider.request({ method: "eth_chainId" }); return fromHex(hexChainId, "number"); }, async isAuthorized() { if (!connected) return false; const accounts = await this.getAccounts(); return !!accounts.length; }, onAccountsChanged(accounts) { if (accounts.length === 0) this.onDisconnect(); else config.emitter.emit("change", { accounts: accounts.map((x) => getAddress(x)), }); }, async switchChain({ chainId }) { const provider = await this.getProvider(); const chain = config.chains.find((x) => x.id === chainId); if (!chain) throw new SwitchChainError(new ChainNotConfiguredError()); await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: numberToHex(chainId) }], }); return chain; }, disconnect() { console.log("disconnect from burnerwallet"); connected = false; return Promise.resolve(); }, })); }; //# sourceMappingURL=burner.js.map