Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions plugins/twitterPrimusPlugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# @virtuals-protocol/game-twitter-primus-plugin

A plugin to fully verify agent activities, including actions and other behaviors that use HTTPS.

## Overview
This plugin verifies the validity of network requests and responses using the [Primus zk-tls SDK](https://docs.primuslabs.xyz/data-verification/core-sdk/overview). It generates and verifies a zkTLS proof based on the zkTLS protocol.

## Usage

Here is full code of PrimusClient.
```typescript

export class PrimusClient {
private zkTLS: PrimusCoreTLS = new PrimusCoreTLS();
async init(appId: string, appSecret: string) {
await this.zkTLS.init(appId, appSecret);
console.log('init zkTLS success')
}


generateProof = async (
endpoint: string,
method: string,
headers: Record<string, any>,
responseParsePath: string,
body?: string,
): Promise<Attestation> => {
const requestParam = body
? {
url: endpoint,
method: method,
header: headers,
body: body,
}
: {
url: endpoint,
method: method,
header: headers,
};
// console.log('requestParam:',requestParam)
const attestationParams = this.zkTLS.generateRequestParams(requestParam, [
{
keyName: "content",
parsePath: responseParsePath,
parseType: "string",
},
]);
attestationParams.setAttMode({
algorithmType: "proxytls",
});
return await this.zkTLS.startAttestation(attestationParams);
};

verifyProof = async (attestation: Attestation): Promise<boolean> => {
return this.zkTLS.verifyAttestation(attestation);
};
}
```

The core functions in `PrimusClient` are the following, which are also used in `GameFunction`.
```typescript
// Generate a zkTLS proof.
generateProof = async (
// The target endpoint of the network request.
endpoint: string,
// The HTTP method of the request, such as 'GET', 'POST', etc.
method: string,
// A record containing the headers of the request.
headers: Record<string, any>,
//A [JSONPath](https://datatracker.ietf.org/doc/rfc9535/) expression to locate the specific field in the response you want to attest.
responseParsePath: string,
// The body of the request. It should be a string.
body?: string

): Promise<any>

// Verify the proof.
verifyProof = async (attestation: any): Promise<boolean>

```

### Verify the Actions

Below is an example showcasing how to post a price from Binance to Twitter. Developers can easily adapt this process for other functions.
```typescript
//.............
executable: async (args, logger) => {
try {
//
logger("Getting btc price with zktls...");
// Get price of BTC with primus client
const btcPriceStr = await this.getLatestBTCPriceFromBinance(logger)
const priceInfo = JSON.parse(btcPriceStr.feedback)
// Post tweet with primus client
logger(`Posting tweet with price: ${priceInfo.price}`);
const rsp = await this.twitterScraper.sendTweet(priceInfo.price,logger);
return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Done,
JSON.stringify({
rsp: "Tweet posted",
attestation: rsp.attestation
})
);
} catch (e) {
console.log(e)
return new ExecutableGameFunctionResponse(
ExecutableGameFunctionStatus.Failed,
"Failed to post tweet"
);
}
}
//.........
```

## Installation

```bash
pnpm add @virtuals-protocol/game-twitter-primus-plugin
```

## Configuration

This is the configuration class, and you must provide all required parameters in it.

```
interface ITwitterPrimusPluginOptions {
// Parameter for worker
id: string;
name: string;
description: string;

// Parameter for PrimusClient
appId: string;
appSecret: string;

// Parameter for twitter client
username: string;
password: string;
email: string;
twitter2faSecret: string;
}
```

***How to get appId and appSecret?***

1. Visit the [Primus Developer Hub](https://dev.primuslabs.xyz/).
2. Create a new `Backend` project
3. Save your 'Application ID(appId)' and 'Secret Key(appSecret)'


Here is a demo to show how to run this plugin
[Example](./example/README.md)
16 changes: 16 additions & 0 deletions plugins/twitterPrimusPlugin/example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
GAME_API_KEY=

# Worker information
WORKER_ID=
WORKER_NAME=
WORKER_DESC=

# Primus SDK
APP_ID=
APP_SECRET=

# Twitter account
TWITTER_USER_NAME=
TWITTER_PASSWORD=
TWITTER_EMAIL=
TWITTER_2FA_SECRET=#NOT NECESSARY, Only need for twitter 2FA
51 changes: 51 additions & 0 deletions plugins/twitterPrimusPlugin/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# twitterPrimusPlugin Demo
## Overview
This is a demo project that demonstrates how to use the `twitterPrimusPlugin` to generate a zkTlS attestation for you function(action).

## How to run

### Install
#### Install dependencies in twitterPrimusPlugin
```shell
npm install
```
#### Install dependencies in example
run `npm install` to install dependencies.
```shell
cd example
npm install
```

### Configuration
1. Create a `.env` file in the root directory using the `.env.example` as template.
```shell
cp .env.example .env
```

2. Set the environment variables in the `.env` file.
```dotenv
# Get from https://console.game.virtuals.io/
GAME_API_KEY=

# Worker information
WORKER_ID=<worker id>
WORKER_NAME=<worker name>
WORKER_DESC=<worker desc>

# Primus SDK
# APP_ID and APP_SECRET get from https://dev.primuslabs.xyz/myDevelopment/myProjects . Create a new Backend project and save your 'Application ID(APP_ID)' and 'Secret Key(APP_SECRET)'
# Docs for Primus SDK : https://docs.primuslabs.xyz/data-verification/core-sdk/overview
APP_ID=
APP_SECRET=

# Twitter account
TWITTER_USER_NAME=
TWITTER_PASSWORD=
TWITTER_EMAIL=
TWITTER_2FA_SECRET=#NOT NECESSARY, Only need for twitter 2FA
```

### Run
```shell
npm run start
```
14 changes: 14 additions & 0 deletions plugins/twitterPrimusPlugin/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "example",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "ts-node src/index.ts"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"dotenv": "^16.4.7"
}
}
64 changes: 64 additions & 0 deletions plugins/twitterPrimusPlugin/example/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {GameAgent, LLMModel} from "@virtuals-protocol/game";
import TwitterPrimusPlugin from "../../src";

