-
Notifications
You must be signed in to change notification settings - Fork 1
/
respondToTask.ts
133 lines (111 loc) · 3.45 KB
/
respondToTask.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { createPublicClient, createWalletClient, http, parseAbi, encodePacked, keccak256, parseAbiItem, AbiEvent } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { anvil } from 'viem/chains';
import ollama from 'ollama';
import 'dotenv/config';
if (!process.env.OPERATOR_PRIVATE_KEY) {
throw new Error('OPERATOR_PRIVATE_KEY not found in environment variables');
}
type Task = {
contents: string;
taskCreatedBlock: number;
};
const abi = parseAbi([
'function respondToTask((string contents, uint32 taskCreatedBlock) task, uint32 referenceTaskIndex, bool isSafe, bytes memory signature) external',
'event NewTaskCreated(uint32 indexed taskIndex, (string contents, uint32 taskCreatedBlock) task)'
]);
async function createSignature(account: any, isSafe: boolean, contents: string) {
// Recreate the same message hash that the contract uses
const messageHash = keccak256(
encodePacked(
['bool', 'string'],
[isSafe, contents]
)
);
// Sign the message hash
const signature = await account.signMessage({
message: { raw: messageHash }
});
return signature;
}
async function respondToTask(
walletClient: any,
publicClient: any,
contractAddress: string,
account: any,
task: Task,
taskIndex: number
) {
try {
const response = await ollama.chat({
model: 'llama-guard3:1b',
messages: [{ role: 'user', 'content': task.contents }]
})
let isSafe = true;
if (response.message.content.includes('unsafe')) {
isSafe = false
}
const signature = await createSignature(account, isSafe, task.contents);
const { request } = await publicClient.simulateContract({
address: contractAddress,
abi,
functionName: 'respondToTask',
args: [task, taskIndex, isSafe, signature],
account: account.address,
});
const hash = await walletClient.writeContract(request);
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log('Responded to task:', {
taskIndex,
task,
isSafe,
transactionHash: hash
});
} catch (error) {
console.error('Error responding to task:', error);
}
}
async function main() {
const contractAddress = '0xb60971942E4528A811D24826768Bc91ad1383D21';
const account = privateKeyToAccount(process.env.OPERATOR_PRIVATE_KEY as `0x${string}`);
const publicClient = createPublicClient({
chain: anvil,
transport: http('http://localhost:8545'),
});
const walletClient = createWalletClient({
chain: anvil,
transport: http('http://localhost:8545'),
account,
});
console.log('Starting to watch for new tasks...');
publicClient.watchEvent({
address: contractAddress,
event: parseAbiItem('event NewTaskCreated(uint32 indexed taskIndex, (string contents, uint32 taskCreatedBlock) task)') as AbiEvent,
onLogs: async (logs) => {
for (const log of logs) {
const { args } = log;
if (!args) continue;
const taskIndex = Number(args.taskIndex);
const task = args.task as Task;
console.log('New task detected:', {
taskIndex,
task
});
await respondToTask(
walletClient,
publicClient,
contractAddress,
account,
task,
taskIndex
);
}
},
});
process.on('SIGINT', () => {
console.log('Stopping task watcher...');
process.exit();
});
await new Promise(() => { });
}
main().catch(console.error);