Diff
checker
Text
Text
Images
Documents
Excel
Folders
Legal
Enterprise
Desktop
Pricing
Sign in
Download Diffchecker Desktop
Compare text
Find the difference between two text files
Tools
History
Real-time editor
Hide unchanged lines
Disable line wrap
Layout
Split
Unified
Diff precision
Smart
Word
Char
Syntax highlighting
Choose syntax
Ignore
Transform text
Go to first change
Edit input
Diffchecker Desktop
The most secure way to run Diffchecker. Get the Diffchecker Desktop app: your diffs never leave your computer!
Get Desktop
diff
Created
2 years ago
Diff never expires
Clear
Export
Share
Explain
18 removals
Lines
Total
Removed
Characters
Total
Removed
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
146 lines
Copy
25 additions
Lines
Total
Added
Characters
Total
Added
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
153 lines
Copy
import "dotenv/config"
import "dotenv/config"
import {
import {
createKernelAccount,
createKernelAccount,
createZeroDevPaymasterClient,
createZeroDevPaymasterClient,
createKernelAccountClient,
createKernelAccountClient,
Copy
Copied
Copy
Copied
addressToEmptyAccount,
} from "@zerodev/sdk"
} from "@zerodev/sdk"
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator"
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator"
import {
import {
signerToSessionKeyValidator,
signerToSessionKeyValidator,
ParamOperator,
ParamOperator,
serializeSessionKeyAccount,
serializeSessionKeyAccount,
deserializeSessionKeyAccount,
deserializeSessionKeyAccount,
oneAddress,
oneAddress,
} from "@zerodev/session-key"
} from "@zerodev/session-key"
import { UserOperation } from "permissionless"
import { UserOperation } from "permissionless"
import {
import {
http,
http,
Hex,
Hex,
createPublicClient,
createPublicClient,
parseAbi,
parseAbi,
encodeFunctionData,
encodeFunctionData,
Copy
Copied
Copy
Copied
Address,
} from "viem"
} from "viem"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
import { polygonMumbai } from "viem/chains"
import { polygonMumbai } from "viem/chains"
if (
if (
!process.env.BUNDLER_RPC ||
!process.env.BUNDLER_RPC ||
!process.env.PAYMASTER_RPC ||
!process.env.PAYMASTER_RPC ||
!process.env.PRIVATE_KEY
!process.env.PRIVATE_KEY
) {
) {
throw new Error("BUNDLER_RPC or PAYMASTER_RPC or PRIVATE_KEY is not set")
throw new Error("BUNDLER_RPC or PAYMASTER_RPC or PRIVATE_KEY is not set")
}
}
const publicClient = createPublicClient({
const publicClient = createPublicClient({
Copy
Copied
Copy
Copied
chain: polygonMumbai,
transport: http(process.env.BUNDLER_RPC),
transport: http(process.env.BUNDLER_RPC),
})
})
const signer = privateKeyToAccount(process.env.PRIVATE_KEY as Hex)
const signer = privateKeyToAccount(process.env.PRIVATE_KEY as Hex)
const contractAddress = "0x34bE7f35132E97915633BC1fc020364EA5134863"
const contractAddress = "0x34bE7f35132E97915633BC1fc020364EA5134863"
const contractABI = parseAbi([
const contractABI = parseAbi([
"function mint(address _to) public",
"function mint(address _to) public",
"function balanceOf(address owner) external view returns (uint256 balance)",
"function balanceOf(address owner) external view returns (uint256 balance)",
])
])
Copy
Copied
Copy
Copied
const sessionPrivateKey = generatePrivateKey()
const sessionKeySigner = privateKeyToAccount(sessionPrivateKey)
const createSessionKey = async () => {
Copy
Copied
Copy
Copied
const createSessionKey = async (sessionKeyAddress: Address) => {
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
signer,
signer,
})
})
const masterAccount = await createKernelAccount(publicClient, {
const masterAccount = await createKernelAccount(publicClient, {
plugins: {
plugins: {
sudo: ecdsaValidator,
sudo: ecdsaValidator,
},
},
})
})
console.log("Account address:", masterAccount.address)
console.log("Account address:", masterAccount.address)
Copy
Copied
Copy
Copied
// Create an "empty account" as the signer -- you only need the public
// key (address) to do this.
const emptySessionKeySigner = addressToEmptyAccount(sessionKeyAddress)
const sessionKeyValidator = await signerToSessionKeyValidator(publicClient, {
const sessionKeyValidator = await signerToSessionKeyValidator(publicClient, {
Copy
Copied
Copy
Copied
signer:
s
essionKeySigner,
signer:
emptyS
essionKeySigner,
validatorData: {
validatorData: {
paymaster: oneAddress,
paymaster: oneAddress,
permissions: [
permissions: [
{
{
target: contractAddress,
target: contractAddress,
// Maximum value that can be transferred. In this case we
// Maximum value that can be transferred. In this case we
// set it to zero so that no value transfer is possible.
// set it to zero so that no value transfer is possible.
valueLimit: BigInt(0),
valueLimit: BigInt(0),
// Contract abi
// Contract abi
abi: contractABI,
abi: contractABI,
// Function name
// Function name
functionName: "mint",
functionName: "mint",
// An array of conditions, each corresponding to an argument for
// An array of conditions, each corresponding to an argument for
// the function.
// the function.
args: [
args: [
{
{
// In this case, we are saying that the session key can only mint
// In this case, we are saying that the session key can only mint
// NFTs to the account itself
// NFTs to the account itself
operator: ParamOperator.EQUAL,
operator: ParamOperator.EQUAL,
value: masterAccount.address,
value: masterAccount.address,
},
},
],
],
},
},
],
],
},
},
})
})
const sessionKeyAccount = await createKernelAccount(publicClient, {
const sessionKeyAccount = await createKernelAccount(publicClient, {
plugins: {
plugins: {
sudo: ecdsaValidator,
sudo: ecdsaValidator,
regular: sessionKeyValidator,
regular: sessionKeyValidator,
},
},
})
})
Copy
Copied
Copy
Copied
// Include the private key when you serialize the session key
return await serializeSessionKeyAccount(sessionKeyAccount
)
return await serializeSessionKeyAccount(sessionKeyAccount
, sessionPrivateKey
)
}
}
Copy
Copied
Copy
Copied
const useSessionKey = async (serializedSessionKey: string
) => {
const useSessionKey = async (serializedSessionKey: string
, sessionKeySigner: any
) => {
const sessionKeyAccount = await deserializeSessionKeyAccount(publicClient, serializedSessionKey
)
const sessionKeyAccount = await deserializeSessionKeyAccount(publicClient, serializedSessionKey
, sessionKeySigner
)
const kernelClient = createKernelAccountClient({
const kernelClient = createKernelAccountClient({
account: sessionKeyAccount,
account: sessionKeyAccount,
chain: polygonMumbai,
chain: polygonMumbai,
transport: http(process.env.BUNDLER_RPC),
transport: http(process.env.BUNDLER_RPC),
sponsorUserOperation: async ({ userOperation }): Promise<UserOperation> => {
sponsorUserOperation: async ({ userOperation }): Promise<UserOperation> => {
const kernelPaymaster = createZeroDevPaymasterClient({
const kernelPaymaster = createZeroDevPaymasterClient({
chain: polygonMumbai,
chain: polygonMumbai,
transport: http(process.env.PAYMASTER_RPC),
transport: http(process.env.PAYMASTER_RPC),
})
})
return kernelPaymaster.sponsorUserOperation({
return kernelPaymaster.sponsorUserOperation({
userOperation,
userOperation,
})
})
},
},
})
})
const userOpHash = await kernelClient.sendUserOperation({
const userOpHash = await kernelClient.sendUserOperation({
userOperation: {
userOperation: {
callData: await sessionKeyAccount.encodeCallData({
callData: await sessionKeyAccount.encodeCallData({
to: contractAddress,
to: contractAddress,
value: BigInt(0),
value: BigInt(0),
data: encodeFunctionData({
data: encodeFunctionData({
abi: contractABI,
abi: contractABI,
functionName: "mint",
functionName: "mint",
args: [sessionKeyAccount.address],
args: [sessionKeyAccount.address],
}),
}),
}),
}),
},
},
})
})
console.log("userOp hash:", userOpHash)
console.log("userOp hash:", userOpHash)
}
}
const main = async () => {
const main = async () => {
Copy
Copied
Copy
Copied
// The
owner
creates a
session
key
, serializes it,
and
shares it with
the
agent
.
// The
agent
creates a
public-private
key
pair
and
sends
const
serializedSessionKey = await createSessionKey()
// the public key (address) to
the
owner
.
const
sessionPrivateKey = generatePrivateKey()
const sessionKeySigner = privateKeyToAccount(sessionPrivateKey)
Copy
Copied
Copy
Copied
// The agent
re
constructs
the
session key
using the serialized value
// The owner authorizes the public key by signing it and sending
await useSessionKey(serializedSessionKey
)
// back the signature
const serializedSessionKey = await createSessionKey(sessionKeySigner.address)
// The agent
constructs
a full
session key
await useSessionKey(serializedSessionKey
, sessionKeySigner
)
}
}
main()
main()
Saved diffs
Original text
Open file
import "dotenv/config" import { createKernelAccount, createZeroDevPaymasterClient, createKernelAccountClient, } from "@zerodev/sdk" import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator" import { signerToSessionKeyValidator, ParamOperator, serializeSessionKeyAccount, deserializeSessionKeyAccount, oneAddress, } from "@zerodev/session-key" import { UserOperation } from "permissionless" import { http, Hex, createPublicClient, parseAbi, encodeFunctionData, } from "viem" import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" import { polygonMumbai } from "viem/chains" if ( !process.env.BUNDLER_RPC || !process.env.PAYMASTER_RPC || !process.env.PRIVATE_KEY ) { throw new Error("BUNDLER_RPC or PAYMASTER_RPC or PRIVATE_KEY is not set") } const publicClient = createPublicClient({ chain: polygonMumbai, transport: http(process.env.BUNDLER_RPC), }) const signer = privateKeyToAccount(process.env.PRIVATE_KEY as Hex) const contractAddress = "0x34bE7f35132E97915633BC1fc020364EA5134863" const contractABI = parseAbi([ "function mint(address _to) public", "function balanceOf(address owner) external view returns (uint256 balance)", ]) const sessionPrivateKey = generatePrivateKey() const sessionKeySigner = privateKeyToAccount(sessionPrivateKey) const createSessionKey = async () => { const ecdsaValidator = await signerToEcdsaValidator(publicClient, { signer, }) const masterAccount = await createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator, }, }) console.log("Account address:", masterAccount.address) const sessionKeyValidator = await signerToSessionKeyValidator(publicClient, { signer: sessionKeySigner, validatorData: { paymaster: oneAddress, permissions: [ { target: contractAddress, // Maximum value that can be transferred. In this case we // set it to zero so that no value transfer is possible. valueLimit: BigInt(0), // Contract abi abi: contractABI, // Function name functionName: "mint", // An array of conditions, each corresponding to an argument for // the function. args: [ { // In this case, we are saying that the session key can only mint // NFTs to the account itself operator: ParamOperator.EQUAL, value: masterAccount.address, }, ], }, ], }, }) const sessionKeyAccount = await createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator, regular: sessionKeyValidator, }, }) // Include the private key when you serialize the session key return await serializeSessionKeyAccount(sessionKeyAccount, sessionPrivateKey) } const useSessionKey = async (serializedSessionKey: string) => { const sessionKeyAccount = await deserializeSessionKeyAccount(publicClient, serializedSessionKey) const kernelClient = createKernelAccountClient({ account: sessionKeyAccount, chain: polygonMumbai, transport: http(process.env.BUNDLER_RPC), sponsorUserOperation: async ({ userOperation }): Promise<UserOperation> => { const kernelPaymaster = createZeroDevPaymasterClient({ chain: polygonMumbai, transport: http(process.env.PAYMASTER_RPC), }) return kernelPaymaster.sponsorUserOperation({ userOperation, }) }, }) const userOpHash = await kernelClient.sendUserOperation({ userOperation: { callData: await sessionKeyAccount.encodeCallData({ to: contractAddress, value: BigInt(0), data: encodeFunctionData({ abi: contractABI, functionName: "mint", args: [sessionKeyAccount.address], }), }), }, }) console.log("userOp hash:", userOpHash) } const main = async () => { // The owner creates a session key, serializes it, and shares it with the agent. const serializedSessionKey = await createSessionKey() // The agent reconstructs the session key using the serialized value await useSessionKey(serializedSessionKey) } main()
Changed text
Open file
import "dotenv/config" import { createKernelAccount, createZeroDevPaymasterClient, createKernelAccountClient, addressToEmptyAccount, } from "@zerodev/sdk" import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator" import { signerToSessionKeyValidator, ParamOperator, serializeSessionKeyAccount, deserializeSessionKeyAccount, oneAddress, } from "@zerodev/session-key" import { UserOperation } from "permissionless" import { http, Hex, createPublicClient, parseAbi, encodeFunctionData, Address, } from "viem" import { generatePrivateKey, privateKeyToAccount } from "viem/accounts" import { polygonMumbai } from "viem/chains" if ( !process.env.BUNDLER_RPC || !process.env.PAYMASTER_RPC || !process.env.PRIVATE_KEY ) { throw new Error("BUNDLER_RPC or PAYMASTER_RPC or PRIVATE_KEY is not set") } const publicClient = createPublicClient({ transport: http(process.env.BUNDLER_RPC), }) const signer = privateKeyToAccount(process.env.PRIVATE_KEY as Hex) const contractAddress = "0x34bE7f35132E97915633BC1fc020364EA5134863" const contractABI = parseAbi([ "function mint(address _to) public", "function balanceOf(address owner) external view returns (uint256 balance)", ]) const createSessionKey = async (sessionKeyAddress: Address) => { const ecdsaValidator = await signerToEcdsaValidator(publicClient, { signer, }) const masterAccount = await createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator, }, }) console.log("Account address:", masterAccount.address) // Create an "empty account" as the signer -- you only need the public // key (address) to do this. const emptySessionKeySigner = addressToEmptyAccount(sessionKeyAddress) const sessionKeyValidator = await signerToSessionKeyValidator(publicClient, { signer: emptySessionKeySigner, validatorData: { paymaster: oneAddress, permissions: [ { target: contractAddress, // Maximum value that can be transferred. In this case we // set it to zero so that no value transfer is possible. valueLimit: BigInt(0), // Contract abi abi: contractABI, // Function name functionName: "mint", // An array of conditions, each corresponding to an argument for // the function. args: [ { // In this case, we are saying that the session key can only mint // NFTs to the account itself operator: ParamOperator.EQUAL, value: masterAccount.address, }, ], }, ], }, }) const sessionKeyAccount = await createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator, regular: sessionKeyValidator, }, }) return await serializeSessionKeyAccount(sessionKeyAccount) } const useSessionKey = async (serializedSessionKey: string, sessionKeySigner: any) => { const sessionKeyAccount = await deserializeSessionKeyAccount(publicClient, serializedSessionKey, sessionKeySigner) const kernelClient = createKernelAccountClient({ account: sessionKeyAccount, chain: polygonMumbai, transport: http(process.env.BUNDLER_RPC), sponsorUserOperation: async ({ userOperation }): Promise<UserOperation> => { const kernelPaymaster = createZeroDevPaymasterClient({ chain: polygonMumbai, transport: http(process.env.PAYMASTER_RPC), }) return kernelPaymaster.sponsorUserOperation({ userOperation, }) }, }) const userOpHash = await kernelClient.sendUserOperation({ userOperation: { callData: await sessionKeyAccount.encodeCallData({ to: contractAddress, value: BigInt(0), data: encodeFunctionData({ abi: contractABI, functionName: "mint", args: [sessionKeyAccount.address], }), }), }, }) console.log("userOp hash:", userOpHash) } const main = async () => { // The agent creates a public-private key pair and sends // the public key (address) to the owner. const sessionPrivateKey = generatePrivateKey() const sessionKeySigner = privateKeyToAccount(sessionPrivateKey) // The owner authorizes the public key by signing it and sending // back the signature const serializedSessionKey = await createSessionKey(sessionKeySigner.address) // The agent constructs a full session key await useSessionKey(serializedSessionKey, sessionKeySigner) } main()
Find difference