Added Rock paper scissors blink to the solana agent kit (#42)

This commit is contained in:
ARYAN
2024-12-28 01:04:01 +05:30
committed by GitHub
4 changed files with 193 additions and 0 deletions

View File

@@ -35,6 +35,7 @@ import {
getOwnedAllDomains,
resolveAllDomains,
create_gibwork_task,
rock_paper_scissor,
} from "../tools";
import {
CollectionDeployment,
@@ -337,4 +338,11 @@ export class SolanaAgentKit {
payer ? new PublicKey(payer) : undefined,
);
}
async rockPaperScissors(
amount: number,
choice: "rock" | "paper" | "scissors",
) {
return rock_paper_scissor(this, amount, choice);
}
}

View File

@@ -1229,6 +1229,56 @@ export class SolanaCreateGibworkTask extends Tool {
}
}
export class SolanaRockPaperScissorsTool extends Tool {
name = "rock_paper_scissors";
description = `Play rock paper scissors to win SEND coins.
Inputs (input is a JSON string):
choice: string, either "rock", "paper", or "scissors" (required)
amount: number, amount of SOL to play with - must be 0.1, 0.01, or 0.005 SOL (required)`;
constructor(private solanaKit: SolanaAgentKit) {
super();
}
private validateInput(input: any): void {
if (input.choice !== undefined) {
throw new Error("choice is required.");
}
if (
input.amount !== undefined &&
(typeof input.spaceKB !== "number" || input.spaceKB <= 0)
) {
throw new Error("amount must be a positive number when provided");
}
}
protected async _call(input: string): Promise<string> {
try {
const parsedInput = toJSON(input);
this.validateInput(parsedInput);
const result = await this.solanaKit.rockPaperScissors(
Number(parsedInput['"amount"']),
parsedInput['"choice"'].replace(/^"|"$/g, "") as
| "rock"
| "paper"
| "scissors",
);
return JSON.stringify({
status: "success",
message: result,
});
} catch (error: any) {
return JSON.stringify({
status: "error",
message: error.message,
code: error.code || "UNKNOWN_ERROR",
});
}
}
}
export function createSolanaTools(solanaKit: SolanaAgentKit) {
return [
new SolanaBalanceTool(solanaKit),
@@ -1263,5 +1313,6 @@ export function createSolanaTools(solanaKit: SolanaAgentKit) {
new SolanaGetMainDomain(solanaKit),
new SolanaResolveAllDomainsTool(solanaKit),
new SolanaCreateGibworkTask(solanaKit),
new SolanaRockPaperScissorsTool(solanaKit),
];
}

View File

@@ -37,3 +37,5 @@ export * from "./openbook_create_market";
export * from "./pyth_fetch_price";
export * from "./create_gibwork_task";
export * from "./rock_paper_scissor";

View File

@@ -0,0 +1,132 @@
import { sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
import { SolanaAgentKit } from "../agent";
export async function rock_paper_scissor(
agent: SolanaAgentKit,
amount: number,
choice: "rock" | "paper" | "scissors",
) {
try {
const res = await fetch(
`https://rps.sendarcade.fun/api/actions/bot?amount=${amount}&choice=${choice}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
account: agent.wallet.publicKey.toBase58(),
}),
},
);
const data = await res.json();
if (data.transaction) {
const txn = Transaction.from(Buffer.from(data.transaction, "base64"));
txn.sign(agent.wallet);
txn.recentBlockhash = (
await agent.connection.getLatestBlockhash()
).blockhash;
const sig = await sendAndConfirmTransaction(
agent.connection,
txn,
[agent.wallet],
{ commitment: "confirmed" },
);
const href = data.links?.next?.href;
return await outcome(agent, sig, href);
} else {
return "failed";
}
} catch (error: any) {
console.error(error);
throw new Error(`RPS game failed: ${error.message}`);
}
}
async function outcome(
agent: SolanaAgentKit,
sig: string,
href: string,
): Promise<string> {
try {
const res = await fetch(
"https://rps.sendarcade.fun" + href, // href = /api/actions/outcome?id=...
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
account: agent.wallet.publicKey.toBase58(),
signature: sig,
}),
},
);
const data: any = await res.json();
const title = data.title;
if (title.startsWith("You lost")) {
return title;
}
const next_href = data.links?.actions?.[0]?.href;
return title + "\n" + (await won(agent, next_href));
} catch (error: any) {
console.error(error);
throw new Error(`RPS outcome failed: ${error.message}`);
}
}
async function won(agent: SolanaAgentKit, href: string): Promise<string> {
try {
const res = await fetch(
"https://rps.sendarcade.fun" + href, // href = /api/actions/won?id=...
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
account: agent.wallet.publicKey.toBase58(),
}),
},
);
const data: any = await res.json();
if (data.transaction) {
const txn = Transaction.from(Buffer.from(data.transaction, "base64"));
txn.partialSign(agent.wallet);
await agent.connection.sendRawTransaction(txn.serialize(), {
preflightCommitment: "confirmed",
});
} else {
return "Failed to claim prize.";
}
const next_href = data.links?.next?.href;
return await postWin(agent, next_href);
} catch (error: any) {
console.error(error);
throw new Error(`RPS outcome failed: ${error.message}`);
}
}
async function postWin(agent: SolanaAgentKit, href: string): Promise<string> {
try {
const res = await fetch(
"https://rps.sendarcade.fun" + href, // href = /api/actions/postwin?id=...
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
account: agent.wallet.publicKey.toBase58(),
}),
},
);
const data: any = await res.json();
const title = data.title;
return "Prize claimed Successfully" + "\n" + title;
} catch (error: any) {
console.error(error);
throw new Error(`RPS outcome failed: ${error.message}`);
}
}