@arbius/aa-wallet
Version:
A secure and flexible Account Abstraction wallet implementation for Arbitrum One chain applications.
126 lines (125 loc) • 4.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupEthereumProxy = setupEthereumProxy;
const init_1 = require("./init");
const transactionQueue_1 = require("./transactionQueue");
// Store the original ethereum object
let originalEthereum = null;
/**
* Setup the ethereum proxy to intercept window.ethereum calls
*/
function setupEthereumProxy() {
// Ensure the wallet is initialized
if (!(0, init_1.isInitialized)()) {
throw new Error('AA Wallet must be initialized before setting up ethereum proxy');
}
// Check if window.ethereum exists
if (typeof window === 'undefined' || !window.ethereum) {
console.warn('window.ethereum not found. Ethereum proxy not set up.');
return;
}
// Store the original ethereum object
originalEthereum = window.ethereum;
// Create the proxy
const ethereumProxy = createEthereumProxy(originalEthereum);
// Replace window.ethereum with our proxy
Object.defineProperty(window, 'ethereum', {
value: ethereumProxy,
writable: true,
configurable: true,
});
console.log('Ethereum proxy set up successfully');
}
/**
* Create an ethereum proxy object
* @param target The original ethereum object
* @returns The proxied ethereum object
*/
function createEthereumProxy(target) {
return new Proxy(target, {
get(target, prop, receiver) {
// Add the isAA flag
if (prop === 'isAA') {
return true;
}
// Get the original property
const originalProp = Reflect.get(target, prop, receiver);
// If the property is a function, we might need to intercept it
if (typeof originalProp === 'function') {
return function (...args) {
// Intercept eth_sendTransaction requests
if (prop === 'request' && args[0]?.method === 'eth_sendTransaction') {
return handleSendTransaction(args[0]);
}
// Intercept personal_sign requests
if (prop === 'request' && args[0]?.method === 'personal_sign') {
return handlePersonalSign(args[0]);
}
// Pass through all other requests
return originalProp.apply(this, args);
};
}
// Return the original property for everything else
return originalProp;
}
});
}
/**
* Handle eth_sendTransaction requests
* @param request The original request
* @returns Promise resolving to the transaction hash
*/
async function handleSendTransaction(request) {
console.log('Intercepted eth_sendTransaction:', request);
// Get the current chain ID
const chainId = await getCurrentChainId();
// Create a transaction object
const transaction = {
method: request.method,
params: request.params,
chainId,
};
// Send the transaction through our transaction queue
return (0, transactionQueue_1.sendTransaction)(transaction);
}
/**
* Handle personal_sign requests
* @param request The original request
* @returns Promise resolving to the signature
*/
async function handlePersonalSign(request) {
console.log('Intercepted personal_sign:', request);
// Get the current website URL
const websiteUrl = window.location.origin;
const websiteName = new URL(websiteUrl).hostname;
// Modify the message to include the website URL and address
const [message, address] = request.params;
const enhancedMessage = `Arbius Wallet: Create deterministic wallet on ${websiteName} for ${address}\nMake sure you check ${websiteName} is the same!`;
// Create a new request with the enhanced message
const enhancedRequest = {
...request,
params: [enhancedMessage, address]
};
// Pass through to the original ethereum object with enhanced message
return originalEthereum.request(enhancedRequest);
}
/**
* Get the current chain ID
* @returns Promise resolving to the current chain ID
*/
async function getCurrentChainId() {
// Try to get from the original ethereum object
try {
const chainIdHex = await originalEthereum.request({ method: 'eth_chainId' });
return parseInt(chainIdHex, 16);
}
catch (error) {
// Fall back to the default chain ID from config
const config = (0, init_1.getConfig)();
if (config) {
return config.defaultChainId;
}
// Default to Ethereum mainnet if all else fails
return 1;
}
}