SessionKeyValidator SDK examples
ERC20-Transfer with SessionKey Signature
import { BigNumber, ethers } from 'ethers';
import { EtherspotBundler, ModularSdk, SessionKeyValidator, sleep, ERC20_ABI, printOp } from '@etherspot/modular-sdk';
import * as dotenv from 'dotenv';
dotenv.config();
async function main() {
// add/change these values
const recipient = '0xdE79F0eF8A1268DAd0Df02a8e527819A3Cd99d40'; // recipient wallet address
const value = '1'; // transfer value
const tokenAddress = ''; // token address
const decimals = 18;
const erc20SessionKeyValidator = '0x22A55192a663591586241D42E603221eac49ed09';
const bundlerApiKey = process.env.API_KEY as string;
const walletPrivateKey = process.env.WALLET_PRIVATE_KEY as string;
const chainId = Number(process.env.CHAIN_ID);
// initializating sdk...
const modularSdk = new ModularSdk({ privateKey: privateKey },
{
chainId: chainId,
bundlerProvider: new EtherspotBundler(chainId, bundlerApiKey)
})
const sessionKeyModule = await SessionKeyValidator.create(
modularSdk,
new EtherspotBundler(chainId, bundlerApiKey)
);
console.log(`sessionKey SDK initialized`);
// get address of EtherspotWallet...
const address: string = await modularSdk.getCounterFactualAddress();
console.log('\x1b[33m%s\x1b[0m', `EtherspotWallet address: ${address}`);
const provider = new ethers.providers.JsonRpcProvider(process.env.BUNDLER_URL)
// get erc20 Contract Interface
const erc20Instance = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
// get transferFrom encoded data
const transactionData = erc20Instance.interface.encodeFunctionData('transfer',
[recipient, ethers.utils.parseUnits(value, decimals)])
// clear the transaction batch
await modularSdk.clearUserOpsFromBatch();
// add transactions to the batch
const userOpsBatch = await modularSdk.addUserOpsToBatch({
to: tokenAddress, data: transactionData });
console.log('transactions: ', userOpsBatch);
console.log(`erc20SessionKeyValidator ${erc20SessionKeyValidator} as BigNumber is: ${BigNumber.from(erc20SessionKeyValidator)}`);
// estimate transactions added to the batch and get the fee data for the UserOp
const op = await modularSdk.estimate({
key: BigNumber.from(erc20SessionKeyValidator)
});
const nonceBig = BigNumber.from(op.nonce);
console.log(`Nonce: ${nonceBig}`);
console.log(`Estimate UserOp: ${await printOp(op)}`);
// sign the UserOp using sessionKey
const sessionKey = '';
const signedUserOp = await sessionKeyModule.signUserOpWithSessionKey(sessionKey, op);
console.log(`etherspot-modular-sdk -> Signed UserOp: ${signedUserOp.signature}`);
console.log(`Signed UserOp: ${await printOp(signedUserOp)}`);
console.log(`UserOpNonce is: ${BigNumber.from(signedUserOp.nonce)}`);
const userOpHashFromSignedUserOp = await modularSdk.getUserOpHash(signedUserOp);
console.log(`UserOpHash from Signed UserOp: ${userOpHashFromSignedUserOp}`);
// sending to the bundler with isUserOpAlreadySigned true...
const uoHash = await modularSdk.send(signedUserOp, true);
console.log(`UserOpHash: ${uoHash}`);
// get transaction hash...
console.log('Waiting for transaction...');
let userOpsReceipt = null;
const timeout = Date.now() + 60000; // 1 minute timeout
while ((userOpsReceipt == null) && (Date.now() < timeout)) {
await sleep(2);
userOpsReceipt = await modularSdk.getUserOpReceipt(uoHash);
}
console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt);
}