Files
metamask-integration/examples/smart-accounts-example.html
2026-03-02 12:14:14 -08:00

274 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart Accounts Example - ChainID 138</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
h1 {
color: #333;
}
h2 {
color: #555;
margin-top: 0;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 12px 24px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 10px 5px;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.3s;
}
button:hover:not(:disabled) {
background-color: #45a049;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.error {
background-color: #f44336;
color: white;
padding: 15px;
border-radius: 4px;
margin: 20px 0;
}
.success {
background-color: #4CAF50;
color: white;
padding: 15px;
border-radius: 4px;
margin: 20px 0;
}
.info {
background-color: #2196F3;
color: white;
padding: 15px;
border-radius: 4px;
margin: 20px 0;
}
code {
background-color: #f4f4f4;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}
.address {
word-break: break-all;
font-family: monospace;
background-color: #f4f4f4;
padding: 10px;
border-radius: 4px;
margin: 10px 0;
}
</style>
</head>
<body>
<h1>Smart Accounts Example</h1>
<p><strong>ChainID 138 - SMOM-DBIS-138</strong></p>
<div id="error" class="error" style="display: none;"></div>
<div id="success" class="success" style="display: none;"></div>
<div id="info" class="info" style="display: none;"></div>
<div class="container">
<h2>1. Connect Wallet</h2>
<p>Connect your MetaMask wallet to get started.</p>
<button id="connectBtn" onclick="connectWallet()">Connect MetaMask</button>
<div id="walletInfo" style="display: none;">
<p><strong>Connected Address:</strong></p>
<div class="address" id="userAddress"></div>
</div>
</div>
<div class="container" id="smartAccountSection" style="display: none;">
<h2>2. Create Smart Account</h2>
<p>Create a new Smart Account linked to your wallet.</p>
<button id="createAccountBtn" onclick="createSmartAccount()">Create Smart Account</button>
<div id="accountInfo" style="display: none;">
<p><strong>Smart Account Address:</strong></p>
<div class="address" id="accountAddress"></div>
<p><strong>Owner:</strong></p>
<div class="address" id="accountOwner"></div>
</div>
</div>
<div class="container" id="delegationSection" style="display: none;">
<h2>3. Request Delegation</h2>
<p>Request delegation for a dApp or service to execute transactions on your behalf.</p>
<label for="targetAddress">Target Address:</label>
<input type="text" id="targetAddress" placeholder="0x..." style="width: 100%; padding: 8px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px;">
<button id="requestDelegationBtn" onclick="requestDelegation()">Request Delegation</button>
<div id="delegationInfo" style="display: none;">
<p><strong>Delegation Status:</strong></p>
<div id="delegationStatus"></div>
</div>
</div>
<div class="container" id="batchSection" style="display: none;">
<h2>4. Batch Operations</h2>
<p>Execute multiple operations in a single transaction.</p>
<button id="batchBtn" onclick="batchOperations()">Execute Batch</button>
<div id="batchInfo" style="display: none;">
<p><strong>Batch Transaction:</strong></p>
<div class="address" id="batchTx"></div>
</div>
</div>
<script type="module">
// Note: This is a simplified example. In production, you would:
// 1. Use a bundler (webpack, vite, etc.)
// 2. Import SmartAccountsKit properly
// 3. Handle errors more gracefully
// 4. Add proper TypeScript types
// For this HTML example, we'll use a simplified approach
// In production, use the React or Vue examples instead
let userAddress = '';
let smartAccountAddress = '';
let smartAccountsKit = null;
// Check if MetaMask is installed
if (typeof window.ethereum === 'undefined') {
showError('MetaMask is not installed. Please install MetaMask to continue.');
document.getElementById('connectBtn').disabled = true;
}
// Load configuration (in production, this would be from a config file)
const config = {
chainId: 138,
rpcUrl: 'https://rpc.d-bis.org',
entryPointAddress: '', // Set after deployment
accountFactoryAddress: '', // Set after deployment
};
window.connectWallet = async function() {
try {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
userAddress = accounts[0];
document.getElementById('userAddress').textContent = userAddress;
document.getElementById('walletInfo').style.display = 'block';
document.getElementById('smartAccountSection').style.display = 'block';
showSuccess('Wallet connected successfully!');
} catch (error) {
showError('Failed to connect wallet: ' + error.message);
}
};
window.createSmartAccount = async function() {
try {
showInfo('Creating Smart Account...');
// In production, use SmartAccountsKit:
// const kit = new SmartAccountsKit(config);
// const account = await kit.createAccount({ owner: userAddress });
// For demo purposes, we'll simulate:
smartAccountAddress = '0x' + Array.from({length: 40}, () => Math.floor(Math.random() * 16).toString(16)).join('');
document.getElementById('accountAddress').textContent = smartAccountAddress;
document.getElementById('accountOwner').textContent = userAddress;
document.getElementById('accountInfo').style.display = 'block';
document.getElementById('delegationSection').style.display = 'block';
document.getElementById('batchSection').style.display = 'block';
showSuccess('Smart Account created successfully!');
} catch (error) {
showError('Failed to create Smart Account: ' + error.message);
}
};
window.requestDelegation = async function() {
const target = document.getElementById('targetAddress').value;
if (!target || !target.startsWith('0x')) {
showError('Please enter a valid target address');
return;
}
try {
showInfo('Requesting delegation...');
// In production, use SmartAccountsKit:
// const delegation = await kit.requestDelegation({ target, permissions: [...], expiry: ... });
// For demo purposes, we'll simulate:
document.getElementById('delegationStatus').innerHTML = `
<strong>Target:</strong> ${target}<br>
<strong>Status:</strong> Approved<br>
<strong>Expires:</strong> ${new Date(Date.now() + 86400000).toLocaleString()}
`;
document.getElementById('delegationInfo').style.display = 'block';
showSuccess('Delegation requested successfully!');
} catch (error) {
showError('Failed to request delegation: ' + error.message);
}
};
window.batchOperations = async function() {
try {
showInfo('Executing batch operations...');
// In production, use SmartAccountsKit:
// const userOps = await kit.batchUserOperations([...]);
// const result = await kit.executeBatch(userOps);
// For demo purposes, we'll simulate:
const txHash = '0x' + Array.from({length: 64}, () => Math.floor(Math.random() * 16).toString(16)).join('');
document.getElementById('batchTx').textContent = txHash;
document.getElementById('batchInfo').style.display = 'block';
showSuccess('Batch operations executed successfully!');
} catch (error) {
showError('Failed to execute batch: ' + error.message);
}
};
function showError(message) {
const el = document.getElementById('error');
el.textContent = message;
el.style.display = 'block';
setTimeout(() => el.style.display = 'none', 5000);
}
function showSuccess(message) {
const el = document.getElementById('success');
el.textContent = message;
el.style.display = 'block';
setTimeout(() => el.style.display = 'none', 5000);
}
function showInfo(message) {
const el = document.getElementById('info');
el.textContent = message;
el.style.display = 'block';
setTimeout(() => el.style.display = 'none', 3000);
}
</script>
</body>
</html>