-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathchat.ts
127 lines (110 loc) · 3.54 KB
/
chat.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
import {Contract, ethers, TransactionReceipt, Wallet} from "ethers";
import ABI from "./abis/ChatGpt.json";
import * as readline from 'readline';
require("dotenv").config()
interface Message {
role: string,
content: string,
}
async function main() {
const rpcUrl = process.env.RPC_URL
if (!rpcUrl) throw Error("Missing RPC_URL in .env")
const privateKey = process.env.PRIVATE_KEY
if (!privateKey) throw Error("Missing PRIVATE_KEY in .env")
const contractAddress = process.env.CHAT_CONTRACT_ADDRESS
if (!contractAddress) throw Error("Missing CHAT_CONTRACT_ADDRESS in .env")
const provider = new ethers.JsonRpcProvider(rpcUrl)
const wallet = new Wallet(
privateKey, provider
)
const contract = new Contract(contractAddress, ABI, wallet)
// The message you want to start the chat with
const message = await getUserInput()
// Call the startChat function
const transactionResponse = await contract.startChat(message)
const receipt = await transactionResponse.wait()
console.log(`Message sent, tx hash: ${receipt.hash}`)
console.log(`Chat started with message: "${message}"`)
// Get the chat ID from transaction receipt logs
let chatId = getChatId(receipt, contract);
console.log(`Created chat ID: ${chatId}`)
if (!chatId && chatId !== 0) {
return
}
let allMessages: Message[] = []
// Run the chat loop: read messages and send messages
while (true) {
const newMessages: Message[] = await getNewMessages(contract, chatId, allMessages.length);
if (newMessages) {
for (let message of newMessages) {
console.log(`${message.role}: ${message.content}`)
allMessages.push(message)
if (allMessages.at(-1)?.role == "assistant") {
const message = getUserInput()
const transactionResponse = await contract.addMessage(message, chatId)
const receipt = await transactionResponse.wait()
console.log(`Message sent, tx hash: ${receipt.hash}`)
}
}
}
await new Promise(resolve => setTimeout(resolve, 2000))
}
}
async function getUserInput(): Promise<string | undefined> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
const question = (query: string): Promise<string> => {
return new Promise((resolve) => {
rl.question(query, (answer) => {
resolve(answer)
})
})
}
try {
const input = await question("Message ChatGPT: ")
rl.close()
return input
} catch (err) {
console.error('Error getting user input:', err)
rl.close()
}
}
function getChatId(receipt: TransactionReceipt, contract: Contract) {
let chatId
for (const log of receipt.logs) {
try {
const parsedLog = contract.interface.parseLog(log)
if (parsedLog && parsedLog.name === "ChatCreated") {
// Second event argument
chatId = ethers.toNumber(parsedLog.args[1])
}
} catch (error) {
// This log might not have been from your contract, or it might be an anonymous log
console.log("Could not parse log:", log)
}
}
return chatId;
}
async function getNewMessages(
contract: Contract,
chatId: number,
currentMessagesCount: number
): Promise<Message[]> {
const messages = await contract.getMessageHistory(chatId)
const newMessages: Message[] = []
messages.forEach((message: any, i: number) => {
if (i >= currentMessagesCount) {
newMessages.push(
{
role: message[0],
content: message.content[0].value,
}
);
}
})
return newMessages;
}
main()
.then(() => console.log("Done"))