-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathagent-created.ts
118 lines (101 loc) · 3.35 KB
/
agent-created.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Simplified example from zerodev: https://github.com/zerodevapp/zerodev-examples/blob/main/session-keys/v2/agent-created.ts
require("dotenv").config();
require("dotenv").config({ path: `.env.local`, override: true });
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator";
import {
addressToEmptyAccount,
createKernelAccount,
createKernelAccountClient,
} from "@zerodev/sdk";
import {
deserializeSessionKeyAccount,
serializeSessionKeyAccount,
signerToSessionKeyValidator,
} from "@zerodev/session-key";
import { ENTRYPOINT_ADDRESS_V06 } from "permissionless";
import { Address, Hex, createPublicClient, http, pad } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
if (
!process.env.BUNDLER_RPC ||
!process.env.PRIVATE_KEY ||
!process.env.RECIPIENT_ADDRESS
) {
throw new Error("BUNDLER_RPC or PRIVATE_KEY or RECIPIENT_ADDRESS is not set");
}
const publicClient = createPublicClient({
transport: http(process.env.BUNDLER_RPC),
});
const signer = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const entryPoint = ENTRYPOINT_ADDRESS_V06;
const createSessionKey = async (sessionKeyAddress: Address) => {
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
entryPoint,
signer,
});
const masterAccount = await createKernelAccount(publicClient, {
entryPoint,
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, {
entryPoint,
signer: emptySessionKeySigner,
validatorData: {
permissions: [
{
target: process.env.RECIPIENT_ADDRESS as Hex,
valueLimit: BigInt(100),
},
],
},
});
const sessionKeyAccount = await createKernelAccount(publicClient, {
entryPoint,
plugins: {
sudo: ecdsaValidator,
regular: sessionKeyValidator,
},
});
return await serializeSessionKeyAccount(sessionKeyAccount);
};
const useSessionKey = async (
serializedSessionKey: string,
sessionKeySigner: any
) => {
const sessionKeyAccount = await deserializeSessionKeyAccount(
publicClient,
entryPoint,
serializedSessionKey,
sessionKeySigner
);
const kernelClient = createKernelAccountClient({
entryPoint,
account: sessionKeyAccount,
chain: sepolia,
bundlerTransport: http(process.env.BUNDLER_RPC),
});
const userOpHash = await kernelClient.sendTransaction({
to: process.env.RECIPIENT_ADDRESS as Hex,
data: pad("0x", { size: 4 }),
value: BigInt(1),
});
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();