import dotenv from "dotenv";

dotenv.config();

(async () => {
// Create a worker with the functions
const twitterPlugin = new TwitterPrimusPlugin();
// Check env has set
if (!process.env.APP_ID || !process.env.APP_SECRET || !process.env.TWITTER_USER_NAME || !process.env.TWITTER_PASSWORD || !process.env.TWITTER_EMAIL) {
throw new Error("Missing environment variables");
}
await twitterPlugin.init({
id: process.env.WORKER_ID || "",
name: process.env.WORKER_NAME || "",
description: process.env.WORKER_DESC || "",

appId: process.env.APP_ID || "",
appSecret: process.env.APP_SECRET || "",

username: process.env.TWITTER_USER_NAME || "",
password: process.env.TWITTER_PASSWORD || "",
email: process.env.TWITTER_EMAIL || "",
//NOT NECESSARY
twitter2faSecret: process.env.TWITTER_2FA_SECRET || "",
});

const gameApiKey = process.env.GAME_API_KEY;

if(!gameApiKey){
throw new Error("Missing environment variables");
}
// Create an agent with the worker
const agent = new GameAgent(gameApiKey, {
name: "Twitter Primus Bot",
goal: "Verify actions",
description: "Get btc price and post tweet by zktls",
workers: [
twitterPlugin.getWorker({}),
],
llmModel: LLMModel.DeepSeek_R1,
getAgentState: async () => {
return {
username: "twitter_primus_bot"
};
},
});

agent.setLogger((agent, message) => {
console.log(`-----[${agent.name}]-----`);
console.log(message);
console.log("\n");
});

await agent.init();

while (true) {
await agent.step({
verbose: true,
});
}
})();
16 changes: 16 additions & 0 deletions plugins/twitterPrimusPlugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@virtuals-protocol/game-twitter-primus-plugin",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@virtuals-protocol/game": "^0.1.7",
"@primuslabs/zktls-core-sdk": "^0.1.1",
"agent-twitter-client": "0.0.18"
},
"author": "dev@primuslabs.xyz",
"license": "ISC",
"description": ""
}
Loading