Skip to content

Instantly share code, notes, and snippets.

@TABASCOatw
Created April 24, 2024 22:26
Show Gist options
  • Save TABASCOatw/4d03c67a510b550b2acd974884b28171 to your computer and use it in GitHub Desktop.
Save TABASCOatw/4d03c67a510b550b2acd974884b28171 to your computer and use it in GitHub Desktop.
XLayer Demo App.tsx (Smart Wallet-as-a-Service)
import React, { useState, useEffect } from 'react';
import { XLayer, XLayerTestnet } from '@particle-network/chains';
import { AAWrapProvider, SendTransactionMode, SmartAccount } from '@particle-network/aa';
import { useEthereum, useConnect, useAuthCore } from '@particle-network/auth-core-modal';
import { ethers } from 'ethers';
import { notification } from 'antd';
import './App.css';
const App = () => {
const { provider } = useEthereum();
const { connect, disconnect } = useConnect();
const { userInfo } = useAuthCore();
const [balance, setBalance] = useState(null);
const smartAccount = new SmartAccount(provider, {
projectId: process.env.REACT_APP_PROJECT_ID,
clientKey: process.env.REACT_APP_CLIENT_KEY,
appId: process.env.REACT_APP_APP_ID,
aaOptions: {
accountContracts: {
SIMPLE: [{ chainIds: [XLayerTestnet.id], version: '1.0.0' }],
}
}
});
const customProvider = new ethers.providers.Web3Provider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless), "any");
useEffect(() => {
if (userInfo) {
fetchBalance();
}
}, [userInfo]);
const fetchBalance = async () => {
const address = await smartAccount.getAddress();
const balanceResponse = await customProvider.getBalance(address);
setBalance(ethers.utils.formatEther(balanceResponse));
};
const handleLogin = async (socialType) => {
if (!userInfo) {
await connect({
socialType,
chain: XLayerTestnet
});
}
};
const executeUserOp = async () => {
const signer = customProvider.getSigner();
const tx = {
to: "0x000000000000000000000000000000000000dEaD",
value: ethers.utils.parseEther('0.001')
};
const txResponse = await signer.sendTransaction(tx);
const txReceipt = await txResponse.wait();
notification.success({
message: "Transaction Successful",
description: (
<div>
Transaction Hash: <a href={`https://sepolia.explorer.mode.network/tx/${txReceipt.transactionHash}`} target="_blank" rel="noopener noreferrer">{txReceipt.transactionHash}</a>
</div>
)
});
};
return (
<div className="App">
<div className="logo-section">
<img src="https://i.imgur.com/EerK7MS.png" alt="Logo 1" className="logo logo-big" />
<img src="https://i.imgur.com/LL9rWVH.png" alt="Logo 2" className="logo logo-small" />
</div>
{!userInfo ? (
<div className="login-section">
<button className="sign-button google-button" onClick={() => handleLogin('google')}>
<img src="https://i.imgur.com/nIN9P4A.png" alt="Google" className="icon"/>
Sign in with Google
</button>
<button className="sign-button twitter-button" onClick={() => handleLogin('twitter')}>
<img src="https://i.imgur.com/afIaQJC.png" alt="Twitter" className="icon"/>
Sign in with X
</button>
<button className="sign-button other-button" onClick={() => handleLogin('')}>
<img src="https://i.imgur.com/VRftF1b.png" alt="Twitter" className="icon"/>
</button>
</div>
) : (
<div className="profile-card">
<h2>{userInfo.name}</h2>
<div className="balance-section">
<small>{balance} OKB</small>
<button className="sign-message-button" onClick={executeUserOp}>Execute Transaction</button>
<button className="disconnect-button" onClick={() => disconnect()}>Logout</button>
</div>
</div>
)}
</div>
);
};
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment