Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: smart sessions migration
Browse files Browse the repository at this point in the history
joepegler committed Dec 31, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 3fe6115 commit 82e726a
Showing 7 changed files with 230 additions and 133 deletions.
21 changes: 20 additions & 1 deletion src/sdk/account/toNexusAccount.test.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,8 @@ import {
parseAbiParameters,
parseEther,
toBytes,
toHex
toHex,
encodeFunctionData
} from "viem"
import type { UserOperation } from "viem/account-abstraction"
import { afterAll, beforeAll, describe, expect, test } from "vitest"
@@ -60,6 +61,7 @@ import {
eip1271MagicValue
} from "./utils/Constants"
import type { BytesLike } from "./utils/Types"
import { CounterAbi } from "../../test/__contracts/abi/CounterAbi"

describe("nexus.account", async () => {
let network: NetworkConfig
@@ -600,4 +602,21 @@ describe("nexus.account", async () => {
expect(BICONOMY_ATTESTER_ADDRESS).toBe(biconomyAttesterAddress)
}
)

testnetTest(
"should debug user operation and generate tenderly link",
async ({ config: { chain } }) => {
await nexusClient.debugUserOperation({
calls: [
{
to: testAddresses.Counter,
data: encodeFunctionData({
abi: CounterAbi,
functionName: "incrementNumber"
})
}
]
})
}
)
})
41 changes: 41 additions & 0 deletions src/sdk/account/utils/Utils.ts
Original file line number Diff line number Diff line change
@@ -433,3 +433,44 @@ export const getAllowance = async (

return approval as bigint
}

export function parseRequestArguments(input: string[]) {
const fieldsToOmit = [
"callGasLimit",
"preVerificationGas",
"maxFeePerGas",
"maxPriorityFeePerGas",
"paymasterAndData",
"verificationGasLimit"
]

// Skip the first element which is just "Request Arguments:"
const argsString = input.slice(1).join("")

// Split by newlines and filter out empty lines
const lines = argsString.split("\n").filter((line) => line.trim())

// Create an object from the key-value pairs
const result = lines.reduce(
(acc, line) => {
// Remove extra spaces and split by ':'
const [key, value] = line.split(":").map((s) => s.trim())

// Clean up the key (remove trailing spaces and colons)
const cleanKey = key.trim()

// Clean up the value (remove 'gwei' and other units)
const cleanValue: string | number = value.replace("gwei", "").trim()

if (fieldsToOmit.includes(cleanKey)) {
return acc
}

acc[cleanKey] = cleanValue
return acc
},
{} as Record<string, string | number>
)

return result
}
29 changes: 29 additions & 0 deletions src/sdk/account/utils/contractSimulation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { http, type Address, createPublicClient, parseEther } from "viem"
import { ENTRY_POINT_ADDRESS, EntrypointAbi } from "../../constants"
import { getChain } from "./getChain"
import { getSimulationUserOp } from "./tenderlySimulation"
import type { AnyUserOperation } from "./tenderlySimulation"

export async function contractSimulation(
partialUserOp: AnyUserOperation,
chainId: number
) {
const packed = getSimulationUserOp(partialUserOp)

return createPublicClient({
chain: getChain(chainId),
transport: http()
}).simulateContract({
account: partialUserOp.sender as Address,
address: ENTRY_POINT_ADDRESS,
abi: EntrypointAbi,
functionName: "handleOps",
args: [[packed], packed.sender],
stateOverride: [
{
address: partialUserOp.sender as Address,
balance: parseEther("1000")
}
]
})
}
66 changes: 66 additions & 0 deletions src/sdk/account/utils/tenderlySimulation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { RpcUserOperation } from "viem"
import {
type UserOperation,
toPackedUserOperation
} from "viem/account-abstraction"
import { getTenderlyDetails } from "."
import { ENTRY_POINT_ADDRESS } from "../../constants"
import { deepHexlify } from "./deepHexlify"

export type AnyUserOperation = Partial<UserOperation<"0.7"> | RpcUserOperation>

export const getSimulationUserOp = (partialUserOp: AnyUserOperation) => {
const simulationGasLimits = {
callGasLimit: 100_000_000_000n,
verificationGasLimit: 100_000_000_000n,
preVerificationGas: 1n,
maxFeePerGas: 100_000_000_000n,
maxPriorityFeePerGas: 1n,
paymasterVerificationGasLimit: 100_000_000_000n,
paymasterPostOpGasLimit: 100_000n
}

const mergedUserOp = deepHexlify({
...simulationGasLimits,
...partialUserOp
})

return toPackedUserOperation(mergedUserOp)
}

export function tenderlySimulation(
partialUserOp: AnyUserOperation,
chainId = 84532
) {
const tenderlyDetails = getTenderlyDetails()

if (!tenderlyDetails) {
console.log(
"Tenderly details not found in environment variables. Please set TENDERLY_API_KEY, TENDERLY_ACCOUNT_SLUG, and TENDERLY_PROJECT_SLUG."
)
return null
}

const tenderlyUrl = new URL(
`https://dashboard.tenderly.co/${tenderlyDetails.accountSlug}/${tenderlyDetails.projectSlug}/simulator/new`
)

const packedUserOp = getSimulationUserOp(partialUserOp)

const params = new URLSearchParams({
contractAddress: ENTRY_POINT_ADDRESS,
value: "0",
network: chainId.toString(),
contractFunction: "0x765e827f", // handleOps
functionInputs: JSON.stringify([packedUserOp]),
stateOverrides: JSON.stringify([
{
contractAddress: packedUserOp.sender,
balance: "100000000000000000000"
}
])
})

tenderlyUrl.search = params.toString()
return tenderlyUrl.toString()
}
Loading

0 comments on commit 82e726a

Please sign in to comment.