import { RequestArguments } from './providers/base-provider'; import { PrexClient } from './prex-client'; import { ApprovalRequestFunction, PrexClientOptions } from './types'; export class WalletMessageReceiver extends PrexClient { allowedOrigins: string[]; approvalRequestFn?: ApprovalRequestFunction; approvedOrigins: string[] = []; constructor( chainId: number, policyId: string, options: PrexClientOptions & { allowedOrigins?: string[]; approvalRequestFn?: ApprovalRequestFunction; } ) { super(chainId, policyId, options); this.allowedOrigins = options.allowedOrigins || []; this.approvalRequestFn = options.approvalRequestFn; } async startHandler() { window.addEventListener('message', async (event) => { if (!this.allowedOrigins.includes(event.origin)) return; if (this.approvalRequestFn) { if (!this.approvedOrigins.includes(event.origin)) { const approval = await this.approvalRequestFn(event.origin); if (!approval) { throw new Error('Approval denied'); } this.approvedOrigins.push(event.origin); } } if (!!event.data.data.method) { const approval = await this.checkApproval(event.data.data); if (!approval) { throw new Error('Approval denied'); } const response = await this.signer?.provider?.request(event.data.data); event.source?.postMessage( { id: event.data.id, requestId: event.data.id, data: response, }, { targetOrigin: event.origin, } ); } }); window.opener.postMessage( { event: 'PopupLoaded', }, this.allowedOrigins[0] ); } async checkApproval(request: RequestArguments) { if (!this.approvalRequestFn) { return true; } const { method, params } = request; switch (method) { case 'eth_requestAccounts': return true; case 'eth_sign': if (Array.isArray(params)) { return this.approvalRequestFn({ contractAddress: params[0], hash: params[1], }); } else { throw new Error('invalid params'); } case 'eth_signTypedData_v4': if (Array.isArray(params)) { return this.approvalRequestFn(params[1]); } else { throw new Error('invalid params'); } default: return true; } } }