Deploy a delegator account
A delegator smart contract account must be deployed to the blockchain, just like any other smart contract. It can be deployed either just-in-time (when sending a user operation) or ahead of time.
The DeleGatorClient
that you use to interact with the account must be configured correctly with
isAccountDeployed
on the account
.
A delegator smart contract account is considered "counterfactual" until it is deployed. This means that you know where the account will be deployed in the future, so you can do some things you would normally do with an account (such as send tokens or NFTs) before actually deploying the account.
Prerequisites
- Install and set up the MetaMask Delegation Toolkit.
- Configure the toolkit.
- Create a delegator account.
Deploy just in time
When sending your first user operation, you can deploy the smart contract account as part of
processing the user operation.
This happens via the user operation's factory
and factoryData
fields.
The MetaMask Delegation Toolkit generates these fields automatically when you create a user
operation (as long as the DeleGatorClient
is created with isAccountDeployed
set to false
).
For example:
const client = createDeleGatorClient({
transport,
chain,
account: {
implementation: Implementation.Hybrid,
deployParams: [owner.address, [], [], []],
deploySalt,
// isAccountDeployed must be false in order for factory and factoryData to be set on the user operation.
isAccountDeployed: false,
signatory: owner,
},
});
const userOperation = await delegatorClient.createAndSignExecuteUserOp({
to,
value,
data,
});
// userOperation.factory and userOperation.factoryData are automatically set.
// todo: submit the userOperation to the bundler, and wait for inclusion.
const deployedClient = client.toDeployedClient();
See Send a user operation to learn how to submit the user operation to a bundler.
You can deploy the account ahead of time, using this mechanism, by sending a "no action" user operation:
const action = createAction(zeroAddress);
const deployAccountUserOperation = await delegatorClient.createAndSignExecuteUserOp(action);
Deploy ahead of time
You can deploy a delegator smart contract account directly using a traditional transaction (or a
user operation from a different smart contract account).
To do so, get the factoryData
from the DeleGatorClient
and submit a transaction that will
execute that factoryData
against the SimpleFactory
contract.
The following example assumes that a Viem Wallet Client and Public Client are correctly configured.
const client = createDeleGatorClient({
transport,
chain,
account: {
implementation: Implementation.Hybrid,
deployParams: [owner.address, [], [], []],
deploySalt,
// isAccountDeployed must be false in order for factoryData to be set on account.
isAccountDeployed: false,
signatory: owner,
},
});
const hash = await walletClient.sendTransaction({
to: client.environment.SimpleFactory
data: client.account.factoryData,
});
await publicClient.waitForTransactionReceipt({
hash
});
const deployedClient = client.toDeployedClient();
Create a DeleGatorClient
for a deployed account
Once your delegator smart contract account is deployed, you can create a DeleGatorClient
directly,
with either the deployParams
and deploySalt
or the address
of the smart contract account.
- deployParams and deploySalt
- address
const deployedClient = createDeleGatorClient({
transport,
chain,
account: {
implementation: Implementation.Hybrid,
deployParams: [owner.address, [], [], []],
deploySalt,
isAccountDeployed: true,
signatory: owner,
},
});
const deployedClient = createDeleGatorClient({
transport,
chain,
account: {
implementation: Implementation.Hybrid,
address: smartContractAddress,
isAccountDeployed: true,
signatory: owner,
},
});
Once a counterfactual account is deployed (for example, once the account's first user operation is
included in the blockchain), you must recreate the DeleGatorClient
as a "deployed" client.
You can do this using this same example, or using the counterfactualClient.toDeployedClient()
convenience function.
Check if a delegator account is deployed
In some cases, you may not be certain whether a delegator account has been deployed or not. You can check the deployment status and create a DeleGatorClient
using the following approach:
const address = getDeleGatorAddress(environment, {
implementation: Implementation.Hybrid,
deployParams: [owner.address, [], [], []],
deploySalt,
});
const isAccountDeployed = !!(await publicClient.getCode({ address }));
const client = createDeleGatorClient({
transport,
chain,
environment,
account: {
implementation: Implementation.Hybrid,
deployParams: [owner.address, [], [], []],
deploySalt,
isAccountDeployed,
},
});