Skip to content

Commit

Permalink
Add create:account, create:backup scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
pidturkina committed Jul 13, 2024
1 parent 3b965d4 commit 2c348a3
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 61 deletions.
4 changes: 3 additions & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
"test": "forge test",
"test:lite": "FOUNDRY_PROFILE=lite forge test",
"test:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge test",
"add:module": "bun run ./test/add-module-to-account.js"
"create:account": "bun run ./test/create-smart-account.js",
"add:module": "bun run ./test/add-module-to-account.js",
"create:backup": "bun run ./test/create-backup.js"
},
"dependencies": {
"@rhinestone/modulekit": "^0.4.7"
Expand Down
75 changes: 15 additions & 60 deletions contracts/test/add-module-to-account.js
Original file line number Diff line number Diff line change
@@ -1,60 +1,11 @@
import {
ENTRYPOINT_ADDRESS_V07,
createSmartAccountClient,
} from "permissionless";
import { signerToSafeSmartAccount } from "permissionless/accounts";
import {
createPimlicoBundlerClient,
} from "permissionless/clients/pimlico";
import { createPublicClient, http, encodePacked } from "viem";
import { sepolia } from "viem/chains";
import {generatePrivateKey, privateKeyToAccount} from "viem/accounts";
import {erc7579Actions} from "permissionless/actions/erc7579.js";
import {pimlicoPaymasterActions} from "permissionless/actions/pimlico";
import {abi} from "./abi";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { abi } from "./abi";
import { createSmartWallet } from "./create-smart-account";

const apiKey = ""
const beneficiaryPK = generatePrivateKey();

const privateKey = generatePrivateKey()

export const bundlerUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`

const signer = privateKeyToAccount(privateKey);


const publicClient = createPublicClient({
transport: http("https://rpc.ankr.com/eth_sepolia"),
})

const pimlicoBundlerClient = createPimlicoBundlerClient({
transport: http(bundlerUrl),
entryPoint: ENTRYPOINT_ADDRESS_V07,
}).extend(pimlicoPaymasterActions(ENTRYPOINT_ADDRESS_V07));

const safeAccount = await signerToSafeSmartAccount(publicClient, {
signer,
safeVersion: "1.4.1",
entryPoint: ENTRYPOINT_ADDRESS_V07,
safe4337ModuleAddress: "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2",
erc7579LaunchpadAddress: "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE",
})

const smartAccountClient = createSmartAccountClient({
account: safeAccount,
entryPoint: ENTRYPOINT_ADDRESS_V07,
chain: sepolia,
bundlerTransport: http(bundlerUrl),
middleware: {
gasPrice: async () => {
return (await pimlicoBundlerClient.getUserOperationGasPrice()).fast
},
sponsorUserOperation: pimlicoBundlerClient.sponsorUserOperation

},
}).extend(erc7579Actions({ entryPoint: ENTRYPOINT_ADDRESS_V07 }))

const beneficiary = privateKeyToAccount(privateKey);
const timeout = 100; //in seconds
const timeout = 123123123;
const beneficiary = privateKeyToAccount(beneficiaryPK);

async function installModule({smartClient, beneficiaryAddress, timeout, moduleType, hook, account, bundlerClient, moduleAddress, publicClient}) {
const isInitialized = (await publicClient.readContract({
Expand All @@ -66,9 +17,7 @@ async function installModule({smartClient, beneficiaryAddress, timeout, moduleTy

const module = {
module: moduleAddress,
initData: isInitialized
? '0x'
: encodePacked(['address', 'uint48'], [beneficiaryAddress, timeout]),
initData: '0x',
deInitData: '0x',
additionalContext: '0x',
type: moduleType,
Expand All @@ -85,14 +34,20 @@ async function installModule({smartClient, beneficiaryAddress, timeout, moduleTy
const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: opHash })
}

const { smartAccountClient, safeAccount, pimlicoBundlerClient, publicClient } = createSmartWallet({
privateKey: "<PK>",
bundlerUrl: "<bundlerUrl>"
})

installModule({
smartClient: smartAccountClient,
beneficiaryAddress: beneficiary.address,
timeout,
moduleType: "validator",
moduleType: "validator", //todo: executor
hook: '0x',
account: safeAccount,
bundlerClient: pimlicoBundlerClient,
moduleAddress: "0x6A53E204b8A21dfD64516ff27484e6113640CB96",
publicClient
})
});

26 changes: 26 additions & 0 deletions contracts/test/backup-abi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const generateBackupAbiWithArgs = ({name, unlockAt, beneficiaries}) => ({
abi: [
{
name: "updateBackup",
type: "function",
stateMutability: "nonpayable",
inputs: [
{ internalType: 'string', name: 'name', type: 'string' },
{ internalType: 'uint48', name: 'unlockAt', type: 'uint48' },
{
internalType: 'struct Wingman.Beneficiary[]',
name: 'beneficiaries',
type: 'tuple[]',
components: [
{ internalType: 'address', name: 'account', type: 'address' },
{ internalType: 'uint8', name: 'percentage', type: 'uint8' },
{ internalType: 'uint256', name: 'amount', type: 'uint256' }
]
}
],
outputs: []
}
],
functionName: "updateBackup",
args: [name, unlockAt, beneficiaries]
})
72 changes: 72 additions & 0 deletions contracts/test/create-backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {parseAccount, sendUserOperation} from "permissionless";
import {generateBackupAbiWithArgs} from "./backup-abi";
import {createSmartWallet} from "./create-smart-account";

async function updateBackup({
smartClient,
accountAddress,
moduleAddress,
name,
unlockAt,
beneficiaries,
bundlerClient
}) {
const account = parseAccount(accountAddress);

const updateBackupCallData = account.encodeFunctionData(
generateBackupAbiWithArgs({name, unlockAt, beneficiaries})
);

const opHash = await smartClient.sendUserOperation({
sender: account.address,
updateBackupCallData,
to: moduleAddress
});

const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: opHash });
return receipt;
}

async function main({
name,
unlockAt,
beneficiaries
}) {
const {
smartAccountClient,
safeAccount,
pimlicoBundlerClient
} = createSmartWallet({
privateKey: "<PK>",
bundlerUrl: "<bundler url>",
});

await updateBackup({
smartClient: smartAccountClient,
accountAddress: safeAccount.address,
moduleAddress: "0xab614e4a5398bb2a2a0bf73f9c913ec7ff47d81f",
name,
unlockAt,
beneficiaries,
bundlerClient: pimlicoBundlerClient
});

console.log("Backup updated successfully!");
}

main({
name: "name",
unlockAt: 1231231233,
beneficiaries: [
{
account: "0xAddress1",
percentage: 50,
amount: BigInt(1000)
},
{
account: "0xAddress2",
percentage: 50,
amount: BigInt(1000)
}
]
})
54 changes: 54 additions & 0 deletions contracts/test/create-smart-account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
ENTRYPOINT_ADDRESS_V07,
createSmartAccountClient,
} from "permissionless";
import { signerToSafeSmartAccount } from "permissionless/accounts";
import { createPimlicoBundlerClient } from "permissionless/clients/pimlico";
import { createPublicClient, http } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { erc7579Actions } from "permissionless/actions/erc7579.js";
import { pimlicoPaymasterActions } from "permissionless/actions/pimlico";


export async function createSmartWallet({privateKey, bundlerUrl}) {
const signer = privateKeyToAccount(privateKey);


const publicClient = createPublicClient({
transport: http("https://rpc.ankr.com/eth_sepolia"),
})

const pimlicoBundlerClient = createPimlicoBundlerClient({
transport: http(bundlerUrl),
entryPoint: ENTRYPOINT_ADDRESS_V07,
}).extend(pimlicoPaymasterActions(ENTRYPOINT_ADDRESS_V07));

const safeAccount = await signerToSafeSmartAccount(publicClient, {
signer,
safeVersion: "1.4.1",
entryPoint: ENTRYPOINT_ADDRESS_V07,
safe4337ModuleAddress: "0x3Fdb5BC686e861480ef99A6E3FaAe03c0b9F32e2",
erc7579LaunchpadAddress: "0xEBe001b3D534B9B6E2500FB78E67a1A137f561CE",
})

const smartAccountClient = createSmartAccountClient({
account: safeAccount,
entryPoint: ENTRYPOINT_ADDRESS_V07,
chain: sepolia,
bundlerTransport: http(bundlerUrl),
middleware: {
gasPrice: async () => {
return (await pimlicoBundlerClient.getUserOperationGasPrice()).fast
},
sponsorUserOperation: pimlicoBundlerClient.sponsorUserOperation
},
}).extend(erc7579Actions({ entryPoint: ENTRYPOINT_ADDRESS_V07 }))

return { smartAccountClient, safeAccount, pimlicoBundlerClient, publicClient }
}

createSmartWallet({
privateKey: "0x30320097c1d7009d6d970376c792fe157a5e989f057b8908345043393a56a8a5",
bundlerUrl: "https://api.pimlico.io/v2/sepolia/rpc?apikey=04287e53-84d2-413b-bbc6-450629d7e999",
})

0 comments on commit 2c348a3

Please sign in to comment.