Particle AA SDK
Installation
Install and import the biconomy package from the Particle Network SDK
yarn add @particle-network/aa
//or
npm install @particle-network/aa
Initialize the SmartAccount
You need to create a Particle project to connect to your app, Visit Particle Dashboard.
The provider is EIP-1193: Ethereum Provider JavaScript API , you can use Particle Provider, MetaMask Provider or any EVM wallet provider.
import { SmartAccount } from '@particle-network/aa';
const smartAccount = new SmartAccount(provider, {
projectId: 'particle project id',
clientKey: 'particle client key',
appId: 'particle app id',
aaOptions: {
accountContracts: {
BICONOMY: [
{
version: '1.0.0',
chainIds: [x, xx],
},
{
version: '2.0.0'
}
],
CYBERCONNECT: [
{
version: '1.0.0'
}
],
SIMPLE: [
{
version: '1.0.0'
}
],
},
},
});
smartAccount.setSmartAccountContract({ name: 'BICONOMY', version: '2.0.0' });
Get Smart Account Address
Once you have connected your EOA signer and created an instance of Smart Account, the address is the public property and remains the same across all EVM chains.
const address = await smartAccount.getAddress();
const address = await smartAccount.getOwner();
const accountInfo = await smartAccount.getAccount();
Get Fee Quotes
Before send transactions, you can get fee quotes and display on UI Modal, users can choose which token to use to pay gas fees.
const tx = {
to: '0x...',
value: '0x...'
}
const txs = [
{
to: '0x...',
value: '0x...'
},
{
to: '0x...',
value: '0x...'
}
]
const feeQuotesResult = await smartAccount.getFeeQuotes(tx);
const gaslessUserOp = feeQuotesResult.verifyingPaymasterGasless?.userOp;
const gaslessUserOpHash = feeQuotesResult.verifyingPaymasterGasless?.userOpHash;
const paidNativeUserOp = feeQuotesResult.verifyingPaymasterNative?.userOp;
const paidNativeUserOpHash = feeQuotesResult.verifyingPaymasterNative?.userOpHash;
const tokenPaymasterAddress = feeQuotesResult.tokenPaymaster.tokenPaymasterAddress;
const tokenFeeQuotes = feeQuotesResult.tokenPaymaster.feeQuotes;
</code></pre>
Build User Operation
Builds a UserOp
object from the provided array of Transaction
s. It also accepts optional feeQuote
and tokenPaymasterAddress
. Returns a Promise that resolves to the UserOpBundle
.
const userOpBundle = await smartAccount.buildUserOperation({ tx, feeQuote, tokenPaymasterAddress })
const userOp = userOpBundle.userOp;
const userOpHash = userOpBundle.userOpHash;
Send User Operation
Sends the pre-signed UserOperation
to the Particle network for execution. Returns a Promise that resolves to a TransactionHash
.
const txHash = await smartAccount.sendUserOperation({ userOp, userOpHash });
Wallet Deployment flow
Any gasless or user paid transaction will check whether the wallet is deployed or not. If the wallet is not deployed, the SDK will batch the wallet deployment with the intended transaction/batch transactions. This behaviour is handled within the SDK itself & would require no changes in your code to enable this.
Deploy Wallet Contract Manual
const isDeploy = await smartAccount.isDeployed();
if (!isDeploy) {
const txHash = await smartAccount.deployWalletContract();
}
Wrap Provider
If your app has implemented sending transactions, or use web3.js, you can wrap the EIP-1193 provider to quickly implement AA wallet.
import { AAWrapProvider, SendTransactionMode, SendTransactionEvent } from '@particle-network/aa';
import Web3 from "web3";
const wrapProvider = new AAWrapProvider(smartAccount, SendTransactionMode.UserPaidNative);
const web3 = new Web3(wrapProvider);
await web3.eth.sendTransaction(tx);
const wrapProvider = new AAWrapProvider(smartAccount, SendTransactionMode.Gasless);
const web3 = new Web3(wrapProvider);
await web3.eth.sendTransaction(tx);
const wrapProvider = new AAWrapProvider(smartAccount, SendTransactionMode.UserSelect);
const web3 = new Web3(wrapProvider);
wrapProvider.once(SendTransactionEvent.Request, (feeQuotesResult) => {
wrapProvider.resolveSendTransaction({
feeQuote: feeQuotesResult.tokenPaymaster.feeQuote[0],
tokenPaymasterAddress: feeQuotesResult.tokenPaymaster.tokenPaymasterAddress
});
wrapProvider.resolveSendTransaction(feeQuotesResult.verifyingPaymasterNative);
if (feeQuotesResult.verifyingPaymasterGasless) {
wrapProvider.resolveSendTransaction(feeQuotesResult.verifyingPaymasterGasless);
}
wrapProvider.rejectSendTransaction({ message: 'user rejected'});
});
await web3.eth.sendTransaction(tx);
Learn More